Skip to contents

This workflow interprets one molecular layer measured on canonical biological samples. Registered strategies cover independent cross-sectional samples and independent destructive-sampling time courses. Repeated-subject time courses require their own subject-aware strategy and are not silently treated as independent. Every result remains exploratory.

The workflow separates five actions:

  1. associate_metadata() stores raw, adjusted, and resampled evidence.
  2. plot() renders the stored decision surface without changing it.
  3. propose_component() ranks only the predeclared effect and may compute a search-aware permutation null.
  4. assess_component_identifiability() repeats the complete search under design-preserving resampling and aligns every replicate to the frozen discovery basis.
  5. confirm_component() records a separate analyst decision and rationale.

Synthetic worked example

The example demonstrates software behavior with synthetic coordinates. It is not biological evidence and does not calibrate a universal decision rule.

primary <- sprintf("sample_%02d", 1:8)
assay_ids <- sprintf("rna_%02d", 1:8)
std <- StateTransitionData(
  experiments = list(
    rna = SummarizedExperiment::SummarizedExperiment(
      assays = list(logcounts = matrix(
        seq_len(32L),
        nrow = 4L,
        dimnames = list(sprintf("gene_%02d", 1:4), assay_ids)
      ))
    )
  ),
  colData = S4Vectors::DataFrame(
    condition = factor(
      rep(c("control", "treatment"), each = 4L),
      levels = c("control", "treatment")
    ),
    severity = c(1, 2, 2, 4, 5, 6, 7, 8),
    state = ordered(
      c("early", "early", "middle", "middle",
        "late", "late", "late", "end"),
      levels = c("early", "middle", "late", "end")
    ),
    subtype = factor(rep(c("A", "B", "C", "D"), each = 2L)),
    batch = rep(c("run_1", "run_2"), 4L),
    mouse_id = sprintf("mouse_%02d", 1:8),
    row.names = primary
  ),
  sampleMap = S4Vectors::DataFrame(
    assay = factor(rep("rna", 8L), levels = "rna"),
    primary = primary,
    colname = assay_ids
  )
)
std <- declare_sampling_design(std, cross_sectional())
std_metadata <- S4Vectors::metadata(std)
std_metadata$stage1 <- DecompositionResult(
  V_star = c(1, 0, 0, 0),
  sigma = 1,
  coords = list(1:8),
  V_k = diag(4)[, 1:2, drop = FALSE],
  sigma_k = matrix(c(2, 1), nrow = 1L),
  coords_k = list(cbind(
    PC1 = c(4, 3, 2, 1, 1, 2, 3, 4),
    PC2 = 1:8
  )),
  k = 2L
)
S4Vectors::metadata(std) <- std_metadata

Declare intent, then build the atlas

The specification owns the target, direction, nuisance fields, and run identity. Numerical spacing is explicit here because severity is declared as continuous. Ordered factor labels instead use their declared level order and never imply unequal spacing.

specification <- analysis_specification(
  id = "synthetic-severity",
  target_field = "severity",
  target_type = "continuous",
  continuous_direction = "increasing",
  nuisance_fields = "batch"
)

