---
title: Working with TemplateFlow in neuroatlas
author: neuroatlas Dev Team
date: '`r Sys.Date()`'
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Working with TemplateFlow in neuroatlas}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
params:
  family: red
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 setup, include = FALSE, eval = TRUE}
if (requireNamespace("ggplot2", quietly = TRUE) && requireNamespace("albersdown", quietly = TRUE)) ggplot2::theme_set(albersdown::theme_albers(params$family))
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  echo = TRUE,
  eval = FALSE # Default to FALSE to avoid network-heavy calls during build
)

# Load package and detect if TemplateFlow is available so we can
# selectively evaluate a few chunks with real output when feasible.
suppressWarnings(suppressMessages({
  library(neuroatlas)
}))

templateflow_ok <- FALSE
try({
  templateflow_ok <- reticulate::py_available(initialize = TRUE) &&
    reticulate::py_module_available("templateflow")
}, silent = TRUE)
```

## Introduction

[TemplateFlow](https://www.templateflow.org/) is a repository of curated neuroimaging templates and atlases, accessible via a Python client. The `neuroatlas` package provides an R interface to TemplateFlow, allowing you to easily discover, download, and use these resources within your R workflows.

This vignette provides a guide to using the TemplateFlow functionalities in `neuroatlas`.

## Getting Started: The `templateflow` Object

The main entry point for interacting with TemplateFlow is by creating a `templateflow` interface object. This object manages the connection to the Python API and caching configurations.

```{r create_tf_object, eval = FALSE}
# Create a templateflow interface object
tf <- create_templateflow()
print(tf)
```

If Python or the templateflow module are not available, you'll need to install them first:

```{r install_tf, eval = FALSE}
# Install the Python templateflow package
install_templateflow()
```

Running `print(tf)` (if `tf` is successfully created) will show you:
- The local cache path where TemplateFlow files will be stored. `neuroatlas` sets this up in a user-specific directory (e.g., `~/.cache/neuroatlas/templateflow` on Linux).
- The status of the connection to the Python API.
- A few examples of available templates and their total count.

Output might look like:
```
#> <neuroatlas TemplateFlow Interface>
#>   Cache Path:  /Users/youruser/Library/Caches/org.R-project.R/R/neuroatlas/templateflow 
#>   API Status:  Connected (Python API handle initialized) 
#>   Available Templates (Examples):  AMYGDALA, ARA, BRODMANN, CHARITE, Fischer344, ... (Total: 76)
```
(Note: The exact cache path and template list may vary.)

The underlying Python TemplateFlow library uses the `TEMPLATEFLOW_HOME` environment variable to determine its storage location. `neuroatlas` attempts to set this to its managed cache path to centralize downloads.

## Discovering Templates and Metadata

Before fetching files, you might want to see what's available.

### Listing Available Template Spaces

Use `tflow_spaces()` to get a list of all top-level template space identifiers:

```{r list_templates, eval = templateflow_ok}
# List all available template spaces
all_templates <- tflow_spaces()
print(head(all_templates))
cat("Total templates available:", length(all_templates), "\n")
```
(If nothing prints here during build, see the note below.)

```{r list_templates_note, eval = !templateflow_ok}
cat("TemplateFlow was not available during vignette build.\n")
cat("Run the chunk locally to see your real template list.\n")
```

You can also filter this list with a pattern (regular expression):
```{r list_templates_pattern, eval = templateflow_ok}
# Find all MNI templates
mni_templates <- tflow_spaces(pattern = "MNI")
print(mni_templates)
```
```{r list_templates_pattern_note, eval = !templateflow_ok}
cat("TemplateFlow was not available during vignette build.\n")
cat("Run this chunk locally to see matching MNI spaces.\n")
```

### Discovering Volumetric Templates

Use `tflow_files()` to query available volumetric files within a template space:

```{r discover_volumetric, eval = FALSE}
# Find all T1w images for MNI space
mni_t1w_files <- tflow_files(
  space = "MNI152NLin2009cAsym",
  query_args = list(suffix = "T1w")
)
print(mni_t1w_files)

# Find brain masks at specific resolution
mni_masks <- tflow_files(
  space = "MNI152NLin2009cAsym",
  query_args = list(suffix = "mask", desc = "brain", resolution = "1")
)
print(mni_masks)

# Find tissue probability maps (GM, WM, CSF)
mni_probseg <- tflow_files(
  space = "MNI152NLin2009cAsym",
  query_args = list(suffix = "probseg")
)
print(mni_probseg)

