.. include:: ../links.inc

.. _adding_masks:

Adding Masks
============

Many processing steps and markers in Junifer allow you to specify a binary
mask to select voxels you want to include in the analysis. There are a number
of masks :ref:`in-built in Junifer already<builtin>`, so check if any of them
suit your needs. Check how to use these masks :ref:`here<using_masks>`. Once
you know how to use these masks, and you checked whether the in-built masks
suit your needs, and you have found that they don't, you can come back here to
learn how to use your own masks.

The principle is fairly simple and quite similar to :ref:`adding_parcellations`
and :ref:`adding_coordinates`. Junifer provides a
:func:`junifer.data.masks.register_mask` function that lets you register your
own custom masks. It consists of two positional arguments (``name`` and
``mask_path``) and one optional keyword argument (``overwrite``).

The ``name`` argument is a string indicating the name of the mask. This name
is used to refer to that mask in Junifer internally in order to obtain the
actual mask data and perform operations on it. For example, using the name you
can load a mask after registration using the
:func:`junifer.data.masks.load_mask` function.

The ``mask_path`` should contain the path to a valid NIfTI image with binary
voxel values (i.e. 0 or 1). This data can then be used by Junifer to mask other
MR images.

Step 1: Prepare code to register a mask
---------------------------------------

A simple script called ``register_custom_mask.py`` to register a mask could
look as follows:

.. code-block:: python

  from junifer.data import register_custom_mask
  from pathlib import Path

  # this path is only an example, of course use the correct path
  # on your system:
  mask_path = Path("..") / ".." / "my_custom_mask.nii.gz"

  register_mask(name="my_custom_mask", mask_path=mask_path)

Simple, right? Now we just have to configure a YAML file to register this mask
so we can use it for :ref:`codeless configuration of junifer<codeless>`.

Step 2: Configure a YAML file for registration of a mask
--------------------------------------------------------

In order to do this, we can use the ``with`` keyword provided by Junifer:

.. code-block:: yaml

  with:
    - register_custom_mask.py

Then we can use this mask for any processing step or marker that takes in a
mask as an argument. For example:

.. code-block:: yaml

  markers:
    - name: CustomMaskParcelAggregation_mean
      kind: ParcelAggregation
      parcellation: Schaefer200x17
      method: mean
      masks: "my_custom_mask"

Now, you can simply use this YAML file to run your pipeline. One important
point to keep in mind is that if the paths given in ``register_custom_mask.py``
are relative paths, they will be interpreted by Junifer as relative to the
jobs directory (i.e. where Junifer will create submit files, logs directory and
so on). For simplicity, you may just want to use absolute paths to avoid
confusion, yet using relative paths is likely a better way to make your
pipeline directory/repository more portable and therefore more reproducible for
others. Really, once you understand how these paths are interpreted by Junifer,
it is quite easy.