atlas <- associate_metadata(
  std,
  specification = specification,
  non_analytical_fields = "mouse_id",
  dataset_id = "synthetic-cross-sectional-control",
  n_resamples = 49L,
  seed = 7001L
)
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : pseudoinverse used at 1
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : neighborhood radius 2
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : reciprocal condition number 0
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : There are other near singularities as well. 4
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : pseudoinverse used at 1
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : neighborhood radius 2
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : reciprocal condition
#> number 0
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : There are other near
#> singularities as well. 1
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : pseudoinverse used at 1
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : neighborhood radius 2
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : reciprocal condition number 0
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : There are other near singularities as well. 4
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : pseudoinverse used at 1
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : neighborhood radius 2
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : reciprocal condition
#> number 0
#> Warning in predLoess(object$y, object$x, newx = if (is.null(newdata)) object$x
#> else if (is.data.frame(newdata))
#> as.matrix(model.frame(delete.response(terms(object)), : There are other near
#> singularities as well. 1
atlas_associations(atlas)
#>    metadata_field component component_label                        estimand
#> 1       condition         1             PC1            signed-rank-biserial
#> 2       condition         2             PC2            signed-rank-biserial
#> 3        severity         1             PC1                        spearman
#> 4        severity         2             PC2                        spearman
#> 5        severity         1             PC1 adjusted-rank-score-association
#> 6        severity         2             PC2 adjusted-rank-score-association
#> 7           state         1             PC1                   kendall-tau-b
#> 8           state         2             PC2                   kendall-tau-b
#> 9         subtype         1             PC1  kruskal-wallis-epsilon-squared
#> 10        subtype         2             PC2  kruskal-wallis-epsilon-squared
#> 11          batch         1             PC1            signed-rank-biserial
#> 12          batch         2             PC2            signed-rank-biserial
#>       estimate effect_magnitude reference_level comparison_level n_available
#> 1   0.00000000       0.00000000         control        treatment           8
#> 2   1.00000000       1.00000000         control        treatment           8
#> 3   0.02454403       0.02454403            <NA>             <NA>           8
#> 4   0.99402980       0.99402980            <NA>             <NA>           8
#> 5   0.02552383       0.02552383            <NA>             <NA>           8
#> 6   0.99542929       0.99542929            <NA>             <NA>           8
#> 7  -0.04256283       0.04256283            <NA>             <NA>           8
#> 8   0.90632697       0.90632697            <NA>             <NA>           8
#> 9   0.65000000       0.65000000            <NA>             <NA>           8
#> 10  0.91666667       0.91666667            <NA>             <NA>           8
#> 11  0.00000000       0.00000000           run_1            run_2           8
#> 12  0.25000000       0.25000000           run_1            run_2           8
#>    n_missing n_score_ties n_target_ties evidence_variant proposal_eligible
#> 1          0            8            NA       unadjusted              TRUE
#> 2          0            0            NA       unadjusted              TRUE
#> 3          0            8             2       unadjusted              TRUE
#> 4          0            0             2       unadjusted              TRUE
#> 5          0            8             2         adjusted              TRUE
#> 6          0            0             2         adjusted              TRUE
#> 7          0            8             7       unadjusted              TRUE
#> 8          0            0             7       unadjusted              TRUE
#> 9          0            8             8       unadjusted             FALSE
#> 10         0            0             8       unadjusted             FALSE
#> 11         0            8            NA       unadjusted              TRUE
#> 12         0            0            NA       unadjusted              TRUE
#>    nuisance_fields
#> 1                 
#> 2                 
#> 3                 
#> 4                 
#> 5            batch
#> 6            batch
#> 7                 
#> 8                 
#> 9                 
#> 10                
#> 11                
#> 12                
#>                                                       cohort_digest
#> 1  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 2  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 3  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 4  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 5  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 6  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 7  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 8  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 9  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 10 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 11 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 12 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#>                                                       design_digest
#> 1                                                              <NA>
#> 2                                                              <NA>
#> 3                                                              <NA>
#> 4                                                              <NA>
#> 5  9d176423b6495def65761f853c969617e669012b0cc0870bc1f29cbc4d8ac362
#> 6  9d176423b6495def65761f853c969617e669012b0cc0870bc1f29cbc4d8ac362
#> 7                                                              <NA>
#> 8                                                              <NA>
#> 9                                                              <NA>
#> 10                                                             <NA>
#> 11                                                             <NA>
#> 12                                                             <NA>
#>                          diagnostic      p_value      q_value effect_conf_low
#> 1                                   1.000000e+00 1.000000e+00      -0.8437500
#> 2                                   3.038282e-02 6.076564e-02       1.0000000
#> 3  possible-nonmonotone-association 9.539984e-01 9.539984e-01      -0.9087758
#> 4                                   5.296154e-07 1.059231e-06       0.8268956
#> 5                                   9.521636e-01 9.521636e-01      -0.9732012
#> 6                                   2.379030e-07 4.758061e-07       0.9394658
#> 7  possible-nonmonotone-association 8.940523e-01 8.940523e-01      -0.8261047
#> 8                                   2.905435e-03 5.810870e-03       0.8647617
#> 9                                   1.327784e-01 1.666326e-01       0.6701923
#> 10                                  8.331631e-02 1.666326e-01       0.9216867
#> 11                                  1.000000e+00 1.000000e+00      -0.9218750
#> 12                                  6.650055e-01 1.000000e+00      -0.9687500
#>    effect_conf_high n_resamples resample_failures
#> 1         0.9375000          49                 0
#> 2         1.0000000          49                 0
#> 3         0.6445467          49                 0
#> 4         1.0000000          49                 0
#> 5         0.8122143          49                 0
#> 6         1.0000000          49                 0
#> 7         0.1304348          49                 0
#> 8         0.9888833          49                 0
#> 9         0.9775641          49                 0
#> 10        0.9945988          49                 0
#> 11        0.8593750          49                 0
#> 12        1.0000000          49                 0
#>                       resampling_method
#> 1  stratified-biological-unit-bootstrap
#> 2  stratified-biological-unit-bootstrap
#> 3  stratified-biological-unit-bootstrap
#> 4  stratified-biological-unit-bootstrap
#> 5  stratified-biological-unit-bootstrap
#> 6  stratified-biological-unit-bootstrap
#> 7  stratified-biological-unit-bootstrap
#> 8  stratified-biological-unit-bootstrap
#> 9  stratified-biological-unit-bootstrap
#> 10 stratified-biological-unit-bootstrap
#> 11 stratified-biological-unit-bootstrap
#> 12 stratified-biological-unit-bootstrap
#>                                              resampling_plan_digest
#> 1  17f55a77b11a359503abae6eb0560dbcddb9926c7f33942afcbe97ad668281fb
#> 2  17f55a77b11a359503abae6eb0560dbcddb9926c7f33942afcbe97ad668281fb
#> 3  db8db0c4d2f793a4ebb2e670a02bd2df46ceeab0b35ccbd4e133cb9783a986da
#> 4  db8db0c4d2f793a4ebb2e670a02bd2df46ceeab0b35ccbd4e133cb9783a986da
#> 5  db8db0c4d2f793a4ebb2e670a02bd2df46ceeab0b35ccbd4e133cb9783a986da
#> 6  db8db0c4d2f793a4ebb2e670a02bd2df46ceeab0b35ccbd4e133cb9783a986da
#> 7  4dd69435f02789b23320749dfe9a29951b5d2a00bc098dee11fb0741d35c24e1
#> 8  4dd69435f02789b23320749dfe9a29951b5d2a00bc098dee11fb0741d35c24e1
#> 9  a42b0efc9baaa92c85a6dc2773e725b8312b5986d841d8c05bc9bae7eb51a707
#> 10 a42b0efc9baaa92c85a6dc2773e725b8312b5986d841d8c05bc9bae7eb51a707
#> 11 34ee11a603b3526224443611b14a985e40a246bc1e886fd61d8befa903d0b6f6
#> 12 34ee11a603b3526224443611b14a985e40a246bc1e886fd61d8befa903d0b6f6
#>               evidence_status
#> 1  estimable-exploratory-only
#> 2  estimable-exploratory-only
#> 3  estimable-exploratory-only
#> 4  estimable-exploratory-only
#> 5  estimable-exploratory-only
#> 6  estimable-exploratory-only
#> 7  estimable-exploratory-only
#> 8  estimable-exploratory-only
#> 9  estimable-exploratory-only
#> 10 estimable-exploratory-only
#> 11 estimable-exploratory-only
#> 12 estimable-exploratory-only
atlas_exclusions(atlas)
#>   metadata_field                  reason
#> 1       mouse_id declared-non-analytical
atlas_evidence_contract(atlas)
#> $version
#> [1] "cross-sectional-v1"
#> 
#> $sampling_design
#> [1] "cross_sectional"
#> 
#> $row_counts
#> associations observations   exclusions 
#>           12           80            1 
#> 
#> $digests
#>                                                       associations 
#> "aa086c69d980902d418437ac2de6a89bdcdb80050575562c23f74beba474df49" 
#>                                                       observations 
#> "8ae1356309fcff374967c3693b3d903cd45205bb1aef19c5a9af7590735a3e53" 
#>                                                         exclusions 
#> "d7f577eceee6b36862c85beb86a84f7f3f276afd081f6407e645817a7a8a55bf" 
#>                                                     cohort_members 
#> "5f174ac88066d5a13b0fa1aa7908dadfaa73948a754bcc35d3b24ede40349ff4" 
#>                                                   display_evidence 
#> "920e66e8ef26e75bea457e9ebb9e803c1a925be13dbbf4a8b0f1451f3cc34d94" 
#> 
#> $cohorts
#>    metadata_field component evidence_variant
#> 1       condition         1       unadjusted
#> 2       condition         2       unadjusted
#> 3        severity         1       unadjusted
#> 4        severity         2       unadjusted
#> 5        severity         1         adjusted
#> 6        severity         2         adjusted
#> 7           state         1       unadjusted
#> 8           state         2       unadjusted
#> 9         subtype         1       unadjusted
#> 10        subtype         2       unadjusted
#> 11          batch         1       unadjusted
#> 12          batch         2       unadjusted
#>                                                       cohort_digest n_available
#> 1  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 2  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 3  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 4  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 5  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 6  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 7  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 8  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 9  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 10 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 11 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 12 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#>    n_missing
#> 1          0
#> 2          0
#> 3          0
#> 4          0
#> 5          0
#> 6          0
#> 7          0
#> 8          0
#> 9          0
#> 10         0
#> 11         0
#> 12         0
#> 
#> $cohort_members
#>    metadata_field component evidence_variant primary_sample included
#> 1       condition         1       unadjusted      sample_01     TRUE
#> 2       condition         1       unadjusted      sample_02     TRUE
#> 3       condition         1       unadjusted      sample_03     TRUE
#> 4       condition         1       unadjusted      sample_04     TRUE
#> 5       condition         1       unadjusted      sample_05     TRUE
#> 6       condition         1       unadjusted      sample_06     TRUE
#> 7       condition         1       unadjusted      sample_07     TRUE
#> 8       condition         1       unadjusted      sample_08     TRUE
#> 9       condition         2       unadjusted      sample_01     TRUE
#> 10      condition         2       unadjusted      sample_02     TRUE
#> 11      condition         2       unadjusted      sample_03     TRUE
#> 12      condition         2       unadjusted      sample_04     TRUE
#> 13      condition         2       unadjusted      sample_05     TRUE
#> 14      condition         2       unadjusted      sample_06     TRUE
#> 15      condition         2       unadjusted      sample_07     TRUE
#> 16      condition         2       unadjusted      sample_08     TRUE
#> 17       severity         1       unadjusted      sample_01     TRUE
#> 18       severity         1       unadjusted      sample_02     TRUE
#> 19       severity         1       unadjusted      sample_03     TRUE
#> 20       severity         1       unadjusted      sample_04     TRUE
#> 21       severity         1       unadjusted      sample_05     TRUE
#> 22       severity         1       unadjusted      sample_06     TRUE
#> 23       severity         1       unadjusted      sample_07     TRUE
#> 24       severity         1       unadjusted      sample_08     TRUE
#> 25       severity         2       unadjusted      sample_01     TRUE
#> 26       severity         2       unadjusted      sample_02     TRUE
#> 27       severity         2       unadjusted      sample_03     TRUE
#> 28       severity         2       unadjusted      sample_04     TRUE
#> 29       severity         2       unadjusted      sample_05     TRUE
#> 30       severity         2       unadjusted      sample_06     TRUE
#> 31       severity         2       unadjusted      sample_07     TRUE
#> 32       severity         2       unadjusted      sample_08     TRUE
#> 33       severity         1         adjusted      sample_01     TRUE
#> 34       severity         1         adjusted      sample_02     TRUE
#> 35       severity         1         adjusted      sample_03     TRUE
#> 36       severity         1         adjusted      sample_04     TRUE
#> 37       severity         1         adjusted      sample_05     TRUE
#> 38       severity         1         adjusted      sample_06     TRUE
#> 39       severity         1         adjusted      sample_07     TRUE
#> 40       severity         1         adjusted      sample_08     TRUE
#> 41       severity         2         adjusted      sample_01     TRUE
#> 42       severity         2         adjusted      sample_02     TRUE
#> 43       severity         2         adjusted      sample_03     TRUE
#> 44       severity         2         adjusted      sample_04     TRUE
#> 45       severity         2         adjusted      sample_05     TRUE
#> 46       severity         2         adjusted      sample_06     TRUE
#> 47       severity         2         adjusted      sample_07     TRUE
#> 48       severity         2         adjusted      sample_08     TRUE
#> 49          state         1       unadjusted      sample_01     TRUE
#> 50          state         1       unadjusted      sample_02     TRUE
#> 51          state         1       unadjusted      sample_03     TRUE
#> 52          state         1       unadjusted      sample_04     TRUE
#> 53          state         1       unadjusted      sample_05     TRUE
#> 54          state         1       unadjusted      sample_06     TRUE
#> 55          state         1       unadjusted      sample_07     TRUE
#> 56          state         1       unadjusted      sample_08     TRUE
#> 57          state         2       unadjusted      sample_01     TRUE
#> 58          state         2       unadjusted      sample_02     TRUE
#> 59          state         2       unadjusted      sample_03     TRUE
#> 60          state         2       unadjusted      sample_04     TRUE
#> 61          state         2       unadjusted      sample_05     TRUE
#> 62          state         2       unadjusted      sample_06     TRUE
#> 63          state         2       unadjusted      sample_07     TRUE
#> 64          state         2       unadjusted      sample_08     TRUE
#> 65        subtype         1       unadjusted      sample_01     TRUE
#> 66        subtype         1       unadjusted      sample_02     TRUE
#> 67        subtype         1       unadjusted      sample_03     TRUE
#> 68        subtype         1       unadjusted      sample_04     TRUE
#> 69        subtype         1       unadjusted      sample_05     TRUE
#> 70        subtype         1       unadjusted      sample_06     TRUE
#> 71        subtype         1       unadjusted      sample_07     TRUE
#> 72        subtype         1       unadjusted      sample_08     TRUE
#> 73        subtype         2       unadjusted      sample_01     TRUE
#> 74        subtype         2       unadjusted      sample_02     TRUE
#> 75        subtype         2       unadjusted      sample_03     TRUE
#> 76        subtype         2       unadjusted      sample_04     TRUE
#> 77        subtype         2       unadjusted      sample_05     TRUE
#> 78        subtype         2       unadjusted      sample_06     TRUE
#> 79        subtype         2       unadjusted      sample_07     TRUE
#> 80        subtype         2       unadjusted      sample_08     TRUE
#> 81          batch         1       unadjusted      sample_01     TRUE
#> 82          batch         1       unadjusted      sample_02     TRUE
#> 83          batch         1       unadjusted      sample_03     TRUE
#> 84          batch         1       unadjusted      sample_04     TRUE
#> 85          batch         1       unadjusted      sample_05     TRUE
#> 86          batch         1       unadjusted      sample_06     TRUE
#> 87          batch         1       unadjusted      sample_07     TRUE
#> 88          batch         1       unadjusted      sample_08     TRUE
#> 89          batch         2       unadjusted      sample_01     TRUE
#> 90          batch         2       unadjusted      sample_02     TRUE
#> 91          batch         2       unadjusted      sample_03     TRUE
#> 92          batch         2       unadjusted      sample_04     TRUE
#> 93          batch         2       unadjusted      sample_05     TRUE
#> 94          batch         2       unadjusted      sample_06     TRUE
#> 95          batch         2       unadjusted      sample_07     TRUE
#> 96          batch         2       unadjusted      sample_08     TRUE
plot(atlas)

