% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/imaging-registration-native.R
\name{register_volume3d}
\alias{register_volume3d}
\title{Native 3D volume registration (\code{'rigid'}, \code{'affine'}, or \code{'SyN'})}
\usage{
register_volume3d(
  source,
  target,
  source_vox2ras = NULL,
  target_vox2ras = NULL,
  source_mask = NULL,
  target_mask = NULL,
  source_points = NULL,
  target_points = NULL,
  points_weight = 0.5,
  weights = NULL,
  type = c("rigid", "affine", "syn", "syn_only"),
  metric = "mattes",
  shrink_factors = c(4, 2, 1),
  smoothing_sigmas = c(2, 1, 0),
  iterations = c(1000, 500, 250),
  sampling_rate = 0.2,
  interpolation = "trilinear",
  number_of_bins = 32L,
  seed = 1L,
  init_transform = NULL,
  syn_iterations = c(40, 20, 0),
  syn_sigma = 3,
  verbose = TRUE
)
}
\arguments{
\item{source}{the moving volume to be aligned, a 3D array (for example a
\code{'CT'}); the result transform maps \code{target} into this image's space.
May also be a \code{list} of already co-registered 3D arrays (multiple
modalities such as \code{'T1'}, \code{'T2'}, an atlas constraint); all source
channels must share the same dimensions and \code{vox2ras}}

\item{target}{the fixed/reference volume to align to, a 3D array (for example
a \code{'MRI'}), or a \code{list} of co-registered arrays matching
\code{source} channel-for-channel}

\item{source_vox2ras, target_vox2ras}{4x4 (or 3x4) matrices mapping the
0-indexed voxel coordinate (column-row-slice, \code{'C'}-style starting from
0, complying with \code{'NIfTI'}) to the \verb{RAS} coordinate system; if
\code{NULL}, the function looks for a \code{"vox2ras"} attribute on the array}

\item{source_mask, target_mask}{optional 3D mask arrays restricting where the
metric is evaluated; default \code{NULL} (no mask, evaluate everywhere). A
\code{target_mask} (on the target/fixed grid, same dimensions as
\code{target}) limits which target voxels drive the registration; a
\code{source_mask} (on the source/moving grid) drops samples that map outside
it. Non-zero voxels are included. Besides focusing the alignment on a region
of interest, masks speed things up by skipping background: the linear stage
samples only inside the mask, and the deformable stage skips warping voxels
outside the (dilated) mask. One mask per grid, shared across channels}

\item{source_points, target_points}{optional \code{N x 3} matrices of
corresponding landmark coordinates that add a surface/landmark term to the
\strong{deformable} (\code{"syn"}/\code{"syn_only"}) stage; default
\code{NULL} (no term). Row \code{i} of \code{target_points} (in the
target/fixed \verb{RAS}) and row \code{i} of \code{source_points} (in the
source/moving \verb{RAS}) must be the \emph{same} anatomical location, for
example corresponding cortical-surface vertices from a \code{'FreeSurfer'}
spherical registration. The term pulls the warp of each target point onto its
source correspondent, recovering cortical folding (\verb{gyrification})
that the intensity metric blurs over, while the image metric still drives
deep-brain \verb{subcortical} structures. Must be supplied together with
equal row counts. \strong{Points must be in the same \verb{RAS} frame as
\code{source_vox2ras}/\code{target_vox2ras}} (note \code{'FreeSurfer'}
surfaces use \verb{surface/tkr} \verb{RAS}, which differs from scanner
\verb{RAS} by \code{c_ras})}

\item{points_weight}{relative weight of the landmark term against the image
metric in the deformable stage; default \code{0.5}. Larger values follow the
landmarks more closely. The sparse landmark force is attenuated by
\code{syn_sigma} smoothing, so this typically needs tuning for a given point
count and spacing}

\item{weights}{optional numeric weights, one per source/target pair,
controlling each channel's contribution to the deformable cost; default is
equal weighting. Weights are normalized internally to sum to 1. Only the
deformable (\code{"syn"}/\code{"syn_only"}) stage is multivariate; the linear
stage always uses the first (primary) pair}

\item{type}{type of transform to estimate; one of \code{'rigid'} (6 degrees
of freedom), \code{'affine'} (12), \code{"syn"} (\verb{affine} followed
by a \verb{SDR} - symmetric \verb{diffeomorphic} deformation), or
\code{'syn_only'} (\verb{deformable} stage only — no \verb{affine} is
estimated; \code{init_transform} is used directly as the starting
\verb{affine}, useful when you already have a good linear alignment)}

\item{metric}{similarity metric: \code{"mattes"} (Mattes mutual information,
the default, best for cross-modal such as \code{'CT'}-\code{'MRI'}),
\code{"cc"} (normalized cross-correlation, for same-modality), or
\code{"meansquares"} (mean squared intensity difference). With multiple
channels, supply either a single metric (used for every pair) or a vector
with one metric per source/target pair}

\item{shrink_factors}{integer down-sampling factors, one per resolution level
(coarsest first); default \code{c(4, 2, 1)}}

\item{smoothing_sigmas}{Gaussian smoothing applied at each level, in voxels,
same length as \code{shrink_factors}; default \code{c(2, 1, 0)}}

\item{iterations}{maximum optimizer iterations per level; default
\code{c(1000, 500, 250)}}

\item{sampling_rate}{fraction of fixed voxels sampled to evaluate the metric
(speeds up large volumes); default \code{0.2}}

\item{interpolation}{output interpolation used when warping each modality
onto the target grid: \code{'trilinear'} (default), \code{'nearest'} (keeps
label or segmentation values intact), or \code{"bspline"} (cubic
\verb{Catmull-Rom}, higher quality, slower). Like \code{metric}, supply a
single value (applied to every channel) or one per source/target pair. This
affects only the returned warped images, never the optimization's internal
sampling (always \code{'trilinear'}, so every channel still produces
smooth gradients)}

\item{number_of_bins}{number of histogram bins for the \code{"mattes"}
metric; default \code{32}}

\item{seed}{random seed for the voxel sampler, for reproducibility}

\item{init_transform}{optional 4x4 initial \verb{RAS}-to-\verb{RAS}
transform (fixed to moving) to start from}

\item{syn_iterations, syn_sigma}{deformable stage controls (only used when
\code{type = "syn"} or \code{"syn_only"}): per-level iteration counts and the
Gaussian regularization sigma (in voxels) applied to the update field. Both
are recycled to the number of levels, so \code{syn_sigma} may be a vector to
vary the regularization per stage (e.g. \code{c(3, 3, 1)} to relax it at the
finest level for sharper detail)}

\item{verbose}{logical; if \code{TRUE} (default) print per-level and
per-iteration progress to the console, including the current stage, shrink
factor, smoothing sigma, cost metric, and step size (linear) or maximum
displacement (deformable); useful to monitor convergence on large volumes}
}
\value{
A list with:
\describe{
\item{\code{transform}}{the estimated 4x4 \verb{RAS}-to-\verb{RAS} linear
transform mapping \code{target} (fixed) coordinates to \code{source} (moving)
coordinates}
\item{\code{image}}{the (primary) \code{source} resampled onto the
\code{target} grid}
\item{\code{images}}{a list with every source channel resampled onto the
\code{target} grid using its own \code{interpolation}; \code{image} is the
first element. For single-image input this is a length-1 list}
\item{\code{forward_field},\code{inverse_field}}{(only for \code{"syn"}) the
deformation fields}
\item{\code{metric_trace}}{the metric value across optimizer iterations}
\item{\code{type},\code{metric}}{echoes of the inputs}
}
}
\description{
Self-contained image registration for 3D volumes, implemented purely in
\pkg{RcppEigen} (no other external registration library). It mirrors the
core behavior of \pkg{'ANTs'} \code{antsRegistration}: a multi-resolution,
physical-shift scaled gradient-descent optimizer driving a similarity metric,
working entirely in the anatomical \verb{RAS} (right-anterior-superior)
space. Each volume carries its own \code{vox2ras} (0-indexed voxel index to
anatomical \verb{RAS}) \eqn{4\times 4} transform, so volumes with
different sampling, orientation, or field of view are aligned correctly.
}
\examples{
\donttest{

# --- synthetic same-modality example -------------------------------------
nd <- c(50, 50, 50)
vox2ras <- diag(4); vox2ras[1:3, 4] <- -25
blob <- function(cx, cy, cz, s = 6) {
  g <- expand.grid(x = 0:(nd[1]-1), y = 0:(nd[2]-1), z = 0:(nd[3]-1))
  array(exp(-((g$x-cx)^2 + (g$y-cy)^2 + (g$z-cz)^2) / (2*s^2)), nd)
}
target <- blob(25, 25, 25)
source <- blob(28, 23, 26)            # shifted by a known (3, -2, 1) mm

res <- register_volume3d(
  source, target,
  source_vox2ras = vox2ras, target_vox2ras = vox2ras,
  type = "rigid", metric = "cc"
)
res$transform[1:3, 4]                 # ~ c(3, -2, 1)


# --- multimodal registration (several co-registered channels) ------------
# Two aligned modalities (e.g. a T1 and a T2) jointly drive the deformable
# stage. Each pair may use its own metric, and `weights` set their relative
# influence (normalized internally to sum to 1). All source channels must
# share a grid; likewise all target channels.
t1_target <- blob(25, 25, 25, s = 6)
t2_target <- blob(25, 25, 25, s = 9)  # same anatomy, different contrast
t1_source <- blob(27, 24, 26, s = 6)  # both channels share the same warp
t2_source <- blob(27, 24, 26, s = 9)

res_mm <- register_volume3d(
  source = list(t1_source, t2_source),
  target = list(t1_target, t2_target),
  source_vox2ras = vox2ras, target_vox2ras = vox2ras,
  weights = c(2, 1),                  # T1 counts twice as much as T2
  metric = c("mattes", "cc"),         # one metric per channel
  type = "syn"
)
res_mm$transform[1:3, 4]

}
}
\seealso{
\code{\link{apply_transform3d}}, \code{\link{resample_3d_volume}}
}
