---
title: "Getting started with spliv"
author: "Ore Koren"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{Getting started with spliv}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(spliv)
set.seed(42)
n <- 240
z <- rnorm(n)
w <- rnorm(n)
exposure <- pnorm(w)
inactive <- seq_len(n) <= n / 2
x <- ifelse(inactive, 0, 1) * z + 0.4 * w + rnorm(n)
y <- 1.2 * x + 0.25 * w + 0.15 * exposure * z + rnorm(n)
d <- data.frame(y, x, z, w, exposure, inactive)
f <- y ~ x + w | z + w
```

## Baseline IV and uniform sensitivity

The `spliv()` estimator accepts the usual IV formula `y ~ X | Z`. Ordinary
exogenous controls belong on both sides, as in `y ~ x + w | z + w`. With no
method or bound supplied, the baseline is UCI at `delta = 0`; a positive
`delta` allows a bounded uniform direct effect. On the default scale, `delta`
is an outcome-unit direct effect for a one-residual-SD instrument shift.

```{r baseline}
baseline <- spliv(f, d, vcov = "hc1")
baseline$estimates
uniform <- spliv(f, d, method = "uci", delta = 0.20, vcov = "hc1",
                 grid = list(steps = 9))
uniform$estimates
```

## A patterned UCI/LTZ analysis

Patterns are explicit objects with a substantive rationale. Here the direct
effect is allowed to be larger where the synthetic exposure is larger.

```{r pattern}
pattern <- spliv_pattern(
  name = "Exposure pattern", pattern = ~ exposure,
  rationale = "The alternative channel is stronger at higher exposure.",
  variables_used = "exposure", pattern_type = "theory_defined",
  normalize = "max_abs"
)
spliv_eval_pattern(pattern, d)[1:5]
patterned_uci <- spliv(f, d, method = "uci", delta = 0.20, vcov = "hc1",
                       violation_pattern = pattern, grid = list(steps = 9))
patterned_ltz <- spliv(f, d, method = "ltz", delta = 0.20, vcov = "hc1",
                       violation_pattern = pattern)
patterned_uci$estimates
patterned_ltz$estimates
```

## Sensitivity paths and tipping points

Paths make the sensitivity grid explicit. A tipping point is reported only when
the supplied interval contains zero at a grid value.

```{r paths}
path <- spliv_sensitivity_path(
  f, d, method = "uci", delta_grid = seq(0, 0.30, by = 0.05),
  vcov = "hc1", violation_pattern = pattern
)
head(path)
spliv_tipping_point(path)
```

## Confirmatory BPE design and validation

BPE uses an outcome-independent subset specified before examining the outcome
analysis and requires a non-empty transportability rationale. Validation
reports eligibility diagnostics; it does not search across candidate
subgroups. The default `sampling` transport uses the estimated reduced-form
sampling covariance; `conservative` adds a pre-specified covariance inflation.

```{r bpe}
design <- bpe_design(
  name = "Theory-defined inactive subset", subset = ~ inactive,
  rationale = "The treatment channel is absent in the inactive subset.",
  variables_used = "inactive", subset_type = "theory_defined",
  pre_specified = TRUE,
  transportability_rationale = "The subset direct effect is informative for the target sample."
)
# Illustrative synthetic margin: 0.25 residual treatment SD per
# one-residual-SD instrument shift. In substantive work, pre-specify the
# margin rather than tuning it to obtain BPE eligibility.
bpe_margin <- 0.25
validation <- bpe_validate_design(
  f, d, design = design, vcov = "hc1",
  bpe_min_n_S = 40,
  bpe_equiv_margin = bpe_margin
)
validation[c("n_S", "equivalence_passed", "eligibility_passed")]

bpe_fit <- spliv(f, d, method = "bpe", bpe_design = design,
                 vcov = "hc1", bpe_min_n_S = 40,
                 bpe_equiv_margin = bpe_margin)
bpe_fit$estimates
```

`bpe_explore_subsets()` is available for transparent exploratory diagnostics,
but exploratory subgroup search and selecting the first passing rule are not
confirmatory BPE. Confirmatory claims require a pre-specified design and a
reported validation record.