The table keeps unadjusted and adjusted rows separate. Each row records its complete-cohort and design digests, missingness, tied score and target counts, bootstrap interval, failed-resample count, raw p-value, and Holm-adjusted q-value. The correction family is the declared component set within each metadata field and evidence variant. Bootstrap draws preserve discrete target and nuisance-cell counts and resample complete independent biological units rather than features or technical replicates.

Raw points, a black monotone-constrained fit, and a red flexible smoother expose the predeclared monotone relationship. A reversal in level-wise medians adds a possible-nonmonotone-association warning. The warning and smoother are descriptive and cannot rerank components.

The evidence summary is the inspection-friendly view of the package-owned internal interpretation contract behind the atlas. It records normalized row counts, exact available-case cohort membership, and deterministic table and cohort-membership digests. Atlas validity checks those values before proposal, permutation, plotting, or serialization consumers can use the evidence. Registered association strategies still calculate the scientific estimands; they do not assemble or validate the surrounding evidence.

One resampling contract, three scientific adapters

Bootstrap and permutation work share one internal policy for deterministic seeds, immutable plan digests, requested and completed counts, failure accounting, and typed unavailable outcomes. The requested count is fixed before refitting. A failed eligible refit remains in that denominator and is never silently replaced with another draw.

The shared mechanics do not erase experimental design. Cross-sectional analyses resample independent biological observations, destructive time courses resample within condition-by-time cells, and repeated designs resample complete subject trajectories. Duplicate trajectory draws receive new replicate-subject identifiers so they remain statistically distinct copies of one source trajectory. Unsupported exchangeability or insufficient distinct assignments produces a typed abstention rather than a fallback sampling rule.

Produce an exploratory proposal

