# Resampling, downsampling, and reorientation

This vignette shows how to:

- Resample an image into a new grid (`resample_to()` / `resample()`).
- Downsample 3D/4D data to coarser resolution (`downsample()`).
- Change orientation while keeping physical coordinates consistent (`reorient()`).

We’ll use the example NIfTI that ships with the package:

    demo_path <- system.file("extdata", "global_mask_v4.nii", package = "neuroim2")
    vol  <- read_vol(demo_path)  # 3D NeuroVol
    vec4 <- read_vec(demo_path)  # 4D NeuroVec

    sp   <- space(vol)
    dim(vol)
    #> [1] 64 64 25
    spacing(vol)
    #> [1] 3.5 3.5 3.7

## 1. Resampling to a new space

`resample_to()` is a convenience wrapper around the S4 `resample()` methods that accepts human‑readable interpolation names.

You specify a target grid (`NeuroSpace` or `NeuroVol`) and choose `"nearest"`, `"linear"`, or `"cubic"` interpolation:

    # Create a target space with 2× smaller voxels in each dimension
    sp_fine <- NeuroSpace(
      dim    = sp@dim * 2L,
      spacing = sp@spacing / 2,
      origin  = sp@origin,
      trans   = trans(vol)
    )

    vol_fine_lin <- resample_to(vol, sp_fine, method = "linear")
    dim(vol_fine_lin)
    #> [1] 128 128  50
    spacing(vol_fine_lin)
    #> [1] 1.75 1.75 1.85

Typical patterns:

- Use `"nearest"` when resampling label or mask images.
- Use `"linear"` or `"cubic"` for continuous data (e.g. intensities, statistics).

You can also call `resample(source, target, interpolation = 0/1/3)` directly if you prefer numeric codes.

## 2. Downsampling to coarser resolution

When you want fewer voxels (e.g. to speed up analysis or plotting) but don’t need arbitrarily defined target grids, use `downsample()` on a `NeuroVec` or `NeuroVol`.

### 2.1 Downsample a 4D NeuroVec

    # Downsample by a factor of 0.5 in each spatial dimension
    vec_down_factor <- downsample(vec4, factor = 0.5)

    dim(vec4)
    #> [1] 64 64 25  4
    dim(vec_down_factor)
    #> [1] 32 32 12  4
    spacing(vec4)
    #> [1] 3.5 3.5 3.7
    spacing(vec_down_factor)
    #> [1] 7.00000 7.00000 7.70833

You can also specify a target spacing or output dimensions:

    # Target spacing (mm)
    vec_down_spacing <- downsample(vec4, spacing = c(4, 4, 4))

    # Target spatial dimensions
    vec_down_outdim  <- downsample(vec4, outdim = c(32, 32, 16))
    #> Warning in calculate_downsample_dims(current_dims, current_spacing, spacing, :
    #> Output dimensions do not preserve aspect ratios. Using uniform scaling based on
    #> smallest dimension.

Exactly one of `factor`, `spacing`, or `outdim` must be supplied. The current implementation uses a simple box‑averaging scheme in space.

### 2.2 Downsample a 3D NeuroVol

The same interface applies to volumes:

    vol_down_factor <- downsample(vol, factor = 0.5)

    dim(vol)
    #> [1] 64 64 25
    dim(vol_down_factor)
    #> [1] 32 32 12

This is useful for coarse previews or multi‑scale workflows.

## 3. Reorienting images

`reorient()` updates the mapping between voxel indices and physical coordinates without changing the raw data array. This is helpful when you want a canonical orientation (e.g. RAS) or need to match another dataset’s axis directions.

For `NeuroSpace`, you supply three axis codes:

    sp_lpi <- sp                      # assume input is LPI‑like
    sp_ras <- reorient(sp_lpi, c("R", "A", "S"))

    sp_lpi
    #>
    #>  NeuroSpace Object
    #>
    #>  >> Dimensions
    #>   Grid Size: 64 x 64 x 25
    #>   Memory:   5.9 KB
    #>
    #>  >> Spatial Properties
    #>   Spacing:   3.50 x 3.50 x 3.70 mm
    #>   Origin:    112.00 x -108.00 x -46.20 mm
    #>
    #>  >> Anatomical Orientation
    #>   X: Right-to-Left  |  Y: Posterior-to-Anterior  |  Z: Inferior-to-Superior
    #>
    #>  >> World Transformation
    #>   Forward (Voxel to World):
    #>     -3.500  0.000  -0.000   112.000
    #>  0.000  3.500  -0.000  -108.000
    #>  0.000  0.000   3.700   -46.200
    #>  0.000  0.000   0.000     1.000
    #>   Inverse (World to Voxel):
    #>     -0.286  0.000  0.000  32.000
    #>  0.000  0.286  0.000  30.857
    #>  0.000  0.000  0.270  12.486
    #>  0.000  0.000  0.000   1.000
    #>
    #>  >> Bounding Box
    #>   Min Corner: -108.5, -108.0, -46.2 mm
    #>   Max Corner: 112.0, 112.5, 42.6 mm
    #>
    #> ==================================================
    sp_ras
    #>
    #>  NeuroSpace Object
    #>
    #>  >> Dimensions
    #>   Grid Size: 64 x 64 x 25
    #>   Memory:   5.9 KB
    #>
    #>  >> Spatial Properties
    #>   Spacing:   3.50 x 3.50 x 3.70 mm
    #>   Origin:    -112.00 x 108.00 x 46.20 mm
    #>
    #>  >> Anatomical Orientation
    #>   X: Right-to-Left  |  Y: Posterior-to-Anterior  |  Z: Inferior-to-Superior
    #>
    #>  >> World Transformation
    #>   Forward (Voxel to World):
    #>     3.500   0.000   0.000  -112.000
    #> 0.000  -3.500   0.000   108.000
    #> 0.000   0.000  -3.700    46.200
    #> 0.000   0.000   0.000     1.000
    #>   Inverse (World to Voxel):
    #>     0.286   0.000   0.000  32.000
    #> 0.000  -0.286   0.000  30.857
    #> 0.000   0.000  -0.270  12.486
    #> 0.000   0.000   0.000   1.000
    #>
    #>  >> Bounding Box
    #>   Min Corner: -112.0, -112.5, -42.6 mm
    #>   Max Corner: 108.5, 108.0, 46.2 mm
    #>
    #> ==================================================

For `NeuroVol` / `NeuroVec`, you typically reorient via their space:

    vol_ras <- NeuroVol(as.array(vol), sp_ras)
    dim(vol_ras)
    #> [1] 64 64 25
    spacing(vol_ras)
    #> [1] 3.5 3.5 3.7

Note that `reorient()` preserves physical positions; it only changes how grid indices are interpreted in space. Coordinate transforms (`coord_to_grid`, `grid_to_coord`) automatically respect the new orientation.

## 4. Putting it together

Common combinations:

- Use `resample_to()` when you need to match a specific template grid (e.g. MNI space or another subject’s image).
- Use `downsample()` when you just want fewer voxels while preserving overall FOV and orientation.
- Use `reorient()` when you want a consistent anatomical convention (RAS/LPI) across images without resampling.