% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/ba_rm.R
\name{ba_rm}
\alias{ba_rm}
\alias{print.ba_repeated}
\alias{print.ba_repeated_matrix}
\alias{plot.ba_repeated}
\alias{plot.ba_repeated_matrix}
\title{Bland-Altman for repeated measurements}
\usage{
ba_rm(
  data = NULL,
  response,
  subject,
  method,
  time,
  conf_level = 0.95,
  n_threads = getOption("matrixCorr.threads", 1L),
  verbose = FALSE,
  loa_multiplier = 1.96,
  include_slope = FALSE,
  use_ar1 = FALSE,
  ar1_rho = NA_real_,
  max_iter = 200L,
  tol = 1e-06
)

\method{print}{ba_repeated}(
  x,
  digits = 3,
  ci_digits = 3,
  n = NULL,
  topn = NULL,
  max_vars = NULL,
  width = NULL,
  show_ci = NULL,
  ...
)

\method{print}{ba_repeated_matrix}(
  x,
  digits = 3,
  ci_digits = 3,
  n = NULL,
  topn = NULL,
  max_vars = NULL,
  width = NULL,
  show_ci = NULL,
  style = c("pairs", "matrices"),
  ...
)

\method{plot}{ba_repeated}(
  x,
  title = "Bland-Altman (repeated measurements)",
  subtitle = NULL,
  point_alpha = 0.7,
  point_size = 2.2,
  line_size = 0.8,
  shade_ci = TRUE,
  shade_alpha = 0.08,
  smoother = c("none", "loess", "lm"),
  symmetrize_y = TRUE,
  show_points = TRUE,
  show_value = TRUE,
  ...
)

\method{plot}{ba_repeated_matrix}(
  x,
  pairs = NULL,
  against = NULL,
  facet_scales = c("free_y", "fixed"),
  title = "Bland-Altman (repeated, pairwise)",
  point_alpha = 0.6,
  point_size = 1.8,
  line_size = 0.7,
  shade_ci = TRUE,
  shade_alpha = 0.08,
  smoother = c("none", "loess", "lm"),
  show_points = TRUE,
  show_value = TRUE,
  ...
)
}
\arguments{
\item{data}{Optional data frame-like object. If supplied, \code{response},
\code{subject}, \code{method}, and \code{time} may be column names. Objects not already
inheriting from \code{data.frame} are first coerced with \code{as.data.frame()}.}

\item{response}{Numeric response vector, or a single character string naming
the response column in \code{data}.}

\item{subject}{Subject identifier vector (integer, numeric, or factor), or a
single character string naming the subject column in \code{data}.}

\item{method}{Method label vector (character, factor, integer, or numeric), or
a single character string naming the method column in \code{data}. At least two
distinct method levels are required.}

\item{time}{Replicate/time index vector (integer or numeric), or a single
character string naming the time column in \code{data}. Values are coerced to
integer before pairing and before AR(1) contiguity checks.}

\item{conf_level}{Confidence level for Wald confidence intervals for the
reported bias and both LoA endpoints. Must lie in \verb{(0, 1)}. Default \code{0.95}.}

\item{n_threads}{Integer \eqn{\geq 1}. Number of OpenMP threads. Defaults to
\code{getOption("matrixCorr.threads", 1L)}.}

\item{verbose}{Logical. If \code{TRUE}, print progress for the pairwise
\eqn{\ge 3}-method path. It has no material effect in the exactly-two-method
path.}

\item{loa_multiplier}{Positive scalar giving the SD multiplier used to form
the limits of agreement. Default is \code{1.96}. In the exported \code{ba_rm()}
interface this default is fixed and does not depend on \code{conf_level}.}

\item{include_slope}{Logical. If \code{TRUE}, the model includes the paired mean as
a fixed effect and estimates a proportional-bias slope. The reported BA
centre remains the fitted mean difference at the centred reference paired
mean used internally by the backend; the returned LoA remain horizontal
bands and are not regression-adjusted curves.}

\item{use_ar1}{Logical. If \code{TRUE}, request an AR(1) residual structure within
subject over contiguous integer time blocks.}

\item{ar1_rho}{Optional AR(1) parameter. Must satisfy \code{abs(ar1_rho) < 0.999}
when supplied. If \code{NA} and \code{use_ar1 = TRUE}, the backend estimates \code{rho}
separately for each analysed pair.}

\item{max_iter}{Maximum number of EM/GLS iterations used by the backend.}

\item{tol}{Convergence tolerance for the backend EM/GLS iterations.}

\item{x}{A \code{"ba_repeated_matrix"} object.}

\item{digits}{Number of digits for estimates (default 3).}

\item{ci_digits}{Number of digits for CI bounds (default 3).}

\item{n}{Optional row threshold for compact preview output.}

\item{topn}{Optional number of leading/trailing rows to show when truncated.}

\item{max_vars}{Optional maximum number of visible columns; \code{NULL} derives this
from console width.}

\item{width}{Optional display width; defaults to \code{getOption("width")}.}

\item{show_ci}{One of \code{"yes"} or \code{"no"}.}

\item{...}{Additional theme adjustments passed to \code{ggplot2::theme(...)}
(e.g., \code{plot.title.position = "plot"}, \code{axis.title.x = element_text(size=11)}).}

\item{style}{Show as pairs or matrix format?}

\item{title}{Plot title (character scalar). Defaults to
\code{"Bland-Altman (repeated measurements)"} for two methods and
\code{"Bland-Altman (repeated, pairwise)"} for the faceted matrix plot.}

\item{subtitle}{Optional subtitle (character scalar). If \code{NULL}, a compact
summary is shown using the fitted object.}

\item{point_alpha}{Numeric in \verb{[0, 1]}. Transparency for scatter points
drawn at (pair mean, pair difference) when point data are available.
Passed to \code{ggplot2::geom_point(alpha = ...)}. Default \code{0.7}.}

\item{point_size}{Positive numeric. Size of scatter points; passed to
\code{ggplot2::geom_point(size = ...)}. Default \code{2.2}.}

\item{line_size}{Positive numeric. Line width for horizontal bands
(bias and both LoA) and, when requested, the proportional-bias line.
Passed to \code{ggplot2::geom_hline(linewidth = ...)} (and \code{geom_abline}).
Default \code{0.8}.}

\item{shade_ci}{Logical. If \code{TRUE} and confidence intervals are available in
the object (\code{CI.lines} for two methods; \verb{*_ci_*} matrices for the pairwise
case), semi-transparent rectangles are drawn to indicate CI bands for the
bias and each LoA. If \code{FALSE}, dashed horizontal CI lines are drawn instead.
Has no effect if CIs are not present. Default \code{TRUE}.}

\item{shade_alpha}{Numeric in \verb{[0, 1]}. Opacity of the CI shading
rectangles when \code{shade_ci = TRUE}. Passed to \code{ggplot2::annotate("rect", alpha = ...)}.
Default \code{0.08}.}

\item{smoother}{One of \code{"none"}, \code{"loess"}, or \code{"lm"}. Adds an overlaid trend
for differences vs means when points are drawn, to visualise proportional
bias. \code{"lm"} fits a straight line with no SE ribbon; \code{"loess"} draws a
locally-smoothed curve (span 0.9) with no SE ribbon; \code{"none"} draws no
smoother. Ignored if \code{show_points = FALSE} or if no point data are available.}

\item{symmetrize_y}{Logical (two-method plot only). If \code{TRUE}, the y-axis is
centred at the estimated bias and expanded symmetrically to cover all
elements used to compute the range (bands, CIs, and points if shown).
Default \code{TRUE}.}

\item{show_points}{Logical. If \code{TRUE}, per-pair points are drawn for the
exactly-two-method path from the stored \code{means} and \code{diffs} vectors.
Pairwise matrix plots draw points reconstructed from the canonical
long-form columns stored by \code{ba_rm()}. If \code{FALSE} or if point data are
unavailable, only the bands (and optional CI indicators) are drawn.
Default \code{TRUE}.}

\item{show_value}{Logical; included for a consistent plotting interface.
Repeated-measures Bland-Altman plots do not overlay numeric cell values,
so this argument currently has no effect.}

\item{pairs}{(Faceted pairwise plot only.) Optional character vector of
labels specifying which method contrasts to display. Labels must match the
"row - column" convention used by \code{print()}/\code{summary()} (e.g., \code{"B - A"}).
Defaults to all upper-triangle pairs.}

\item{against}{(Faceted pairwise plot only.) Optional single method name.
If supplied, facets are restricted to contrasts of the chosen method
against all others. Ignored when \code{pairs} is provided.}

\item{facet_scales}{(Faceted pairwise plot only.) Either \code{"free_y"} (default)
to allow each facet its own y-axis limits, or \code{"fixed"} for a common scale
across facets. Passed to \code{ggplot2::facet_wrap(scales = ...)}.}
}
\value{
Either a \code{"ba_repeated"} object (exactly two methods) or a
\code{"ba_repeated_matrix"} object (\eqn{\ge 3} methods).

\strong{If exactly two methods are supplied}, the returned
\code{"ba_repeated"} object is a list with components:
\itemize{
\item \code{means}: numeric vector of paired means
\eqn{(y_1 + y_2)/2} used for plotting helpers.
\item \code{diffs}: numeric vector of paired differences
\eqn{y_2 - y_1} used for plotting helpers.
\item \code{n_obs}: integer number of complete subject-time pairs used.
\item \code{based.on}: compatibility alias for \code{n_obs}.
\item \code{mean.diffs}: scalar model-based BA centre. When
\code{include_slope = FALSE}, this is the fitted intercept of the paired-
difference model. When \code{include_slope = TRUE}, this is the fitted mean
difference at the centred reference paired mean used internally by the
backend.
\item \code{lower.limit}, \code{upper.limit}: scalar limits of agreement,
computed as
\eqn{\mu_0 \pm \texttt{loa\_multiplier}\sqrt{\sigma_u^2 + \sigma_e^2}}.
\item \code{lines}: named numeric vector with entries \code{lower}, \code{mean}, and
\code{upper}.
\item \code{CI.lines}: named numeric vector containing Wald confidence
interval bounds for the bias and both LoA endpoints:
\code{mean.diff.ci.lower}, \code{mean.diff.ci.upper},
\code{lower.limit.ci.lower}, \code{lower.limit.ci.upper},
\code{upper.limit.ci.lower}, \code{upper.limit.ci.upper}.
\item \code{loa_multiplier}: scalar LoA multiplier actually used.
\item \code{critical.diff}: scalar LoA half-width
\eqn{\texttt{loa\_multiplier} \times \texttt{sd\_loa}}.
\item \code{include_slope}: logical, copied from the call.
\item \code{beta_slope}: proportional-bias slope on the original paired-mean
scale when \code{include_slope = TRUE}; otherwise \code{NA}.
\item \code{sigma2_subject}: estimated variance of the subject-level random
intercept on paired differences.
\item \code{sigma2_resid}: estimated residual variance on paired differences.
\item \code{use_ar1}: logical, copied from the call.
\item \code{residual_model}: either \code{"ar1"} or \code{"iid"}, indicating the final
residual structure actually used.
\item \code{ar1_rho}: AR(1) correlation actually used in the final fit when
\code{residual_model == "ar1"}; otherwise \code{NA}.
\item \code{ar1_estimated}: logical indicating whether \code{ar1_rho} was
estimated internally (\code{TRUE}) or supplied by the user (\code{FALSE}) when the
final residual model is AR(1); otherwise \code{NA}.
}

The confidence level is stored as \code{attr(x, "conf.level")}.

\strong{If \eqn{\ge 3} methods are supplied}, the returned
\code{"ba_repeated_matrix"} object is a list with components:
\itemize{
\item \code{bias}: numeric \eqn{m \times m} matrix of model-based BA centres.
For indices \eqn{(j, k)} with \eqn{j < k}, \code{bias[j, k]} estimates
\eqn{\mathrm{method}_k - \mathrm{method}_j}. Thus the matrix orientation is
\strong{column minus row}, not row minus column. The diagonal is \code{NA}.
\item \code{sd_loa}: numeric \eqn{m \times m} matrix of LoA SDs,
\eqn{\sqrt{\sigma_u^2 + \sigma_e^2}}. This matrix is symmetric.
\item \code{loa_lower}, \code{loa_upper}: numeric \eqn{m \times m} matrices
of LoA endpoints corresponding to \code{bias}. These satisfy
\eqn{\texttt{loa\_lower}[j,k] = -\texttt{loa\_upper}[k,j]} and
\eqn{\texttt{loa\_upper}[j,k] = -\texttt{loa\_lower}[k,j]}.
\item \code{width}: numeric \eqn{m \times m} matrix of LoA widths,
\code{loa_upper - loa_lower}. This matrix is symmetric.
\item \code{n}: integer \eqn{m \times m} matrix giving the number of complete
subject-time pairs used for each analysed contrast. Pairs with fewer than
two complete matches are left as \code{NA} in the estimate matrices.
\item \code{mean_ci_low}, \code{mean_ci_high}: numeric \eqn{m \times m}
matrices of Wald confidence interval bounds for \code{bias}.
\item \code{loa_lower_ci_low}, \code{loa_lower_ci_high}: numeric
\eqn{m \times m} matrices of Wald confidence interval bounds for the lower
LoA.
\item \code{loa_upper_ci_low}, \code{loa_upper_ci_high}: numeric
\eqn{m \times m} matrices of Wald confidence interval bounds for the upper
LoA.
\item \code{slope}: optional numeric \eqn{m \times m} matrix of
proportional-bias slopes on the original paired-mean scale when
\code{include_slope = TRUE}; otherwise \code{NULL}. This matrix is antisymmetric in
sign because each fitted contrast is reversed across the transpose.
\item \code{methods}: character vector of method levels defining matrix row
and column order.
\item \code{loa_multiplier}: scalar LoA multiplier actually used.
\item \code{conf_level}: scalar confidence level used for the reported Wald
intervals.
\item \code{use_ar1}: logical, copied from the call.
\item \code{ar1_rho}: scalar equal to the user-supplied common \code{ar1_rho}
when \code{use_ar1 = TRUE} and a value was supplied; otherwise \code{NA}. This field
does \emph{not} store the per-pair estimated AR(1) parameters.
\item \code{residual_model}: character \eqn{m \times m} matrix whose entries
are \code{"ar1"}, \code{"iid"}, or \code{NA}, indicating the final residual structure used
for each pair.
\item \code{sigma2_subject}: numeric \eqn{m \times m} matrix of estimated
subject-level random-intercept variances.
\item \code{sigma2_resid}: numeric \eqn{m \times m} matrix of estimated
residual variances.
\item \code{ar1_rho_pair}: optional numeric \eqn{m \times m} matrix giving
the AR(1) correlation actually used for each pair when the final residual
model is \code{"ar1"}; otherwise \code{NA} for that entry. Present only when
\code{use_ar1 = TRUE}.
\item \code{ar1_estimated}: optional logical \eqn{m \times m} matrix
indicating whether the pair-specific \code{ar1_rho_pair} was estimated internally
(\code{TRUE}) or supplied by the user (\code{FALSE}) for entries whose final residual
model is \code{"ar1"}; otherwise \code{NA}. Present only when \code{use_ar1 = TRUE}.
\item \code{data_long}: canonical long-form data frame with columns
\code{.response}, \code{.subject}, \code{.method}, and \code{.time}
retained for pairwise plotting helpers.
\item \code{mapping}: named list mapping \code{response}, \code{subject},
\code{method}, and \code{time} to the canonical stored columns in
\code{data_long}.
}
}
\description{
Repeated-measures Bland-Altman (BA) analysis for method comparison based on a
mixed-effects model fitted to \strong{subject-time matched paired differences}.
The fitted model includes a subject-specific random intercept and, optionally,
an AR(1) residual correlation structure within subject.

The function accepts either exactly two methods or \eqn{\ge 3} methods.
With exactly two methods it returns a single fitted BA object. With
\eqn{\ge 3} methods it fits the same model to every unordered method pair and
returns pairwise matrices of results.

\strong{Required variables}
\itemize{
\item \code{response}: numeric measurements.
\item \code{subject}: subject identifier.
\item \code{method}: method label with at least two distinct levels.
\item \code{time}: replicate/time key used to form within-subject pairs.
}

For any analysed pair of methods, only records where both methods are present
for the same \code{subject} and integer-coerced \code{time} contribute to the
fit. Rows with missing values in any required field are excluded for that
analysed pair.
}
\details{
For a selected pair of methods \eqn{(a, b)}, the backend first forms complete
within-subject pairs at matched \code{subject} and integer-coerced
\code{time}. Let
\deqn{
d_{it} = y_{itb} - y_{ita},
\qquad
m_{it} = \frac{y_{ita} + y_{itb}}{2},
}
where \eqn{d_{it}} is the paired difference and \eqn{m_{it}} is the paired
mean for subject \eqn{i} at time/replicate \eqn{t}. Only complete
subject-time matches contribute to that pairwise fit.

If multiple rows are present for the same \code{subject}-\code{time}-\code{method}
combination within an analysed pair, the backend keeps the last encountered
value for that combination when forming the pair. The function therefore
implicitly assumes at most one observation per \code{subject}-\code{time}-\code{method}
cell for each analysed contrast.

The fitted model for each analysed pair is
\deqn{
d_{it} = \beta_0 + \beta_1 x_{it} + u_i + \varepsilon_{it},
}
where \eqn{x_{it} = m_{it}} if \code{include_slope = TRUE} and the term is omitted
otherwise; \eqn{u_i \sim \mathcal{N}(0, \sigma_u^2)} is a subject-specific
random intercept; and the within-subject residual vector satisfies
\eqn{\mathrm{Cov}(\varepsilon_i) = \sigma_e^2 R_i}.

When \code{use_ar1 = FALSE}, \eqn{R_i = I}. When \code{use_ar1 = TRUE}, the backend
works with the residual \emph{precision} matrix \eqn{C_i = R_i^{-1}} over
contiguous time blocks within subject and uses \eqn{\sigma_e^2 C_i^{-1}} as
the residual covariance.

\subsection{AR(1) residual structure}{
Within each subject, paired observations are ordered by integer-coerced
\code{time}. AR(1) correlation is applied only over strictly contiguous runs
satisfying \eqn{t_{k+1} = t_k + 1}. Gaps break the run. Negative times, and
any isolated positions not belonging to a contiguous run, are treated as
independent singletons.

For a contiguous run of length \eqn{L} and correlation parameter \eqn{\rho},
the block precision matrix is
\deqn{
C
=
\frac{1}{1-\rho^2}
\begin{bmatrix}
1      & -\rho &        &        &  \\
-\rho  & 1+\rho^2 & -\rho &      &  \\
        & \ddots & \ddots & \ddots & \\
        &        & -\rho & 1+\rho^2 & -\rho \\
        &        &       & -\rho & 1
\end{bmatrix},
}
with a very small ridge added to the diagonal for numerical stability.

If \code{use_ar1 = TRUE} and \code{ar1_rho} is supplied, that value is used after
validation and clipping to the admissible numerical range handled by the
backend.

If \code{use_ar1 = TRUE} and \code{ar1_rho = NA}, the backend estimates \code{rho}
separately for each analysed pair by:
\enumerate{
\item fitting the corresponding iid model;
\item computing a moments-based lag-1 estimate from detrended residuals
within contiguous blocks, used only as a seed; and
\item refining that seed by a short profile search over \code{rho} using the
profiled REML log-likelihood.
}

In the exported \code{ba_rm()} wrapper, if an AR(1) fit for a given analysed pair
fails specifically because the backend EM/GLS routine did not converge to
admissible finite variance-component estimates, the wrapper retries that pair
with iid residuals. If the iid refit succeeds, the final reported residual
model for that pair is \code{"iid"} and a warning is issued. Other AR(1) failures
are not simplified and are propagated as errors.
}

\subsection{Internal centring and scaling for the proportional-bias slope}{
When \code{include_slope = TRUE}, the paired mean regressor is centred and scaled
internally before fitting. Let \eqn{\bar m} be the mean of the observed paired
means. The backend chooses a scaling denominator from:
\itemize{
\item the sample SD;
\item the IQR-based scale \eqn{\mathrm{IQR}(m)/1.349};
\item the MAD-based scale \eqn{1.4826\,\mathrm{MAD}(m)}.
}
It uses the first of these that is not judged near-zero relative to the
largest finite positive candidate scale, under a threshold proportional to
\eqn{\sqrt{\epsilon_{\mathrm{mach}}}}. If all candidate scales are treated as
near-zero, the fit stops with an error because the proportional-bias slope is
not estimable on the observed paired-mean scale.

The returned \code{beta_slope} is back-transformed to the original paired-mean
scale. The returned BA centre is the fitted mean difference at the centred
reference paired mean \eqn{\bar m}, not the original-scale intercept
coefficient.
}

\subsection{Estimation}{
The backend uses a stabilised EM/GLS scheme.

Conditional on current variance components, the fixed effects are updated by
GLS using the marginal precision of the paired differences after integrating
out the random subject intercept. The resulting fixed-effect covariance used
in the confidence-interval calculations is the GLS covariance
\deqn{
\mathrm{Var}(\hat\beta \mid \hat\theta)
=
\left( \sum_i X_i^\top V_i^{-1} X_i \right)^{-1}.
}

Given updated fixed effects, the variance components are refreshed by EM using
the conditional moments of the subject random intercept and the residual
quadratic forms. Variance updates are ratio-damped and clipped to admissible
ranges for numerical stability.
}

\subsection{Reported BA centre and limits of agreement}{
The reported BA centre is always model-based.

When \code{include_slope = FALSE}, it is the fitted intercept of the paired-
difference mixed model.

When \code{include_slope = TRUE}, it is the fitted mean difference at the centred
reference paired mean used internally by the backend.

The reported limits of agreement are
\deqn{
\mu_0 \pm \texttt{loa\_multiplier}\sqrt{\sigma_u^2 + \sigma_e^2},
}
where \eqn{\mu_0} is the reported model-based BA centre. These LoA are for a
single new paired difference from a random subject under the fitted model.

Under the implemented parameterisation, AR(1) correlation affects the
off-diagonal within-subject covariance structure and therefore the estimation
of the model parameters and their uncertainty, but not the marginal variance
of a single paired difference. Consequently \code{rho} does not appear explicitly
in the LoA point-estimate formula.
}

\subsection{Confidence intervals}{
The backend returns Wald confidence intervals for the reported BA centre and
for both LoA endpoints.

These intervals combine:
\itemize{
\item the conditional GLS uncertainty in the fixed effects at the fitted
covariance parameters; and
\item a delta-method propagation of covariance-parameter uncertainty from
the observed information matrix of the profiled REML log-likelihood.
}

The covariance-parameter vector is profiled on transformed scales:
log-variances for \eqn{\sigma_u^2} and \eqn{\sigma_e^2}, and, when \code{rho} is
estimated internally under AR(1), a transformed correlation parameter
mapped back by \eqn{\rho = 0.95\tanh(z)}.

Numerical central finite differences are used to approximate both the
observed Hessian of the profiled REML log-likelihood and the gradients of the
reported derived quantities. The resulting variances are combined and the
final intervals are formed with the normal quantile corresponding to
\code{conf_level}.
}

\subsection{Exactly two methods versus \eqn{\ge 3} methods}{
With exactly two methods, at least two complete subject-time pairs are
required; otherwise the function errors.

With \eqn{\ge 3} methods, the function analyses every unordered pair of method
levels. For a given pair with fewer than two complete subject-time matches,
that contrast is skipped and the corresponding matrix entries remain \code{NA}.

For a fitted contrast between methods in matrix positions \eqn{(j, k)} with
\eqn{j < k}, the stored orientation is:
\deqn{
\texttt{bias}[j,k] \approx \mathrm{method}_k - \mathrm{method}_j.
}
Hence the transposed entry changes sign, while \code{sd_loa} and \code{width} are
symmetric.
}

\subsection{Identifiability and safeguards}{
Separate estimation of the residual and subject-level variance components
requires sufficient complete within-subject replication after pairing. If the
paired data are not adequate to separate these components, the fit stops with
an identifiability error.

If the model is conceptually estimable but no finite positive pooled
within-subject variance can be formed during initialisation, the backend uses
\eqn{0.5 \times v_{\mathrm{ref}}} only as a temporary positive starting value
for the EM routine and records a warning string in the backend output. The
exported wrapper does not otherwise modify the final estimates.

If the EM/GLS routine fails to reach admissible finite variance-component
estimates, the backend throws an explicit convergence error rather than
returning fallback estimates.
}
}
\examples{
# -------- Simulate repeated-measures data --------
set.seed(1)

# design (no AR)
# subjects
S   <- 30L
# replicates per subject
Tm  <- 15L
subj <- rep(seq_len(S), each = Tm)
time <- rep(seq_len(Tm), times = S)

# subject signal centered at 0 so BA "bias" won't be driven by the mean level
mu_s  <- rnorm(S, mean = 0, sd = 8)
# constant within subject across replicates
true  <- mu_s[subj]

# common noise (no AR, i.i.d.)
sd_e <- 2
e0   <- rnorm(length(true), 0, sd_e)

# --- Methods ---
# M1: signal + noise
y1 <- true + e0

# M2: same precision as M1; here identical so M3 can be
#     almost perfectly the inverse of both M1 and M2
y2 <- y1 + rnorm(length(true), 0, 0.01)

# M3: perfect inverse of M1 and M2
y3 <- -y1   # = -(true + e0)

# M4: unrelated to all others (pure noise, different scale)
y4 <- rnorm(length(true), 3, 6)

data <- rbind(
  data.frame(y = y1, subject = subj, method = "M1", time = time),
  data.frame(y = y2, subject = subj, method = "M2", time = time),
  data.frame(y = y3, subject = subj, method = "M3", time = time),
  data.frame(y = y4, subject = subj, method = "M4", time = time)
)
data$method <- factor(data$method, levels = c("M1","M2","M3","M4"))

# quick sanity checks
with(data, {
  Y <- split(y, method)
  round(cor(cbind(M1 = Y$M1, M2 = Y$M2, M3 = Y$M3, M4 = Y$M4)), 3)
})

# Run BA (no AR)
ba4 <- ba_rm(
  data = data,
  response = "y", subject = "subject", method = "method", time = "time",
  loa_multiplier = 1.96, conf_level = 0.95,
  include_slope = FALSE, use_ar1 = FALSE
)
summary(ba4)
estimate(ba4)
tidy(ba4)
confint(ba4)
plot(ba4)

# -------- Simulate repeated-measures with AR(1) data --------
set.seed(123)
S <- 40L                      # subjects
Tm <- 50L                     # replicates per subject
methods <- c("A","B","C")     # N = 3 methods
rho <- 0.4                    # AR(1) within-subject across time

ar1_sim <- function(n, rho, sd = 1) {
  z <- rnorm(n)
  e <- numeric(n)
  e[1] <- z[1] * sd
  if (n > 1) for (t in 2:n) e[t] <- rho * e[t-1] + sqrt(1 - rho^2) * z[t] * sd
  e
}

# Subject baseline + time trend (latent "true" signal)
subj <- rep(seq_len(S), each = Tm)
time <- rep(seq_len(Tm), times = S)
# subject effects
mu_s  <- rnorm(S, 50, 7)
trend <- rep(seq_len(Tm) - mean(seq_len(Tm)), times = S) * 0.8
true  <- mu_s[subj] + trend

# Method-specific biases (B has +1.5 constant; C has slight proportional bias)
bias  <- c(A = 0, B = 1.5, C = -0.5)
# proportional component on "true"
prop  <- c(A = 0.00, B = 0.00, C = 0.10)

# Build long data: for each method, add AR(1) noise within subject over time
make_method <- function(meth, sd = 3) {
  e <- unlist(lapply(split(seq_along(time), subj),
                     function(ix) ar1_sim(length(ix), rho, sd)))
  y <- true * (1 + prop[meth]) + bias[meth] + e
  data.frame(y = y, subject = subj, method = meth, time = time,
             check.names = FALSE)
}

data <- do.call(rbind, lapply(methods, make_method))
data$method <- factor(data$method, levels = methods)

# -------- Repeated BA (pairwise matrix) ---------------------
baN <- ba_rm(
  response = data$y, subject = data$subject, method = data$method, time = data$time,
  loa_multiplier = 1.96, conf_level = 0.95,
  include_slope = FALSE,         # estimate proportional bias per pair
  use_ar1 = TRUE, ar1_rho = rho
)

# Matrices (row - column orientation)
print(baN)
summary(baN)
tidy(baN)

# Faceted BA scatter by pair
plot(baN, smoother = "lm", facet_scales = "free_y")

# -------- Two-method AR(1) path (A vs B only) ------------------------------
data_AB <- subset(data, method \%in\% c("A","B"))
baAB <- ba_rm(
  response = data_AB$y, subject = data_AB$subject,
  method = droplevels(data_AB$method), time = data_AB$time,
  include_slope = FALSE, use_ar1 = TRUE, ar1_rho = 0.4
)
print(baAB)
plot(baAB)

}
\author{
Thiago de Paula Oliveira
}