# Find all files at 2mm resolution
mni_2mm <- tflow_files(
  space = "MNI152NLin2009cAsym",
  query_args = list(resolution = "2")
)
print(mni_2mm)

# Find atlas/parcellation files
mni_atlases <- tflow_files(
  space = "MNI152NLin2009cAsym",
  query_args = list(suffix = "dseg")  # discrete segmentation
)
print(mni_atlases)
```

Common volumetric query parameters:
- `suffix`: "T1w", "T2w", "mask", "probseg", "dseg"
- `desc`: "brain", "head", or specific descriptions
- `resolution`: "1", "2", "01", "02" (template-dependent)
- `label`: "GM", "WM", "CSF" (for probseg files)
- `atlas`: atlas name (e.g., "Schaefer2018")

This function returns a character vector of full paths to the files that TemplateFlow has cached (downloading them if needed).

### Discovering Surface Templates

TemplateFlow includes surface geometry files for templates like `fsLR` and `fsaverage`. Here's how to discover what's available:

```{r discover_surfaces, eval = FALSE}
# Find surface-related template spaces
tflow_spaces(pattern = "fs")
#> [1] "fsLR"      "fsaverage"

# List available surface files for fsLR
# Filter by hemisphere
fslr_left <- tflow_files("fsLR", query_args = list(hemi = "L"))
print(head(fslr_left))

# Filter by surface type and density
fslr_midthick <- tflow_files("fsLR", query_args = list(
  suffix = "midthickness",
  hemi = "L",
  density = "32k"
))
print(fslr_midthick)

# List fsaverage surfaces
fsavg_pial <- tflow_files("fsaverage", query_args = list(
  suffix = "pial",
  hemi = "L"
))
print(fsavg_pial)
```

Common surface query parameters:
- `hemi`: "L" or "R" for hemisphere
- `density`: "32k", "164k", etc. (template-dependent)
- `suffix`: surface type - "pial", "white", "midthickness", "inflated", "sphere"
- `resolution`: "06" for fsaverage6, etc.

## Troubleshooting

If you encounter issues listing templates or fetching files:

- Check Python and TemplateFlow availability: `neuroatlas::check_templateflow()`
- Install or repair the Python environment: `neuroatlas::install_templateflow()`
- Network hiccups can prevent metadata fetches; if resolutions cannot be retrieved, `neuroatlas` skips that check with a warning.
- For Python-side errors, inspect `reticulate::py_last_error()` after a failure.

## Fetching Templates with `get_template()`

The primary function for fetching template files is `get_template()`. It provides a flexible R interface to the TemplateFlow archive.

```{r get_template_setup, echo=FALSE, eval=TRUE}
# For vignette build, use a placeholder if we can't eval real calls
mock_neurovol <- function(name = "mock_vol") {
  vol <- list(name = name, data = array(0, dim=c(2,2,2)))
  class(vol) <- c("NeuroVol", "array") # simplified
  vol
}
```

### Basic Retrieval (Volumetric Data)

To get the default MNI T1-weighted brain template (1mm resolution):
```{r get_default_template, eval = FALSE}
# Get the default template (MNI152NLin2009cAsym T1w brain at 1mm)
mni_t1w <- get_template() 
print(mni_t1w)
```
For this vignette, we'll simulate the object:
```{r get_default_template_mock, echo=FALSE, eval=TRUE}
mni_t1w <- mock_neurovol("MNI152NLin2009cAsym_T1w")
print(mni_t1w$name) # Printing just name for brevity
```

To fetch a specific template space, suffix, and resolution:
```{r get_specific_template, eval = FALSE}
# Get MNI T1w template at 2mm resolution
mni_t1w_res2 <- get_template(
  space = "MNI152NLin2009cAsym", 
  suffix = "T1w", 
  resolution = "2" # or 2
)
print(mni_t1w_res2)
```

### Fetching Other Variants (e.g., Masks)

You can specify other TemplateFlow entities like `desc` (description) and `label`.
```{r get_mask, eval = FALSE}
# Get brain mask for MNI template
mni_brain_mask <- get_template(
  space = "MNI152NLin2009cAsym",
  desc = "brain", # 'brain' for brain masks
  suffix = "mask",
  resolution = "1"
)
print(mni_brain_mask)
```

### Tissue Probability (GM/WM/CSF)

For tissue probability maps, use `variant = "probseg"` and set `label` (e.g., `"GM"`, `"WM"`, `"CSF"`).
Do not set `desc` for these — it’s determined by `suffix` + `label`.

```{r get_probseg, eval = FALSE}
# Gray matter probability map at 1mm
mni_gm_prob <- get_template(
  space = "MNI152NLin2009cAsym",
  variant = "probseg",
  label = "GM",
  resolution = "1"
)
print(mni_gm_prob)

