gam_models/fit_orchestration/
deviation.rs1use super::*;
9
10fn deviation_block_config_from_formula_linkwiggle(
11 wiggle: &LinkWiggleFormulaSpec,
12) -> Result<DeviationBlockConfig, String> {
13 if wiggle.degree != 3 {
19 return Err(format!(
20 "linkwiggle() degree must be 3 when routed into the score-warp / \
21 link-deviation block: that runtime is a cubic I-spline and only \
22 supports cubic splines; got degree={}",
23 wiggle.degree
24 ));
25 }
26 let defaults = WigglePenaltyConfig::cubic_triple_operator_default();
27 Ok(DeviationBlockConfig {
28 degree: wiggle.degree,
29 num_internal_knots: wiggle.num_internal_knots,
30 penalty_order: *wiggle.penalty_orders.iter().max().unwrap_or(&2),
31 penalty_orders: wiggle.penalty_orders.clone(),
32 double_penalty: wiggle.double_penalty,
33 monotonicity_eps: defaults.monotonicity_eps,
34 })
35}
36
37#[derive(Debug)]
38pub struct MarginalSlopeDeviationRouting {
39 pub score_warp: Option<DeviationBlockConfig>,
40 pub link_dev: Option<DeviationBlockConfig>,
41}
42
43pub fn route_marginal_slope_deviation_blocks(
44 main_linkwiggle: Option<&LinkWiggleFormulaSpec>,
45 logslope_linkwiggle: Option<&LinkWiggleFormulaSpec>,
46) -> Result<MarginalSlopeDeviationRouting, String> {
47 Ok(MarginalSlopeDeviationRouting {
48 score_warp: logslope_linkwiggle
49 .map(deviation_block_config_from_formula_linkwiggle)
50 .transpose()?,
51 link_dev: main_linkwiggle
52 .map(deviation_block_config_from_formula_linkwiggle)
53 .transpose()?,
54 })
55}