proposal <- propose_component(
  atlas,
  n_permutations = 49L,
  seed = 8001L
)
proposal_ranking(proposal)
#>   metadata_field component component_label                        estimand
#> 1       severity         2             PC2 adjusted-rank-score-association
#> 2       severity         1             PC1 adjusted-rank-score-association
#>     estimate effect_magnitude reference_level comparison_level n_available
#> 1 0.99542929       0.99542929            <NA>             <NA>           8
#> 2 0.02552383       0.02552383            <NA>             <NA>           8
#>   n_missing n_score_ties n_target_ties evidence_variant proposal_eligible
#> 1         0            0             2         adjusted              TRUE
#> 2         0            8             2         adjusted              TRUE
#>   nuisance_fields
#> 1           batch
#> 2           batch
#>                                                      cohort_digest
#> 1 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#> 2 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd
#>                                                      design_digest diagnostic
#> 1 9d176423b6495def65761f853c969617e669012b0cc0870bc1f29cbc4d8ac362           
#> 2 9d176423b6495def65761f853c969617e669012b0cc0870bc1f29cbc4d8ac362           
#>        p_value      q_value effect_conf_low effect_conf_high n_resamples
#> 1 2.379030e-07 4.758061e-07       0.9394658        1.0000000          49
#> 2 9.521636e-01 9.521636e-01      -0.9732012        0.8122143          49
#>   resample_failures                    resampling_method
#> 1                 0 stratified-biological-unit-bootstrap
#> 2                 0 stratified-biological-unit-bootstrap
#>                                             resampling_plan_digest
#> 1 db8db0c4d2f793a4ebb2e670a02bd2df46ceeab0b35ccbd4e133cb9783a986da
#> 2 db8db0c4d2f793a4ebb2e670a02bd2df46ceeab0b35ccbd4e133cb9783a986da
#>              evidence_status proposal_rank
#> 1 estimable-exploratory-only             1
#> 2 estimable-exploratory-only             2
proposal_provenance(proposal)
#> $association_strategy
#> [1] "cross-sectional-binary-signed-rank-biserial-v1"
#> [2] "cross-sectional-continuous-spearman-v1"        
#> [3] "cross-sectional-ordered-kendall-tau-b-v1"      
#> 
#> $package_version
#> [1] "0.3.0"
#> 
#> $sampling_design
#> [1] "cross_sectional"
#> 
#> $layer
#> [1] "rna"
#> 
#> $input_digest
#> [1] "3d52d2e33dfcc89e909f9957bfdc186f0f0850c94ed15a03bb4a0ebbcbb6c0d3"
#> 
#> $state_space_digest
#> [1] "a813a78c92f483ac66eaf5bd9c64dcc8bfb7c7c1428e72874545eb70dbfd7333"
#> 
#> $dataset_id
#> [1] "synthetic-cross-sectional-control"
#> 
#> $exchangeability
#> [1] "independent"
#> 
#> $multiplicity
#> $multiplicity$method
#> [1] "holm"
#> 
#> $multiplicity$method_label
#> [1] "Holm"
#> 
#> $multiplicity$family_columns
#> [1] "metadata_field"   "evidence_variant"
#> 
#> $multiplicity$family_description
#> [1] "declared components within each metadata field and evidence variant"
#> 
#> 
#> $interpretation_module
#> [1] "cross-sectional-v1"
#> 
#> $visual_evidence
#> $visual_evidence$monotone_fit
#>                metadata_field component_label metadata_numeric monotone_fitted
#> severity.PC1.1       severity             PC1                1        2.100000
#> severity.PC1.2       severity             PC1                2        2.100000
#> severity.PC1.3       severity             PC1                4        2.100000
#> severity.PC1.4       severity             PC1                5        2.100000
#> severity.PC1.5       severity             PC1                6        2.100000
#> severity.PC1.6       severity             PC1                7        3.000000
#> severity.PC1.7       severity             PC1                8        4.000000
#> severity.PC2.1       severity             PC2                1        1.000000
#> severity.PC2.2       severity             PC2                2        2.500000
#> severity.PC2.3       severity             PC2                4        4.000000
#> severity.PC2.4       severity             PC2                5        5.000000
#> severity.PC2.5       severity             PC2                6        6.000000
#> severity.PC2.6       severity             PC2                7        7.000000
#> severity.PC2.7       severity             PC2                8        8.000000
#> state.PC1.1             state             PC1                1        2.333333
#> state.PC1.2             state             PC1                2        2.333333
#> state.PC1.3             state             PC1                3        2.333333
#> state.PC1.4             state             PC1                4        4.000000
#> state.PC2.1             state             PC2                1        1.500000
#> state.PC2.2             state             PC2                2        3.500000
#> state.PC2.3             state             PC2                3        6.000000
#> state.PC2.4             state             PC2                4        8.000000
#> 
#> $visual_evidence$flexible_fit
#>                metadata_field component_label metadata_numeric flexible_fitted
#> severity.PC1.1       severity             PC1                1       4.0000000
#> severity.PC1.2       severity             PC1                2       2.5000000
#> severity.PC1.3       severity             PC1                4       0.9333008
#> severity.PC1.4       severity             PC1                5       1.1300477
#> severity.PC1.5       severity             PC1                6       1.9172797
#> severity.PC1.6       severity             PC1                7       2.8787428
#> severity.PC1.7       severity             PC1                8       4.0618107
#> severity.PC2.1       severity             PC2                1       1.0501147
#> severity.PC2.2       severity             PC2                2       2.4295503
#> severity.PC2.3       severity             PC2                4       4.0222331
#> severity.PC2.4       severity             PC2                5       5.0000000
#> severity.PC2.5       severity             PC2                6       6.0000000
#> severity.PC2.6       severity             PC2                7       7.0000000
#> severity.PC2.7       severity             PC2                8       8.0000000
#> state.PC1.1             state             PC1                1       3.5000000
#> state.PC1.2             state             PC1                2       1.5000000
#> state.PC1.3             state             PC1                3       2.0000000
#> state.PC1.4             state             PC1                4       4.0000000
#> state.PC2.1             state             PC2                1       1.5000000
#> state.PC2.2             state             PC2                2       3.5000000
#> state.PC2.3             state             PC2                3       6.0000000
#> state.PC2.4             state             PC2                4       8.0000000
#> 
#> 
#> $analysis_specification_id
#> [1] "synthetic-severity"
#> 
#> $analysis_specification_digest
#> [1] "dedf2403efa8db394d938849f485505df43e2fdaee6e9fcef6ac8a66203d38d4"
#> 
#> $target_field
#> [1] "severity"
#> 
#> $target_type
#> [1] "continuous"
#> 
#> $reference_level
#> character(0)
#> 
#> $comparison_level
#> character(0)
#> 
#> $ordered_levels
#> character(0)
#> 
#> $continuous_direction
#> [1] "increasing"
#> 
#> $nuisance_fields
#> [1] "batch"
#> 
#> $nuisance_values
#> $nuisance_values$batch
#> sample_01 sample_02 sample_03 sample_04 sample_05 sample_06 sample_07 sample_08 
#>   "run_1"   "run_2"   "run_1"   "run_2"   "run_1"   "run_2"   "run_1"   "run_2" 
#> 
#> 
#> $orientation_anchor
#> character(0)
#> 
#> $claim_intent
#> [1] "exploratory"
#> 
#> $evidence_contract
#> $evidence_contract$version
#> [1] "cross-sectional-v1"
#> 
#> $evidence_contract$sampling_design
#> [1] "cross_sectional"
#> 
#> $evidence_contract$row_counts
#> associations observations   exclusions 
#>           12           80            1 
#> 
#> $evidence_contract$digests
#>                                                       associations 
#> "aa086c69d980902d418437ac2de6a89bdcdb80050575562c23f74beba474df49" 
#>                                                       observations 
#> "8ae1356309fcff374967c3693b3d903cd45205bb1aef19c5a9af7590735a3e53" 
#>                                                         exclusions 
#> "d7f577eceee6b36862c85beb86a84f7f3f276afd081f6407e645817a7a8a55bf" 
#>                                                     cohort_members 
#> "5f174ac88066d5a13b0fa1aa7908dadfaa73948a754bcc35d3b24ede40349ff4" 
#>                                                   display_evidence 
#> "920e66e8ef26e75bea457e9ebb9e803c1a925be13dbbf4a8b0f1451f3cc34d94" 
#> 
#> $evidence_contract$cohorts
#>    metadata_field component evidence_variant
#> 1       condition         1       unadjusted
#> 2       condition         2       unadjusted
#> 3        severity         1       unadjusted
#> 4        severity         2       unadjusted
#> 5        severity         1         adjusted
#> 6        severity         2         adjusted
#> 7           state         1       unadjusted
#> 8           state         2       unadjusted
#> 9         subtype         1       unadjusted
#> 10        subtype         2       unadjusted
#> 11          batch         1       unadjusted
#> 12          batch         2       unadjusted
#>                                                       cohort_digest n_available
#> 1  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 2  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 3  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 4  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 5  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 6  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 7  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 8  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 9  d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 10 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 11 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#> 12 d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd           8
#>    n_missing
#> 1          0
#> 2          0
#> 3          0
#> 4          0
#> 5          0
#> 6          0
#> 7          0
#> 8          0
#> 9          0
#> 10         0
#> 11         0
#> 12         0
#> 
#> $evidence_contract$cohort_members
#>    metadata_field component evidence_variant primary_sample included
#> 1       condition         1       unadjusted      sample_01     TRUE
#> 2       condition         1       unadjusted      sample_02     TRUE
#> 3       condition         1       unadjusted      sample_03     TRUE
#> 4       condition         1       unadjusted      sample_04     TRUE
#> 5       condition         1       unadjusted      sample_05     TRUE
#> 6       condition         1       unadjusted      sample_06     TRUE
#> 7       condition         1       unadjusted      sample_07     TRUE
#> 8       condition         1       unadjusted      sample_08     TRUE
#> 9       condition         2       unadjusted      sample_01     TRUE
#> 10      condition         2       unadjusted      sample_02     TRUE
#> 11      condition         2       unadjusted      sample_03     TRUE
#> 12      condition         2       unadjusted      sample_04     TRUE
#> 13      condition         2       unadjusted      sample_05     TRUE
#> 14      condition         2       unadjusted      sample_06     TRUE
#> 15      condition         2       unadjusted      sample_07     TRUE
#> 16      condition         2       unadjusted      sample_08     TRUE
#> 17       severity         1       unadjusted      sample_01     TRUE
#> 18       severity         1       unadjusted      sample_02     TRUE
#> 19       severity         1       unadjusted      sample_03     TRUE
#> 20       severity         1       unadjusted      sample_04     TRUE
#> 21       severity         1       unadjusted      sample_05     TRUE
#> 22       severity         1       unadjusted      sample_06     TRUE
#> 23       severity         1       unadjusted      sample_07     TRUE
#> 24       severity         1       unadjusted      sample_08     TRUE
#> 25       severity         2       unadjusted      sample_01     TRUE
#> 26       severity         2       unadjusted      sample_02     TRUE
#> 27       severity         2       unadjusted      sample_03     TRUE
#> 28       severity         2       unadjusted      sample_04     TRUE
#> 29       severity         2       unadjusted      sample_05     TRUE
#> 30       severity         2       unadjusted      sample_06     TRUE
#> 31       severity         2       unadjusted      sample_07     TRUE
#> 32       severity         2       unadjusted      sample_08     TRUE
#> 33       severity         1         adjusted      sample_01     TRUE
#> 34       severity         1         adjusted      sample_02     TRUE
#> 35       severity         1         adjusted      sample_03     TRUE
#> 36       severity         1         adjusted      sample_04     TRUE
#> 37       severity         1         adjusted      sample_05     TRUE
#> 38       severity         1         adjusted      sample_06     TRUE
#> 39       severity         1         adjusted      sample_07     TRUE
#> 40       severity         1         adjusted      sample_08     TRUE
#> 41       severity         2         adjusted      sample_01     TRUE
#> 42       severity         2         adjusted      sample_02     TRUE
#> 43       severity         2         adjusted      sample_03     TRUE
#> 44       severity         2         adjusted      sample_04     TRUE
#> 45       severity         2         adjusted      sample_05     TRUE
#> 46       severity         2         adjusted      sample_06     TRUE
#> 47       severity         2         adjusted      sample_07     TRUE
#> 48       severity         2         adjusted      sample_08     TRUE
#> 49          state         1       unadjusted      sample_01     TRUE
#> 50          state         1       unadjusted      sample_02     TRUE
#> 51          state         1       unadjusted      sample_03     TRUE
#> 52          state         1       unadjusted      sample_04     TRUE
#> 53          state         1       unadjusted      sample_05     TRUE
#> 54          state         1       unadjusted      sample_06     TRUE
#> 55          state         1       unadjusted      sample_07     TRUE
#> 56          state         1       unadjusted      sample_08     TRUE
#> 57          state         2       unadjusted      sample_01     TRUE
#> 58          state         2       unadjusted      sample_02     TRUE
#> 59          state         2       unadjusted      sample_03     TRUE
#> 60          state         2       unadjusted      sample_04     TRUE
#> 61          state         2       unadjusted      sample_05     TRUE
#> 62          state         2       unadjusted      sample_06     TRUE
#> 63          state         2       unadjusted      sample_07     TRUE
#> 64          state         2       unadjusted      sample_08     TRUE
#> 65        subtype         1       unadjusted      sample_01     TRUE
#> 66        subtype         1       unadjusted      sample_02     TRUE
#> 67        subtype         1       unadjusted      sample_03     TRUE
#> 68        subtype         1       unadjusted      sample_04     TRUE
#> 69        subtype         1       unadjusted      sample_05     TRUE
#> 70        subtype         1       unadjusted      sample_06     TRUE
#> 71        subtype         1       unadjusted      sample_07     TRUE
#> 72        subtype         1       unadjusted      sample_08     TRUE
#> 73        subtype         2       unadjusted      sample_01     TRUE
#> 74        subtype         2       unadjusted      sample_02     TRUE
#> 75        subtype         2       unadjusted      sample_03     TRUE
#> 76        subtype         2       unadjusted      sample_04     TRUE
#> 77        subtype         2       unadjusted      sample_05     TRUE
#> 78        subtype         2       unadjusted      sample_06     TRUE
#> 79        subtype         2       unadjusted      sample_07     TRUE
#> 80        subtype         2       unadjusted      sample_08     TRUE
#> 81          batch         1       unadjusted      sample_01     TRUE
#> 82          batch         1       unadjusted      sample_02     TRUE
#> 83          batch         1       unadjusted      sample_03     TRUE
#> 84          batch         1       unadjusted      sample_04     TRUE
#> 85          batch         1       unadjusted      sample_05     TRUE
#> 86          batch         1       unadjusted      sample_06     TRUE
#> 87          batch         1       unadjusted      sample_07     TRUE
#> 88          batch         1       unadjusted      sample_08     TRUE
#> 89          batch         2       unadjusted      sample_01     TRUE
#> 90          batch         2       unadjusted      sample_02     TRUE
#> 91          batch         2       unadjusted      sample_03     TRUE
#> 92          batch         2       unadjusted      sample_04     TRUE
#> 93          batch         2       unadjusted      sample_05     TRUE
#> 94          batch         2       unadjusted      sample_06     TRUE
#> 95          batch         2       unadjusted      sample_07     TRUE
#> 96          batch         2       unadjusted      sample_08     TRUE
#> 
#> 
#> $atlas_digest
#> [1] "00ba62ded370bbedf616087a7fcbf84d576dbfec15853570a998afa77d397a8a"
#> 
#> $compute_tier
#> [1] "standard-resampled"
permutation <- proposal_permutation_evidence(proposal)
permutation
#> An object of class "PermutationEvidence"
#> Slot "version":
#> [1] "1.1.0"
#> 
#> Slot "method":
#> [1] "nuisance-only-residual-permutation"
#> 
#> Slot "status":
#> [1] "complete"
#> 
#> Slot "n_requested":
#> [1] 49
#> 
#> Slot "n_completed":
#> [1] 49
#> 
#> Slot "observed_max_effect":
#> [1] 0.9954293
#> 
#> Slot "null_max_effect":
#>  [1] 0.4844576 0.3995111 0.1702148 0.2568286 0.6153920 0.3318098 0.5892051
#>  [8] 0.5707301 0.3995111 0.3011493 0.4582707 0.5136571 0.2925387 0.9131682
#> [15] 0.4594289 0.3995111 0.4594289 0.4582707 0.3797100 0.2237061 0.4565841
#> [22] 0.5615242 0.5630182 0.7201396 0.6380957 0.5421936 0.5630182 0.4582707
#> [29] 0.5892051 0.6415789 0.6415789 0.1964017 0.4058969 0.3709746 0.3613714
#> [36] 0.3995111 0.7146672 0.2041906 0.7146672 0.7055346 0.3613714 0.6367020
#> [43] 0.2581224 0.6380957 0.3573336 0.7463265 0.3957877 0.4565841 0.1712190
#> 
#> Slot "search_aware_p_value":
#> [1] 0.02
#> 
#> Slot "seed":
#> [1] 8001
#> 
#> Slot "cohort_digest":
#> [1] "d4f167505230ab2788195fc248e5496032fd64121ccaf3a1c862b6aa54c746bd"
#> 
#> Slot "design_digest":
#> [1] "9d176423b6495def65761f853c969617e669012b0cc0870bc1f29cbc4d8ac362"
#> 
#> Slot "diagnostic":
#> [1] ""
plot(proposal)

