---
title: Advanced Split, Map, and Reduce
date: '`r Sys.Date()`'
output: rmarkdown::html_vignette
vignette: |
  %\VignetteIndexEntry{Advanced Split, Map, and Reduce}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
params:
  family: red
  preset: homage
css: albers.css
resource_files:
- albers.css
- albers.js
includes:
  in_header: |-
    <script src="albers.js"></script>
    <script>document.addEventListener('DOMContentLoaded',function(){document.body.classList.add('palette-red');});</script>

---

```{r, echo = FALSE, message = FALSE}
knitr::opts_chunk$set(collapse = T, comment = "#>", fig.alt = 'Plot output', message = FALSE, warning = FALSE)
suppressPackageStartupMessages({
  library(purrr)
  library(neuroim2)
})
options(mc.cores=1)
```

This article is now the older, lower-level companion to
`vignette("AnalysisWorkflows")`. Read that vignette first if you want the
shortest path to ROI extraction, searchlights, and split-map-reduce patterns.
Use this article when you want more raw examples of composing those operations
with `purrr` and direct list-processing.

# Pipelining operations with a functional style

`neuroim2` exposes several operations that split an image into pieces, let you
map a function over those pieces, and then reduce the results back into a
vector, list, or derived image.

The ROI- and searchlight-based split-map-reduce patterns now live in
`vignette("AnalysisWorkflows")`. This article keeps the lower-level iteration
helpers that are still useful when you want to split by slices, volumes, or
voxel vectors directly.

```{r}
file_name <- system.file("extdata", "global_mask_v4.nii", package = "neuroim2")
vol <- read_vol(file_name)
```

## Mapping a function over every slice of a `NeuroVol`

Suppose we want to split up an image volume by slice and apply a function to each slice. We can use the `slices` function to achieve this as follows:

```{r}
slice_means <- vol %>% slices %>% map_dbl(~ mean(.))
plot(slice_means, type='l', ylab="mean intensity", xlab="slice number")
```

## Mapping a function over each volume of a `NeuroVec` object

```{r}
vec <- concat(vol,vol,vol,vol,vol)
vec
mean_vec <- vec %>% vols %>% map_dbl(~ mean(.))
sd_vec <- vec %>% vols %>% map_dbl(~ sd(.))
stopifnot(length(mean_vec) == dim(vec)[4])
stopifnot(length(sd_vec) == dim(vec)[4])
```

## Mapping a function over each vector of a `NeuroVec` object

```{r}
vec <- concat(vol,vol,vol,vol,vol)
vec
mean_vol <- vec %>% vectors() %>% map_dbl(~ mean(.)) %>% NeuroVol(., space=space(vol))
stopifnot(all(dim(mean_vol) == dim(vol)))
```