# File path only
gm_path <- get_template(
  space = "MNI152NLin2009cAsym",
  variant = "probseg",
  label = "GM",
  path_only = TRUE
)
print(gm_path)
```

### Getting File Paths Only

If you only need the path to the file (e.g., for use with other tools), set `path_only = TRUE`:
```{r get_path_only, eval = FALSE}
# Get just the file path, not the loaded NeuroVol object
mni_t1w_path <- get_template(
  space = "MNI152NLin2009cAsym", 
  suffix = "T1w", 
  path_only = TRUE
)
print(mni_t1w_path)
```
Example output (path will vary):
```
[1] "/Users/youruser/Library/Caches/org.R-project.R/R/neuroatlas/templateflow/tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-01_T1w.nii.gz"
```

### Vectorized Retrieval

`get_template()` allows one of `space`, `variant`, `modality`, `resolution`, or `label` to be a vector, returning a named list of results.
```{r get_vectorized, eval = FALSE}
# Get both 1mm and 2mm resolution templates
t1_multi_res <- get_template(
  space = "MNI152NLin2009cAsym", 
  suffix = "T1w",
  resolution = c("1", "2") # Get both 1mm and 2mm
)
print(names(t1_multi_res))
# Access individual resolutions
print(t1_multi_res[["1"]]) # The 1mm NeuroVol
print(t1_multi_res[["2"]]) # The 2mm NeuroVol
```

### Key Parameters for `get_template()`
- `space`: Template identifier (e.g., "MNI152NLin2009cAsym").
- `variant`: High-level type (e.g., "brain", "mask", "probseg"). Used to infer `desc` and `suffix` for common cases.
- `modality`: Image type (e.g., "T1w", "T2w"). Used to infer `suffix`.
- `resolution`: Resolution (e.g., "1", "2", "01").
- `desc`: Specific TemplateFlow `desc` field.
- `suffix`: Specific TemplateFlow `suffix` field.
- `label`: E.g., for `variant="probseg"`, tissue labels like "GM", "CSF".
- `atlas`: E.g., "Schaefer2018" if fetching an atlas file.
- `...`: Other BIDS-like entities (e.g., `hemi="L"`, `den="32k"`) can be passed.

The function performs pre-flight validation checks for `space` and `resolution` against information available from TemplateFlow.

## Typed Helper Functions

For common tasks, `neuroatlas` provides convenient wrappers:

### Volumetric Data with `get_volume_template()`
```{r get_volume_helper, eval = FALSE}
# Get T1-weighted volume using the convenience function
t1_vol <- get_volume_template(
  template = "MNI152NLin2009cAsym", 
  type = "T1w", 
  resolution = "1"
)
print(t1_vol)
```
Supported `type`s include "T1w", "T2w", "bold", "probseg", "dseg".

### Surface Data with `get_surface_template()`
This helper typically returns file paths, as surfaces are often handled by specialized geometry software.
```{r get_surface_helper, eval = FALSE}
# Get fsLR left hemisphere pial surface
fslr_pial_L_path <- get_surface_template(
  template_id = "fsLR",       # e.g., "fsaverage", "fsLR"
  surface_type = "pial",      # e.g., "pial", "white", "inflated"
  hemi = "L",                 # "L" or "R"
  density = "32k"             # e.g., "32k", "164k" (for fsLR)
)
print(fslr_pial_L_path)
```
Example output (path will vary):
```
[1] "/Users/youruser/Library/Caches/org.R-project.R/R/neuroatlas/templateflow/tpl-fsLR/tpl-fsLR_den-32k_hemi-L_desc-pial_surf.gii"
```

## Downloading Templates to a Local Folder

TemplateFlow automatically caches files when you query them. If you want to copy templates to a specific folder (e.g., for use with other tools or sharing), here are some approaches:

### Copy from TemplateFlow cache

```{r download_copy, eval = FALSE}
# Get file paths (files are downloaded to cache automatically)
files <- tflow_files("fsLR", query_args = list(hemi = "L", density = "32k"))