plot(permutation)

The proposal ranks the adjusted target effect because nuisance fields were declared. Every nuisance-only residual permutation reconstructs a null score and repeats the complete eligible-component search. The resulting p-value therefore compares the observed maximum absolute effect with null maxima, not with one component considered in isolation. It remains supporting exploratory evidence and cannot promote a runner-up.

The default cross-sectional declaration treats canonical biological samples as independent and exchangeable. If that assumption is not defensible, set exchangeability = "not_identifiable" in associate_metadata(). Point evidence remains available, while permutation returns permutation-not-identifiable and no search-aware p-value.

If target intent or a defensible permutation structure is absent, the same call returns a typed ComponentAbstention with permutation-not-identifiable. A rank-deficient or target-confounded nuisance design similarly preserves raw evidence while adjusted nomination abstains.

Assess whether the proposed axis is recoverable

Association bootstraps quantify uncertainty conditional on a fitted Stage 1 basis. Axis-identifiability evidence asks a different question: whether the complete discovery search recovers the same one-dimensional target structure when the biological sampling units are resampled.

The assessment starts from the pre-decomposition StateTransitionData, the frozen proposal, and the exact PipelineConfig used for discovery:

assessed <- assess_component_identifiability(
  data = raw_data,
  proposal = proposal,
  config = discovery_config,
  non_analytical_fields = "mouse_id",
  n_resamples = 499L,
  seed = 8301L
)

