Workflows
=========

Snakebids workflows are constructed the same way as any other [Snakemake workflows](inv:snakemake#snakefiles/rules), but with a few additions that make it easier to work with BIDS datasets.

To get access to these additions, the base Snakefile for a snakebids workflow should begin with the following boilerplate:

```python
import snakebids
from snakebids import bids

configfile: 'config/snakebids.yml'

# Get input wildcards
inputs = snakebids.generate_inputs(
    bids_dir=config["bids_dir"],
    pybids_inputs=config["pybids_inputs"],
    pybidsdb_dir=config.get("pybidsdb_dir"),
    pybidsdb_reset=config.get("pybidsdb_reset"),
    derivatives=config.get("derivatives"),
    participant_label=config.get("participant_label"),
    exclude_participant_label=config.get("exclude_participant_label"),
)

```

Snakebids workflow features
---------------------------

The [](#snakebids.bids) function generates a properly-formatted BIDS filename with the specified entities, as documented in more detail elsewhere in this documentation.

[](#snakebids.generate_inputs) returns an instance of [](#snakebids.BidsDataset), a special <inv:*:*:class#dict> with keys mapping to the {class}`BidsComponents <snakebids.BidsComponent>` defined in [the config file](/bids_app/config). Each {class}`~snakebids.BidsComponent` contains a number of attributes to assist processing a BIDS dataset with snakemake. {func}`~snakebids.generate_inputs` should be called at the beginning of the workflow and assigned to a variable called `inputs`.

The {attr}`~snakebids.BidsComponent.path` member of {class}`~snakebids.BidsComponent` is generated by snakebids and contains a list of matched files for every input type. Often, the first rule to be invoked will use one or more entries in `inputs.path` as the input file specification.

The {meth}`~snakebids.BidsComponent.expand` method of {class}`~snakebids.BidsComponent` is used to expand over files using only the entity-values found in your dataset. A usage pattern is as follows:

```py
inputs["bold"].expand(
    bids(
        root="results",
        datatype="func",
        suffix="func.shape.gii",
        hemi="{hemi}",
        **inputs.wildcards["bold"]
    ),
    hemi=config["hemi"],
)
```

Extra entities provided to [`BidsComponent.expand()`](#snakebids.BidsComponent.expand) will expand the path across every possible combination of values, just like in the snakemake [`expand()`](#snakefiles_expand).

By default, [`BidsComponent.expand()`](#snakebids.BidsComponent.expand) prevents partial expansion over paths, consistent with the default snakemake behaviour. To allow the presence of extra wildcards in the path, set the `allow_missing` argument in [`BidsComponent.expand()`](#snakebids.BidsComponent.expand) to `True`.

The {attr}`~snakebids.BidsComponent.wildcards` member of {class}`~snakebids.BidsComponent` is generated by snakebids and contains a dictionary mapping the wildcards for each input type to snakemake-formatted wildcards, for convenient use in the ``bids`` function.


## Accessing the underlying *pybids* dataset

In addition to mapping all of the {class}`BidsComponents <snakebids.BidsComponent>` to their names, {class}`~snakebids.BidsDataset` also has a {attr}`~snakebids.BidsDataset.layout` member which gives access to the underlying {class}`BIDSLayout <bids.layout.BIDSLayout>`. This can be used to access advanced pybids features not covered by `snakebids`. Note that if `custom_paths` are specified for every {class}`BidsComponent <snakebids.BidsComponent>`, pybids indexing will be skipped and {attr}`~snakebids.BidsDataset.layout` will be set to `None`. If your workflow relies on accessing this {attr}`~snakebids.BidsDataset.layout`, you must ensure your users do not provide a `custom_path` for every single component, either in the config file or [via the CLI](/running_snakebids/overview) (``--path_{component}``).
