Skip to contents

Generate a single known-shift simulation replicate using the empirically calibrated multi-shift framework. The function supports both the proportional generating-model scenario and a generator-specific non-proportional robustness scenario.

Usage

simulateShiftedDataset(
  template,
  tree_tip_count = NULL,
  num_shifts,
  min_shift_tips,
  max_shift_tips,
  scale_mode = c("proportional", "correlation"),
  scale_factor_range = c(0.1, 2),
  exclude_range = c(0.5, 1.5),
  buffer = 3,
  seed = NULL,
  simulation_generator = c("original", "empirical"),
  covariance_df = NULL,
  integration_power_range = c(0.5, 1.25),
  integration_exclude_range = c(0.8, 1.1),
  eigen_floor = 1e-08
)

Arguments

template

A bifrost_simulation_template returned by createSimulationTemplate().

tree_tip_count

Optional integer tip count for random subtree sampling. If NULL, the full empirical tree from template is used.

num_shifts

Integer number of shifts to simulate.

min_shift_tips

Integer minimum size of any shifted clade.

max_shift_tips

Integer maximum size of any shifted clade.

scale_mode

Character string specifying the generating scenario: "proportional" for the manuscript generating model or "correlation" for the generator-specific non-proportional robustness scenario. With the default "original" generator, the latter reproduces the published correlation transform; with simulation_generator = "empirical", it is an integration-rate trade-off.

scale_factor_range

Strictly positive numeric length-2 vector giving the full range of possible shift scalars.

exclude_range

Numeric length-2 vector specifying the central interval excluded from sampled shift scalars.

buffer

Integer minimum node distance between simulated shifts.

seed

Optional integer random seed. When supplied, the function restores the caller's previous RNG state before returning.

simulation_generator

Covariance and correlation-shift generator to use. "original", the default, reproduces the published simulation operations exactly. "empirical" draws around the full fitted covariance and changes integration and marginal evolutionary variance in opposing directions. Supply exactly one supported string; explicitly supplied vectors are rejected. When omitted, "original" is used.

covariance_df

Optional integer degrees of freedom for empirical Wishart draws. It must be at least the number of response traits. The default uses the residual degrees of freedom stored in template.

integration_power_range

Strictly positive increasing numeric length-2 vector spanning one. Corrected correlation shifts draw spectral powers from the two tails of this range.

integration_exclude_range

Increasing numeric length-2 vector that contains one and lies strictly inside integration_power_range. Powers in this central interval are excluded so shifts have a material effect.

eigen_floor

Numeric stability floor, as a fraction of the largest eigenvalue, used by empirical correlation transforms.

Value

A list of class bifrost_simulation_replicate_shifted containing the painted generating tree, the true shift nodes, the simulated response matrix, a response-only trait_data object used for downstream model fitting, regime covariance matrices, sampled scale factors or integration powers, reciprocal marginal-variance scale factors, generator metadata, covariance diagnostics, and a scenario label. For schema compatibility, sampledScaleFactors contains the sampled integration powers under the empirical correlation generator; the explicit sampledIntegrationPowers and sampledVarianceScaleFactors fields should be preferred for interpretation.

Details

This function generates shifted residual processes around the fitted mean structure stored in the template:

  • random subtree sampling from the empirical tree,

  • shift placement subject to clade-size and non-overlap constraints,

  • buffer enforcement using node distances,

  • generation of a fresh ancestral covariance matrix centered on the full empirical residual covariance for each empirical replicate,

  • construction of derived regimes by either proportional scaling or the generator-specific non-proportional robustness scenario, and

  • simulation of multivariate BMM residuals that are added to the empirical fitted mean structure from the global calibration model.

Under scale_mode = "proportional", derived regimes are scalar multiples of the ancestral covariance matrix and therefore match the generating assumptions of the current bifrost BMM search. Under scale_mode = "correlation", the empirical generator raises the eigenvalues of the ancestral correlation matrix to a sampled positive power and renormalizes the result to a correlation matrix. Powers below one reduce integration; powers above one increase it. The derived covariance is then divided by the same power. Consequently, powers below one pair reduced integration with increased marginal evolutionary variance, whereas powers above one pair increased integration with decreased marginal variance. More precisely, diag(Sigma_derived) = diag(Sigma_ancestral) / power. This deliberate integration-rate trade-off remains a model-misspecification robustness test because the search fits proportional covariance shifts.

The "original" generator is supplied for exact reproduction. Its correlation scenario scales correlations and inversely scales marginal variances according to the original manuscript operations; it should not be interpreted as holding marginal variances fixed. Downstream simulation studies still evaluate intercept-only shift searches on the regenerated response block, so the returned trait_data contains only the simulated response variables. This is the lower-level shifted-replicate generator used by runShiftRecoverySimulationStudy() and runSearchTuningGrid(); use those wrappers for replicated shift-recovery or tuning-grid workflows.

Examples

if (FALSE) { # \dontrun{
set.seed(1)
tr <- ape::rtree(40)
X <- matrix(rnorm(40 * 3), ncol = 3)
rownames(X) <- tr$tip.label
tmpl <- createSimulationTemplate(tr, X, formula = "trait_data ~ 1", method = "LL")

sim_shift <- simulateShiftedDataset(
  tmpl,
  tree_tip_count = 25,
  num_shifts = 2,
  min_shift_tips = 3,
  max_shift_tips = 8,
  scale_mode = "proportional",
  seed = 3
)

sim_shift$shiftNodes
} # }