evidence <- proposal_identifiability(assessed)
evidence$recurrence_summary
evidence$target_recurrence
plot_component_identifiability(assessed)

Each replicate reruns the declared decomposition and complete eligible component ranking. Cross-sectional observations are resampled as independent biological units, destructive time courses within condition-by-time cells, and longitudinal data as complete subject trajectories. Duplicated longitudinal draws receive fresh subject identifiers.

The ordinary SVD strategy declares feature-loading cosine as its matching geometry. A global one-to-one assignment retains the complete similarity matrix, selected and competing assignments, margins, unmatched axes, sign orientation, index recurrence, proposal-rank recurrence, subspace angles, spectral gaps, source sampling units, and failed replicates. Sign correction occurs only after matching; no Procrustes rotation is applied.

Before a known-truth calibration is frozen, the structured outcome is not-calibrated and the evidence remains estimable-exploratory-only. Singular-value gaps are visible diagnostics, not effect weights or universal cutoffs. A later calibrated stable-subspace/no-stable-axis or no-stable-target-structure outcome is a successful scientific abstention and cannot be overridden to confirm an individual component.

Record the analyst decision

confirmed <- confirm_component(
  assessed,
  index = assessed@recommended_component,
  decision = "accept",
  rationale = paste(
    "Accepted the unique effect-first component in this synthetic",
    "implementation example."
  )
)
confirmed
canonical_digest(confirmed)

confirm_component() is the enforced transition to a confirmed AnalysisSpecification. Before calibration it records an explicitly exploratory choice and forces claim_intent = "exploratory"; it does not label the axis stable, validated, accepted as evidence, or scientifically supported. After calibration, only digest-valid stable-axis evidence permits individual component confirmation. Acceptance must use the recommended component. A different effect-equivalent component still requires decision = "override" and remains explicit. An override cannot bypass a calibrated non-axis, non-identifiable-design, outside-calibrated-operating-region, or unique-winner-failure outcome.

Independent destructive-sampling time courses

A destructive time course observes different biological samples at each time point. Time is known, but no subject trajectory is observed. Declare that design explicitly with independent_time_course(). Do not invent subject IDs or use longitudinal() for these data.

The synthetic example below plants a condition-by-time divergence across two components. It uses three independent samples in every condition-by-time cell.

time <- rep(c(0, 2, 4), each = 6L)
condition <- factor(
  rep(rep(c("control", "treatment"), each = 3L), 3L),
  levels = c("control", "treatment")
)
batch <- factor(rep(c("run_1", "run_2", "run_1"), 6L))
primary_time <- sprintf("time_sample_%02d", seq_along(time))
assay_time <- sprintf("rna_time_%02d", seq_along(time))

time_data <- StateTransitionData(
  experiments = list(
    rna = SummarizedExperiment::SummarizedExperiment(
      assays = list(logcounts = matrix(
        seq_len(4L * length(time)),
        nrow = 4L,
        dimnames = list(sprintf("gene_%02d", 1:4), assay_time)
      ))
    )
  ),
  colData = S4Vectors::DataFrame(
    condition = condition,
    day = time,
    batch = batch,
    row.names = primary_time
  ),
  sampleMap = S4Vectors::DataFrame(
    assay = factor(rep("rna", length(time)), levels = "rna"),
    primary = primary_time,
    colname = assay_time
  )
)
time_data <- declare_sampling_design(
  time_data,
  independent_time_course(time = "day", time_unit = "days")
)
time_metadata <- S4Vectors::metadata(time_data)
time_metadata$stage1 <- DecompositionResult(
  V_star = c(1, 0, 0, 0),
  sigma = 1,
  coords = list(seq_along(time)),
  V_k = diag(4)[, 1:2, drop = FALSE],
  sigma_k = matrix(c(2, 1), nrow = 1L),
  coords_k = list(cbind(
    PC1 = as.numeric(scale(time)),
    PC2 = as.numeric(scale(
      time * as.integer(condition == "treatment") +
        rep(c(-0.15, 0, 0.15), 6L)
    ))
  )),
  k = 2L
)
S4Vectors::metadata(time_data) <- time_metadata

time_specification <- analysis_specification(
  id = "synthetic-time-divergence",
  target_field = "condition",
  target_type = "binary",
  reference_level = "control",
  comparison_level = "treatment",
  nuisance_fields = "batch"
)
time_atlas <- associate_metadata(
  time_data,
  specification = time_specification,
  dataset_id = "synthetic-destructive-time-course",
  n_resamples = 49L,
  seed = 8101L
)
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
atlas_associations(time_atlas)
#>   metadata_field component component_label
#> 1      condition         1             PC1
#> 2      condition         1             PC1
#> 3      condition         1             PC1
#> 4      condition         2             PC2
#> 5      condition         2             PC2
#> 6      condition         2             PC2
#>                                  estimand      estimate effect_magnitude
#> 1             pooled-signed-rank-biserial  0.000000e+00     0.000000e+00
#> 2 standardized-condition-time-interaction -1.882906e-16     1.882906e-16
#> 3 standardized-condition-time-interaction -1.882906e-16     1.882906e-16
#> 4             pooled-signed-rank-biserial  6.666667e-01     6.666667e-01
#> 5 standardized-condition-time-interaction  2.536695e+00     2.536695e+00
#> 6 standardized-condition-time-interaction  2.536695e+00     2.536695e+00
#>   reference_level comparison_level n_available n_missing n_score_ties
#> 1         control        treatment          18         0           18
#> 2         control        treatment          18         0           18
#> 3         control        treatment          18         0           18
#> 4         control        treatment          18         0           12
#> 5         control        treatment          18         0           12
#> 6         control        treatment          18         0           12
#>   n_target_ties       evidence_variant proposal_eligible nuisance_fields
#> 1            NA     pooled-descriptive             FALSE                
#> 2            18 time-course-unadjusted              TRUE                
#> 3            18   time-course-adjusted              TRUE           batch
#> 4            NA     pooled-descriptive             FALSE                
#> 5            18 time-course-unadjusted              TRUE                
#> 6            18   time-course-adjusted              TRUE           batch
#>                                                      cohort_digest
#> 1 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#> 2 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#> 3 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#> 4 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#> 5 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#> 6 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#>                                                      design_digest
#> 1                                                             <NA>
#> 2 84d3cc82aa28ee08dce3d4aed356dac9b4a4040db59dac4d8333c360e58906ea
#> 3 256425b40eb39b6971daca132ce361c12746fd194fff78f8736bbc2b7b513fcd
#> 4                                                             <NA>
#> 5 84d3cc82aa28ee08dce3d4aed356dac9b4a4040db59dac4d8333c360e58906ea
#> 6 256425b40eb39b6971daca132ce361c12746fd194fff78f8736bbc2b7b513fcd
#>                                 diagnostic      p_value      q_value
#> 1 descriptive-only-not-trajectory-evidence 1.000000e+00 1.000000e+00
#> 2                                          3.031249e-01 3.031249e-01
#> 3                                          3.064957e-01 3.064957e-01
#> 4 descriptive-only-not-trajectory-evidence 1.744966e-02 3.489932e-02
#> 5                                          5.284264e-13 1.056853e-12
#> 6                                          3.691321e-12 7.382643e-12
#>   effect_conf_low effect_conf_high n_resamples resample_failures
#> 1              NA               NA           0                 0
#> 2   -2.031583e-16    -2.031583e-16          49                 0
#> 3   -2.742894e-16    -4.668591e-17          49                 0
#> 4              NA               NA           0                 0
#> 5    2.398492e+00     2.676428e+00          49                 0
#> 6    2.387538e+00     2.681744e+00          49                 0
#>               resampling_method
#> 1                 not-requested
#> 2 condition-time-cell-bootstrap
#> 3 condition-time-cell-bootstrap
#> 4                 not-requested
#> 5 condition-time-cell-bootstrap
#> 6 condition-time-cell-bootstrap
#>                                             resampling_plan_digest
#> 1                                                             <NA>
#> 2 b41ab0d38c8d4d7c5cdfa08e8497e98b489c05bcdaf3a7b3dd97b142cf1b15c6
#> 3 b41ab0d38c8d4d7c5cdfa08e8497e98b489c05bcdaf3a7b3dd97b142cf1b15c6
#> 4                                                             <NA>
#> 5 b41ab0d38c8d4d7c5cdfa08e8497e98b489c05bcdaf3a7b3dd97b142cf1b15c6
#> 6 b41ab0d38c8d4d7c5cdfa08e8497e98b489c05bcdaf3a7b3dd97b142cf1b15c6
#>              evidence_status
#> 1 estimable-exploratory-only
#> 2 estimable-exploratory-only
#> 3 estimable-exploratory-only
#> 4 estimable-exploratory-only
#> 5 estimable-exploratory-only
#> 6 estimable-exploratory-only
plot(time_atlas)