# Copy to your folder
dest_folder <- "~/my_surfaces"
dir.create(dest_folder, showWarnings = FALSE, recursive = TRUE)
file.copy(files, dest_folder)
```

### Download specific surfaces with `get_surface_template()`

```{r download_surface, eval = FALSE}
# Download and get path to a specific surface
path <- get_surface_template("fsLR", "midthickness", hemi = "L", density = "32k")
file.copy(path, "~/my_surfaces/")
```
### Bulk download helper

For downloading multiple files at once:

```{r download_bulk, eval = FALSE}
download_templateflow_files <- function(space, query_args = list(), dest_folder) {
  dir.create(dest_folder, recursive = TRUE, showWarnings = FALSE)

  files <- tflow_files(space, query_args = query_args)

  if (length(files) == 0) {
    message("No files found")
    return(invisible(character(0)))
  }

  # Copy files preserving names
  dest_paths <- file.path(dest_folder, basename(files))
  success <- file.copy(files, dest_paths, overwrite = TRUE)

  message("Copied ", sum(success), " of ", length(files), " files to ", dest_folder)
  invisible(dest_paths[success])
}

# Download all fsLR 32k left hemisphere surfaces
download_templateflow_files(
  "fsLR",
  query_args = list(hemi = "L", density = "32k"),
  dest_folder = "~/my_surfaces/fsLR"
)

# Download fsaverage pial surfaces (both hemispheres)
download_templateflow_files(
  "fsaverage",
  query_args = list(suffix = "pial"),
  dest_folder = "~/my_surfaces/fsaverage"
)
```

## Caching Behavior

`neuroatlas` and TemplateFlow employ multiple layers of caching:
1.  **R-level Memoisation**: `get_template()` memoises the *file paths* it resolves. If you request the same template with identical parameters multiple times in an R session, the path is retrieved from this memory cache. If `path_only=FALSE`, `as_neurovol()` (which loads the NIfTI file) is also memoised, so the `NeuroVol` object itself is cached in memory for the session if the same path is read again.
2.  **Python Disk Cache**: The underlying Python `templateflow` library maintains a disk cache for downloaded files. `neuroatlas` configures this to use a directory like `~/.cache/neuroatlas/templateflow` (path varies by OS). Once a file is downloaded, subsequent requests (even in new R sessions) will use the disk-cached version if `TEMPLATEFLOW_HOME` remains consistent.

You can inspect and manage the `neuroatlas`-specific TemplateFlow cache:
```{r cache_management, eval = FALSE}
# Show the path to the cache directory
cache_loc <- show_templateflow_cache_path()
print(cache_loc)

# Clear the disk cache and R-level memoisation for TemplateFlow paths
# clear_templateflow_cache()                 # Asks for confirmation if interactive
# clear_templateflow_cache(confirm = FALSE)  # Clears without asking
```

## Integration with Other `neuroatlas` Functions

The `outspace` argument in functions like `get_schaefer_atlas()` can accept TemplateFlow identifiers:
```{r schaefer_tf_outspace, eval = FALSE}
# Load Schaefer atlas resampled to a TemplateFlow space
schaefer_in_mni <- get_schaefer_atlas(
  parcels = "100", 
  networks = "7",
  outspace = "MNI152NLin2009cAsym" # Resolves to default 1mm T1w brain
)

# Or be more specific with a list:
schaefer_in_mni_res2 <- get_schaefer_atlas(
  parcels = "100",
  networks = "7",
  outspace = list(space = "MNI152NLin2009cAsym", resolution = "2")
)
print(schaefer_in_mni_res2)
```
This uses an internal helper `.resolve_template_input()` to fetch the template and extract its `NeuroSpace` information.

## Summary

The `neuroatlas` package provides a comprehensive R interface to TemplateFlow:

- **Easy Setup**: Use `create_templateflow()` to initialize the interface
- **Discovery**: Find templates with `tflow_spaces()` and `tflow_files()`
- **Flexible Retrieval**: Use `get_template()` with various parameters
- **Integration**: Use TemplateFlow spaces directly in atlas functions
- **Caching**: Automatic caching at both R and Python levels

## Further Information

For more details on TemplateFlow itself, including the full range of available templates and BIDS-inspired naming conventions, please visit the [TemplateFlow website](https://www.templateflow.org/). 