The registered ordinary linear model is score_std ~ condition * time_scaled + nuisance_terms. Scores have a deterministic orientation and SD scale. Observed study time is transformed deterministically to the study’s 0–1 interval, and the interaction coefficient is the proposal-eligible effect. Raw and adjusted variants remain separate. The stored evidence records the analysis cohort, formula, model-matrix rank, time transformation, cell counts, bootstrap failures, engine controls, and provenance.

Both conditions must occur at two or more overlapping times, every relevant condition-by-time cell must contain independent replication, the design matrix must be full rank, and the number of observations must exceed its degrees of freedom. A failed gate produces a typed abstention. Bootstrap resampling occurs within condition-by-observed-time cells and retains the observed grid and cell counts. Fixed observed times are never permuted. Unadjusted proposals permute condition labels within time; adjusted proposals use nuisance-only residual permutation within time.

time_proposal <- propose_component(
  time_atlas,
  n_permutations = 49L,
  seed = 8201L
)
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
#> Warning in summary.lm(object, ...): essentially perfect fit: summary may be
#> unreliable
#> Warning in summary.lm(fit): essentially perfect fit: summary may be unreliable
proposal_ranking(time_proposal)
#>   metadata_field component component_label
#> 1      condition         2             PC2
#> 2      condition         1             PC1
#>                                  estimand      estimate effect_magnitude
#> 1 standardized-condition-time-interaction  2.536695e+00     2.536695e+00
#> 2 standardized-condition-time-interaction -1.882906e-16     1.882906e-16
#>   reference_level comparison_level n_available n_missing n_score_ties
#> 1         control        treatment          18         0           12
#> 2         control        treatment          18         0           18
#>   n_target_ties     evidence_variant proposal_eligible nuisance_fields
#> 1            18 time-course-adjusted              TRUE           batch
#> 2            18 time-course-adjusted              TRUE           batch
#>                                                      cohort_digest
#> 1 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#> 2 47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2
#>                                                      design_digest diagnostic
#> 1 256425b40eb39b6971daca132ce361c12746fd194fff78f8736bbc2b7b513fcd           
#> 2 256425b40eb39b6971daca132ce361c12746fd194fff78f8736bbc2b7b513fcd           
#>        p_value      q_value effect_conf_low effect_conf_high n_resamples
#> 1 3.691321e-12 7.382643e-12    2.387538e+00     2.681744e+00          49
#> 2 3.064957e-01 3.064957e-01   -2.742894e-16    -4.668591e-17          49
#>   resample_failures             resampling_method
#> 1                 0 condition-time-cell-bootstrap
#> 2                 0 condition-time-cell-bootstrap
#>                                             resampling_plan_digest
#> 1 b41ab0d38c8d4d7c5cdfa08e8497e98b489c05bcdaf3a7b3dd97b142cf1b15c6
#> 2 b41ab0d38c8d4d7c5cdfa08e8497e98b489c05bcdaf3a7b3dd97b142cf1b15c6
#>              evidence_status proposal_rank
#> 1 estimable-exploratory-only             1
#> 2 estimable-exploratory-only             2
proposal_permutation_evidence(time_proposal)
#> An object of class "PermutationEvidence"
#> Slot "version":
#> [1] "1.1.0"
#> 
#> Slot "method":
#> [1] "within-time-reduced-model-residual-permutation"
#> 
#> Slot "status":
#> [1] "complete"
#> 
#> Slot "n_requested":
#> [1] 49
#> 
#> Slot "n_completed":
#> [1] 49
#> 
#> Slot "observed_max_effect":
#> [1] 2.536695
#> 
#> Slot "null_max_effect":
#>  [1] 7.877586e-01 3.904941e-16 2.076898e-01 1.447149e-01 2.326109e-01
#>  [6] 5.918956e-01 8.455651e-01 5.649150e-02 1.408632e-01 5.996967e-02
#> [11] 5.747082e-02 1.156175e-01 8.516310e-01 8.706429e-01 8.008337e-17
#> [16] 6.982300e-02 1.460708e-01 1.434434e+00 9.155033e-01 1.123433e-15
#> [21] 1.035817e+00 8.455651e-01 5.747082e-02 1.142775e-01 9.793756e-01
#> [26] 1.156175e-01 4.336457e-16 1.618580e+00 8.338125e-01 7.766551e-01
#> [31] 9.289772e-01 1.163054e-01 1.163054e-01 1.697716e+00 8.396271e-01
#> [36] 7.782098e-01 7.136830e-01 1.755087e-01 7.291549e-01 7.877586e-01
#> [41] 8.455651e-01 7.238863e-01 6.409876e-16 1.931770e+00 1.628446e+00
#> [46] 2.867922e-01 1.089679e-15 1.541567e+00 1.724125e-01
#> 
#> Slot "search_aware_p_value":
#> [1] 0.02
#> 
#> Slot "seed":
#> [1] 8201
#> 
#> Slot "cohort_digest":
#> [1] "47352523a881695d7504c68ac5cfbe9d4b37ffd0414ba990487f60fdd628d4c2"
#> 
#> Slot "design_digest":
#> [1] "256425b40eb39b6971daca132ce361c12746fd194fff78f8736bbc2b7b513fcd"
#> 
#> Slot "diagnostic":
#> [1] ""
plot(time_proposal)

This declaration is distinct from two other designs:

  • repeated subjects require complete subject trajectories to be resampled and a subject-aware random-effects association strategy;
  • ordered cross-sectional states express a declared ordering, not elapsed observed time or within-subject change.

Repeated-subject time courses

Repeated measurements declare both the subject identifier and observed study time. The registered strategy estimates the standardized condition-by-time interaction with correlated subject-specific random intercepts and time slopes: score_std ~ condition * time_scaled + nuisance_terms + (1 + time_scaled | subject).

subject_id <- rep(sprintf("mouse_%02d", 1:16), each = 4L)
subject_index <- rep(1:16, each = 4L)
repeated_time <- rep(0:3, times = 16L)
repeated_condition <- factor(
  rep(rep(c("control", "treatment"), each = 8L), each = 4L),
  levels = c("control", "treatment")
)
subject_offset <- 0.12 * sin(subject_index)
subject_slope <- 0.06 * ((subject_index - 1L) %% 8L - 3.5)
repeated_pc1 <- subject_offset +
  (0.5 + subject_slope) * repeated_time +
  1.4 * (repeated_condition == "treatment") * repeated_time +
  0.05 * sin(seq_along(repeated_time))
repeated_pc2 <- 0.1 * cos(subject_index) +
  (0.8 - subject_slope) * repeated_time +
  0.05 * cos(seq_along(repeated_time))
repeated_primary <- sprintf("repeated_sample_%03d", seq_along(repeated_time))
repeated_assay <- sprintf("repeated_rna_%03d", seq_along(repeated_time))

repeated_data <- StateTransitionData(
  experiments = list(
    rna = SummarizedExperiment::SummarizedExperiment(
      assays = list(logcounts = matrix(
        seq_len(5L * length(repeated_time)),
        nrow = 5L,
        dimnames = list(sprintf("gene_%02d", 1:5), repeated_assay)
      ))
    )
  ),
  colData = S4Vectors::DataFrame(
    condition = repeated_condition,
    day = repeated_time,
    mouse_id = subject_id,
    batch = factor(ifelse(subject_index %% 2L, "run_1", "run_2")),
    row.names = repeated_primary
  ),
  sampleMap = S4Vectors::DataFrame(
    assay = factor(
      rep("rna", length(repeated_time)),
      levels = "rna"
    ),
    primary = repeated_primary,
    colname = repeated_assay
  )
)
repeated_data <- declare_sampling_design(
  repeated_data,
  longitudinal(
    subject_id = "mouse_id",
    time = "day",
    time_unit = "days"
  )
)
repeated_metadata <- S4Vectors::metadata(repeated_data)
repeated_metadata$stage1 <- DecompositionResult(
  V_star = c(1, 0, 0, 0, 0),
  sigma = 1,
  coords = list(repeated_pc1),
  V_k = diag(5)[, 1:2, drop = FALSE],
  sigma_k = matrix(c(2, 1), nrow = 1L),
  coords_k = list(cbind(
    PC1 = repeated_pc1,
    PC2 = repeated_pc2
  )),
  k = 2L
)
S4Vectors::metadata(repeated_data) <- repeated_metadata

repeated_specification <- analysis_specification(
  id = "synthetic-repeated-divergence",
  target_field = "condition",
  target_type = "binary",
  reference_level = "control",
  comparison_level = "treatment",
  nuisance_fields = "batch"
)
repeated_atlas <- associate_metadata(
  repeated_data,
  specification = repeated_specification,
  non_analytical_fields = "mouse_id",
  dataset_id = "synthetic-repeated-time-course",
  n_resamples = 49L,
  seed = 8202L
)
repeated_proposal <- propose_component(
  repeated_atlas,
  n_permutations = 49L,
  seed = 8203L
)
plot(repeated_atlas)

plot(repeated_proposal)

The complete subject trajectory is the inferential and resampling unit. Bootstrap draws occur within condition and receive fresh subject identifiers, so a duplicated draw remains one trajectory rather than pseudoreplicated observations. Permutation reassigns condition only at subject level and keeps observed times fixed. Missing required observations exclude the complete subject trajectory from a model; the recorded study-time range is not silently contracted.

At least three usable observed times per subject, independent between-subject replication in each condition, and a full-rank fixed-effects design are required. Singular random-effects covariance and optimizer non-convergence are distinct typed abstentions with native diagnostics. Neither outcome triggers a random-intercept-only or independent-observation fallback. Individual trajectories, condition-level fitted divergence, sampling support, dropout, uncertainty, fit failures, and abstention remain visible in the canonical plots.

All three supported sampling designs cross the same package-owned evidence boundary before the atlas is constructed. atlas_evidence_contract() returns the same inspection fields for each design: a module version and sampling design, normalized row counts, deterministic table digests, cohort summaries, and explicit cohort membership. The common shape makes downstream evidence auditable without treating condition-by-time cells and subject trajectories as exchangeable:

lapply(
  list(
    cross_sectional = atlas,
    independent_time_course = time_atlas,
    repeated_subject = repeated_atlas
  ),
  function(x) {
    contract <- atlas_evidence_contract(x)
    list(
      version = contract$version,
      sampling_design = contract$sampling_design,
      row_counts = contract$row_counts
    )
  }
)
#> $cross_sectional
#> $cross_sectional$version
#> [1] "cross-sectional-v1"
#> 
#> $cross_sectional$sampling_design
#> [1] "cross_sectional"
#> 
#> $cross_sectional$row_counts
#> associations observations   exclusions 
#>           12           80            1 
#> 
#> 
#> $independent_time_course
#> $independent_time_course$version
#> [1] "independent-time-course-v1"
#> 
#> $independent_time_course$sampling_design
#> [1] "independent_time_course"
#> 
#> $independent_time_course$row_counts
#> associations observations   exclusions 
#>            6           36            2 
#> 
#> 
#> $repeated_subject
#> $repeated_subject$version
#> [1] "repeated-time-course-v1"
#> 
#> $repeated_subject$sampling_design
#> [1] "longitudinal"
#> 
#> $repeated_subject$row_counts
#> associations observations   exclusions 
#>            6          128            3

Scientific captions are separate publication artifacts

User-facing landscapeR renderers return ordinary ggplot objects. Migrated renderers attach a deterministic caption derived from the same typed evidence used by the graphic; retrieve it with scientific_caption(plot). The package does not draw this text inside the plot, so Quarto, R Markdown, and manuscript systems can render it as a true figure caption. Caption templates preserve caller-declared experiment, layer, target, level, time, subject, and nuisance labels exactly. They format stored estimands, uncertainty, thresholds, missingness, and claim boundaries without recalculating scientific results.

The same boundary is available directly through visual_evidence(). It returns a validated VisualEvidenceView used by the canonical ggplot renderer:

Design-specific display tables are retrieved by their recorded names with visual_evidence_display(). They contain already-computed trajectories, interval labels, missing-cell markers, dropout endpoints, or fitted diagnostic curves as applicable. Plotting code does not inspect private provenance or reconstruct those scientific results. The view can support a future compatible interactive adapter, but ggplot2 remains the canonical reproducible output and interactive software cannot alter a proposal or abstention.

Registering additional methods

Method authors register an R closure under one contract:name key with register_strategy(). Keys are write-once by default: a different constructor under an existing key raises a typed collision error and leaves the accepted method unchanged, while re-registering a fingerprint-equivalent constructor with the same code and behavior-relevant captured state is an idempotent no-op. Primitive functions are unsupported because they cannot meet the inspectable fingerprint contract.

A deliberate correction uses replace = TRUE with a non-empty rationale. The accepted registration and any replacement remain inspectable with strategy_registration_history(), including chained constructor fingerprints and the replacement rationale. A registered closure whose behavior-relevant captured state has changed must be stabilized and registered from a fresh session rather than silently replacing its recorded identity.

Current boundary

These paths do not reinterpret destructive time courses as longitudinal subjects or claim axis stability before calibration. Association-bootstrap intervals quantify uncertainty while holding the fitted Stage 1 basis fixed; axis-identifiability evidence separately refits Stage 1 and the full component search. The current repeated-subject strategy is linear and frequentist; nonlinear, marginal, robust, or Bayesian trajectory models require separately registered strategies. A real-data confirmation is a documented analyst decision, not proof that the selected coordinate is biologically true.