diff --git a/bids/layout/layout.py b/bids/layout/layout.py index 1088cf2d1..142eb6a5b 100644 --- a/bids/layout/layout.py +++ b/bids/layout/layout.py @@ -63,7 +63,8 @@ class BIDSLayout(object): file in order to be indexed. config : str or list or None, optional Optional name(s) of configuration file(s) to use. - By default (None), uses 'bids'. + By default (None), uses 'bids'. For derivatives use + `['bids', `derivatives`] sources : :obj:`bids.layout.BIDSLayout` or list or None, optional Optional BIDSLayout(s) from which the current BIDSLayout is derived. config_filename : str diff --git a/examples/bids_layout_query.ipynb b/examples/bids_layout_query.ipynb new file mode 100644 index 000000000..ff5e57341 --- /dev/null +++ b/examples/bids_layout_query.ipynb @@ -0,0 +1,1194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Introduction to `pybids`\n", + "\n", + "---\n", + "## Table of contents\n", + "- [The `BIDSLayout`](#layout)\n", + "- [Querying the `BIDSLayout`](#query)\n", + " - [Filtering files by entities](#filtering_files)\n", + " - [Filtering by metadata](#filtering_metadata)\n", + " - [Other `return_type` values](#other_return_types)\n", + " - [Other `get()` options](#other_get_options)\n", + " - [Other query methods](#other_query_methods)\n", + "- [The BIDSFile](#bids_file)\n", + "- [Retrieving BIDS variables](#retrieving_variables)\n", + " \n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[`pybids`](https://github.com/bids-standard/pybids) is a tool to query, summarize and manipulate data using the BIDS standard. \n", + "\n", + "In this tutorial we will use a `pybids` test dataset to illustrate some of the functionality of `pybids.layout`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## The `BIDSLayout`\n", + "\n", + "At the core of pybids is the `BIDSLayout` object. \n", + "\n", + "A `BIDSLayout` is a lightweight Python class that represents a BIDS project file tree and provides a variety of helpful methods for querying and manipulating BIDS files. \n", + "\n", + "While the `BIDSLayout` initializer has a large number of arguments you can use to control the way files are indexed and accessed, you will most commonly initialize a `BIDSLayout` by passing in the BIDS dataset root location as a single argument:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2018-08-01T20:05:23.628184Z", + "start_time": "2018-08-01T20:05:22.060937Z" + }, + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "from bids import BIDSLayout\n", + "from bids.tests import get_test_data_path\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2018-08-01T20:05:23.739377Z", + "start_time": "2018-08-01T20:05:23.630505Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing layout with: /home/remi/github/pybids/bids/tests/data/7t_trt\n" + ] + }, + { + "data": { + "text/plain": [ + "BIDS Layout: .../pybids/bids/tests/data/7t_trt | Subjects: 10 | Sessions: 20 | Runs: 20" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Here we're using an example BIDS dataset that's bundled with the pybids tests\n", + "data_path = os.path.join(get_test_data_path(), \"7t_trt\")\n", + "print(f\"Initializing layout with: {data_path}\")\n", + "\n", + "# Initialize the layout\n", + "layout = BIDSLayout(data_path)\n", + "\n", + "# Print some basic information about the layout\n", + "layout" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## Querying the `BIDSLayout`\n", + "\n", + "When we initialize a `BIDSLayout`, all of the files and metadata found under the specified root folder are indexed. \n", + "\n", + "This can take a few seconds (or, for very large datasets, a minute or two). \n", + "\n", + "Once initialization is complete, we can start querying the `BIDSLayout` in various ways. \n", + "\n", + "The workhorse method is [`.get()`](https://bids-standard.github.io/pybids/generated/bids.grabbids.BIDSLayout.html#bids.grabbids.BIDSLayout.get). \n", + "\n", + "If we call `.get()` with no additional arguments, we get back a list of all the BIDS files in our dataset:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There are 339 files in the layout.\n", + "\n", + "The first 10 files are:\n" + ] + }, + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ,\n", + " ]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_files = layout.get()\n", + "print(f\"There are {len(all_files)} files in the layout.\")\n", + "\n", + "print(\"\\nThe first 10 files are:\")\n", + "all_files[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The returned object is a Python list. \n", + "\n", + "By default, each element in the list is a `BIDSFile` object. We discuss the `BIDSFile` object in much more detail [below](#bids_file). \n", + "\n", + "For now, let's simplify things and work with just filenames:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['/home/remi/github/pybids/bids/tests/data/7t_trt/dataset_description.json',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/participants.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/README',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/anat/sub-01_ses-1_T1map.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/anat/sub-01_ses-1_T1w.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_magnitude1.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_magnitude2.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_phasediff.json',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_phasediff.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-2_magnitude1.nii.gz']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get(return_type=\"filename\")[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This time, we get back only the names of the files." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Filtering files by entities\n", + "\n", + "The utility of the `BIDSLayout` would be pretty limited if all we could do was retrieve a list of all files in the dataset. \n", + "\n", + "Fortunately, the `.get()` method accepts all kinds of arguments that allow us to filter the result set based on specified criteria. \n", + "\n", + "In fact, we can pass *any* BIDS-defined keywords (or, as they're called in PyBIDS, *entities*) as constraints. \n", + "\n", + "For example, here's how we would retrieve all BOLD runs with `.nii.gz` extensions for subject `'01'`:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-fullbrain_run-1_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-fullbrain_run-2_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-prefrontal_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-2/func/sub-01_ses-2_task-rest_acq-fullbrain_run-1_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-2/func/sub-01_ses-2_task-rest_acq-fullbrain_run-2_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-2/func/sub-01_ses-2_task-rest_acq-prefrontal_bold.nii.gz']" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get(subject=\"01\", extension=\"nii.gz\", suffix=\"bold\", return_type=\"filename\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you're wondering what entities you can pass in as filtering arguments, the answer is contained in the `.json` configuration files [housed here](https://github.com/bids-standard/pybids/tree/master/bids/layout/config). \n", + "\n", + "To save you the trouble, here are a few of the most common entities:\n", + "\n", + "* `suffix`: The part of a BIDS filename just before the extension (e.g., `'bold'`, `'events'`, `'physio'`, etc.).\n", + "* `subject`: The subject label\n", + "* `session`: The session label\n", + "* `run`: The run index\n", + "* `task`: The task name\n", + "\n", + "New entities are continually being defined as the spec grows, and in principle (though not always in practice), PyBIDS should be aware of all entities that are defined in the BIDS specification." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Filtering by metadata\n", + "All of the entities listed above are found in the names of BIDS files. \n", + "\n", + "But sometimes we want to search for files based not just on their names, but also based on metadata defined (per the BIDS spec) in JSON files. \n", + "\n", + "Fortunately for us, when we initialize a `BIDSLayout`, all metadata files associated with BIDS files are automatically indexed. \n", + "\n", + "This means we can pass any key that occurs in any JSON file in our project as an argument to `.get()`. \n", + "\n", + "We can combine these with any number of core BIDS entities (like `subject`, `run`, etc.). \n", + "\n", + "For example, say we want to retrieve all files where:\n", + "- the value of `SamplingFrequency` (a metadata key) is `100`, \n", + "- the `acquisition` type is `\"prefrontal\"`, \n", + "- the subject is `\"01\"` or `\"02\"`. Here's how we can do that:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get(subject=[\"01\", \"02\"], SamplingFrequency=100, acquisition=\"prefrontal\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that we passed a list in for `subject` rather than just a string. \n", + "\n", + "This principle applies to all filters: you can always pass in a list instead of a single value, and this will be interpreted as a logical disjunction (i.e., a file must match any one of the provided values)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Other `return_type` values\n", + "\n", + "While we'll typically want to work with either `BIDSFile` objects or filenames, we can also ask `get()` to return unique values (or ids) of particular entities. \n", + "\n", + "For example, say we want to know which subjects have at least one `T1w` file. \n", + "\n", + "We can request that information by setting `return_type='id'`. \n", + "\n", + "When using this option, we also need to specify a target entity (or metadata keyword) called `target`.\n", + "\n", + "This combination tells the `BIDSLayout` to return the unique values for the specified `target` entity. \n", + "\n", + "For example, in the next example, we ask for all of the unique subject IDs that have at least one file with a `T1w` suffix:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2018-08-01T20:05:23.964766Z", + "start_time": "2018-08-01T20:05:23.957477Z" + }, + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['10', '02', '08', '04', '03', '01', '05', '06', '07', '09']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get(return_type=\"id\", target=\"subject\", suffix=\"T1w\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If our `target` is a BIDS entity that corresponds to a particular directory in the BIDS spec (e.g., `subject` or `session`) we can also use `return_type='dir'` to get all matching subdirectories:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2018-08-01T20:05:23.983125Z", + "start_time": "2018-08-01T20:05:23.975085Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-02',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-03',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-04',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-05',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-06',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-07',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-08',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-09',\n", + " '/home/remi/github/pybids/bids/tests/data/7t_trt/sub-10']" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get(return_type=\"dir\", target=\"subject\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Other `get()` options\n", + "The `.get()` method has a number of other useful arguments that control its behavior. \n", + "\n", + "We won't discuss these in detail here, but briefly, here are a couple worth knowing about:\n", + "* `regex_search`: If you set this to `True`, string filter argument values will be interpreted as regular expressions.\n", + "* `scope`: If your BIDS dataset contains BIDS-derivatives sub-datasets, you can specify the scope (e.g., `derivatives`, or a BIDS-Derivatives pipeline name) of the search space." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Other query methods\n", + "\n", + "The layout object has several other methods that can help query some other information quickly.\n", + "\n", + "For more details see the [documentation](https://bids-standard.github.io/pybids/generated/bids.layout.BIDSLayout.html#bids.layout.BIDSLayout) " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'BIDSVersion': '1.0.0rc3', 'Name': '7t_trt'}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get_dataset_description()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['10', '02', '08', '04', '03', '01', '05', '06', '07', '09']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get_subjects()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['2', '1']" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get_sessions()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['rest']" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get_tasks()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "---\n", + "\n", + "## The `BIDSFile`\n", + "\n", + "When you call `.get()` on a `BIDSLayout`, the default returned values are objects of class `BIDSFile`. \n", + "\n", + "A `BIDSFile` is a lightweight container for individual files in a BIDS dataset. It provides easy access to a variety of useful attributes and methods. \n", + "\n", + "Let's take a closer look. First, let's pick a random file from our existing `layout`." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "ExecuteTime": { + "end_time": "2018-08-01T20:05:23.926278Z", + "start_time": "2018-08-01T20:05:23.741189Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Pick the 15th file in the dataset\n", + "bf = layout.get()[15]\n", + "\n", + "# Print it\n", + "bf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here are some of the attributes and methods available to us in a `BIDSFile`:\n", + "* `.path`: The full path of the associated file\n", + "* `.filename`: The associated file's filename (without directory)\n", + "* `.dirname`: The directory containing the file\n", + "* `.get_entities()`: Returns information about entities associated with this `BIDSFile` (optionally including metadata)\n", + "* `.get_image()`: Returns the file contents as a nibabel image (only works for image files)\n", + "* `.get_df()`: Get file contents as a pandas DataFrame (only works for TSV files)\n", + "* `.get_metadata()`: Returns a dictionary of all metadata found in associated JSON files\n", + "* `.get_associations()`: Returns a list of all files associated with this one in some way\n", + "\n", + "**Note**: some of these are only available for certain subclasses of `BIDSFile`; e.g., you can't call `get_image()` on a `BIDSFile` that doesn't correspond to an image file!\n", + "\n", + "Let's see some of these in action." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'acquisition': 'fullbrain',\n", + " 'datatype': 'func',\n", + " 'extension': '.tsv.gz',\n", + " 'run': 1,\n", + " 'session': '1',\n", + " 'subject': '01',\n", + " 'suffix': 'physio',\n", + " 'task': 'rest'}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Print all the entities associated with this file, and their values\n", + "bf.get_entities()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Columns': ['cardiac', 'respiratory', 'trigger', 'oxygen saturation'],\n", + " 'SamplingFrequency': 100,\n", + " 'StartTime': 0}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Print all the metadata associated with this file\n", + "bf.get_metadata()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Columns': ['cardiac', 'respiratory', 'trigger', 'oxygen saturation'],\n", + " 'SamplingFrequency': 100,\n", + " 'StartTime': 0,\n", + " 'acquisition': 'fullbrain',\n", + " 'datatype': 'func',\n", + " 'extension': '.tsv.gz',\n", + " 'run': 1,\n", + " 'session': '1',\n", + " 'subject': '01',\n", + " 'suffix': 'physio',\n", + " 'task': 'rest'}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# We can the union of both of the above in one shot like this\n", + "bf.get_entities(metadata=\"all\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here are all the files associated with our target file in some way. \n", + "\n", + "**Note**: we get back both the JSON sidecar for our target file, and the BOLD run that our target file contains physiological recordings for." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bf.get_associations()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "In cases where a file has a `.tsv.gz` or `.tsv` extension, it will automatically be created as a `BIDSDataFile`, and we can easily grab the contents as a pandas `DataFrame`:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
onsetrespiratorycardiac
00.0-0.714844-0.262109
10.1-0.7573420.048933
20.2-0.7968510.355185
30.3-0.8332150.626669
40.4-0.8662910.836810
\n", + "
" + ], + "text/plain": [ + " onset respiratory cardiac\n", + "0 0.0 -0.714844 -0.262109\n", + "1 0.1 -0.757342 0.048933\n", + "2 0.2 -0.796851 0.355185\n", + "3 0.3 -0.833215 0.626669\n", + "4 0.4 -0.866291 0.836810" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Use a different test dataset--one that contains physio recording files\n", + "data_path = os.path.join(get_test_data_path(), \"synthetic\")\n", + "layout2 = BIDSLayout(data_path)\n", + "\n", + "# Get the first physiological recording file\n", + "recfile = layout2.get(suffix=\"physio\")[0]\n", + "\n", + "# Get contents as a DataFrame and show the first few rows\n", + "df = recfile.get_df()\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While it would have been easy enough to read the contents of the file ourselves with pandas' `read_csv()` method, notice that in the above example, `get_df()` saved us the trouble of having to read the physiological recording file's metadata, pull out the column names and sampling rate, and add timing information.\n", + "\n", + "Mind you, if we don't *want* the timing information, we can ignore it:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
respiratorycardiac
0-0.714844-0.262109
1-0.7573420.048933
2-0.7968510.355185
3-0.8332150.626669
4-0.8662910.836810
\n", + "
" + ], + "text/plain": [ + " respiratory cardiac\n", + "0 -0.714844 -0.262109\n", + "1 -0.757342 0.048933\n", + "2 -0.796851 0.355185\n", + "3 -0.833215 0.626669\n", + "4 -0.866291 0.836810" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "recfile.get_df(include_timing=False).head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In case we only have the filename but want to recover the BIDSFile object associated with it, we can use the `get_file()` method from `BIDSLayout` to recover it." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "bf = layout.get_file(\"sub-01_ses-1_task-rest_acq-fullbrain_run-1_physio.tsv.gz\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## Retrieving BIDS variables \n", + "BIDS variables are stored in .tsv files at the run, session, subject, or dataset level. You can retrieve these variables with `layout.get_collections()`. The resulting objects can be converted to dataframes and merged with the layout to associate the variables with corresponding scans.\n", + "\n", + "In the following example, we request all subject-level variable data available anywhere in the BIDS project, and merge the results into a single `DataFrame` (by default, we'll get back a single `BIDSVariableCollection` object for each subject). " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "ExecuteTime": { + "end_time": "2018-08-01T20:05:26.693372Z", + "start_time": "2018-08-01T20:05:24.276799Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sessionsubjectCCPT_FN_countCCPT_FP_countCCPT_avg_FN_RTCCPT_avg_FP_RTCCPT_avg_succ_RTCCPT_succ_countcaffeine_dailydiastolic_blood_pressure_left...specific_vaguesubject_idsurroundingssystolic_blood_pressure_leftsystolic_blood_pressure_rightthirstvigilancevigilance_nyc-qwordssuffix
01010.01.0NaN507.0500.77083396.00.564...951010810999100100sessions
11020.05.0NaN297.6351.72916796.00.065...1002709910027100100sessions
21030.01.0NaN441.0426.71875096.01.069...100310122128381000sessions
31040.01.0NaN443.0417.90625096.00.174...80401301106510085sessions
41050.02.0NaN355.5372.11458396.00.069...75580105117776030sessions
\n", + "

5 rows × 97 columns

\n", + "
" + ], + "text/plain": [ + " session subject CCPT_FN_count CCPT_FP_count CCPT_avg_FN_RT \\\n", + "0 1 01 0.0 1.0 NaN \n", + "1 1 02 0.0 5.0 NaN \n", + "2 1 03 0.0 1.0 NaN \n", + "3 1 04 0.0 1.0 NaN \n", + "4 1 05 0.0 2.0 NaN \n", + "\n", + " CCPT_avg_FP_RT CCPT_avg_succ_RT CCPT_succ_count caffeine_daily \\\n", + "0 507.0 500.770833 96.0 0.5 \n", + "1 297.6 351.729167 96.0 0.0 \n", + "2 441.0 426.718750 96.0 1.0 \n", + "3 443.0 417.906250 96.0 0.1 \n", + "4 355.5 372.114583 96.0 0.0 \n", + "\n", + " diastolic_blood_pressure_left ... specific_vague subject_id \\\n", + "0 64 ... 95 1 \n", + "1 65 ... 100 2 \n", + "2 69 ... 100 3 \n", + "3 74 ... 80 4 \n", + "4 69 ... 75 5 \n", + "\n", + " surroundings systolic_blood_pressure_left systolic_blood_pressure_right \\\n", + "0 0 108 109 \n", + "1 70 99 100 \n", + "2 10 122 128 \n", + "3 0 130 110 \n", + "4 80 105 117 \n", + "\n", + " thirst vigilance vigilance_nyc-q words suffix \n", + "0 9 9 100 100 sessions \n", + "1 2 7 100 100 sessions \n", + "2 3 8 100 0 sessions \n", + "3 6 5 100 85 sessions \n", + "4 7 7 60 30 sessions \n", + "\n", + "[5 rows x 97 columns]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Get subject variables as a dataframe and merge them back in with the layout\n", + "subj_df = layout.get_collections(level=\"subject\", merge=True).to_df()\n", + "subj_df.head()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + }, + "toc": { + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "toc_cell": false, + "toc_position": {}, + "toc_section_display": "block", + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/bids_to_pandas.ipynb b/examples/bids_to_pandas.ipynb new file mode 100644 index 000000000..bf4eabc49 --- /dev/null +++ b/examples/bids_to_pandas.ipynb @@ -0,0 +1,538 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "90316426-ae94-45d3-b47b-2a5ab2f0b6ce", + "metadata": {}, + "source": [ + "# From a `BIDSLayout` to a pandas `Dataframe`\n", + "\n", + "If you want a summary of all the files in your `BIDSLayout`, but don't want to have to iterate `BIDSFile` objects and extract their entities, you can get a nice bird's-eye view of your dataset using the `to_df()` method." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "ce3e0d10-4b5f-477c-bc04-1112d743c423", + "metadata": {}, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "74f46cdb-8ee2-4de0-b344-2d7269f0502e", + "metadata": {}, + "outputs": [], + "source": [ + "from bids import BIDSLayout\n", + "from bids.tests import get_test_data_path\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4b933d2f-6183-40e0-814f-d43bcbfd5121", + "metadata": {}, + "outputs": [], + "source": [ + "# Using a test dataset that contains physio recording files\n", + "data_path = os.path.join(get_test_data_path(), \"synthetic\")\n", + "layout = BIDSLayout(data_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "779d2dc3-738a-4356-9f5b-9378d02a2ad1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
entitypathdatatypeextensionfmaprunscanssessionsubjectsuffixtask
0/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNT1wNaN
1/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNdescriptionNaN
2/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNdwiNaN
3/home/remi/github/pybids/bids/tests/data/synth...NaN.tsvNaNNaNNaNNaNNaNparticipantsNaN
4/home/remi/github/pybids/bids/tests/data/synth...anat.niiNaNNaNNaN0101T1wNaN
.................................
185/home/remi/github/pybids/bids/tests/data/synth...NaN.tsvNaNNaNNaNNaNNaNeventsnback
186/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNphysionback
187/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNstimnback
188/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNboldrest
189/home/remi/github/pybids/bids/tests/data/synth...NaN.jsonNaNNaNNaNNaNNaNphysiorest
\n", + "

190 rows × 10 columns

\n", + "
" + ], + "text/plain": [ + "entity path datatype extension \\\n", + "0 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "1 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "2 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "3 /home/remi/github/pybids/bids/tests/data/synth... NaN .tsv \n", + "4 /home/remi/github/pybids/bids/tests/data/synth... anat .nii \n", + ".. ... ... ... \n", + "185 /home/remi/github/pybids/bids/tests/data/synth... NaN .tsv \n", + "186 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "187 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "188 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "189 /home/remi/github/pybids/bids/tests/data/synth... NaN .json \n", + "\n", + "entity fmap run scans session subject suffix task \n", + "0 NaN NaN NaN NaN NaN T1w NaN \n", + "1 NaN NaN NaN NaN NaN description NaN \n", + "2 NaN NaN NaN NaN NaN dwi NaN \n", + "3 NaN NaN NaN NaN NaN participants NaN \n", + "4 NaN NaN NaN 01 01 T1w NaN \n", + ".. ... ... ... ... ... ... ... \n", + "185 NaN NaN NaN NaN NaN events nback \n", + "186 NaN NaN NaN NaN NaN physio nback \n", + "187 NaN NaN NaN NaN NaN stim nback \n", + "188 NaN NaN NaN NaN NaN bold rest \n", + "189 NaN NaN NaN NaN NaN physio rest \n", + "\n", + "[190 rows x 10 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Convert the layout to a pandas dataframe\n", + "df = layout.to_df()\n", + "df" + ] + }, + { + "cell_type": "markdown", + "id": "e8f566b1-0d5c-4f96-be0d-cfb85e1b970f", + "metadata": {}, + "source": [ + "---\n", + "**TODO:** \n", + "\n", + "- show how you can the use some \"quick\" panda magic to count how many files you have per subject, session, task since this can be useful to make sure all participants have the same number of files... \n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "fb78a18b-6c31-4da7-995c-5f476b6c8b7f", + "metadata": {}, + "source": [ + "We can also include metadata in the result if we like (which may blow up our `DataFrame` if we have a large dataset). \n", + "\n", + "**Note**: in this case, most of our cells will have missing values." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ef19de65-7d2b-4a83-aa53-db9976789fc6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
entitypathColumnsEchoTimeEchoTime1EchoTime2EffectiveEchoSpacingFlipAngleIntendedForPhaseEncodingDirectionRepetitionTime...TotalReadoutTimedatatypeextensionfmaprunscanssessionsubjectsuffixtask
0/home/remi/github/pybids/bids/tests/data/synth...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaN.jsonNaNNaNNaNNaNNaNT1wNaN
1/home/remi/github/pybids/bids/tests/data/synth...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaN.jsonNaNNaNNaNNaNNaNdescriptionNaN
2/home/remi/github/pybids/bids/tests/data/synth...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaN.jsonNaNNaNNaNNaNNaNdwiNaN
3/home/remi/github/pybids/bids/tests/data/synth...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaN.tsvNaNNaNNaNNaNNaNparticipantsNaN
4/home/remi/github/pybids/bids/tests/data/synth...NaN0.0029NaNNaNNaN8NaNNaN2.5...NaNanat.niiNaNNaNNaN0101T1wNaN
\n", + "

5 rows × 24 columns

\n", + "
" + ], + "text/plain": [ + "entity path Columns EchoTime \\\n", + "0 /home/remi/github/pybids/bids/tests/data/synth... NaN NaN \n", + "1 /home/remi/github/pybids/bids/tests/data/synth... NaN NaN \n", + "2 /home/remi/github/pybids/bids/tests/data/synth... NaN NaN \n", + "3 /home/remi/github/pybids/bids/tests/data/synth... NaN NaN \n", + "4 /home/remi/github/pybids/bids/tests/data/synth... NaN 0.0029 \n", + "\n", + "entity EchoTime1 EchoTime2 EffectiveEchoSpacing FlipAngle IntendedFor \\\n", + "0 NaN NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN NaN \n", + "3 NaN NaN NaN NaN NaN \n", + "4 NaN NaN NaN 8 NaN \n", + "\n", + "entity PhaseEncodingDirection RepetitionTime ... TotalReadoutTime datatype \\\n", + "0 NaN NaN ... NaN NaN \n", + "1 NaN NaN ... NaN NaN \n", + "2 NaN NaN ... NaN NaN \n", + "3 NaN NaN ... NaN NaN \n", + "4 NaN 2.5 ... NaN anat \n", + "\n", + "entity extension fmap run scans session subject suffix task \n", + "0 .json NaN NaN NaN NaN NaN T1w NaN \n", + "1 .json NaN NaN NaN NaN NaN description NaN \n", + "2 .json NaN NaN NaN NaN NaN dwi NaN \n", + "3 .tsv NaN NaN NaN NaN NaN participants NaN \n", + "4 .nii NaN NaN NaN 01 01 T1w NaN \n", + "\n", + "[5 rows x 24 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.to_df(metadata=True).head()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/configurations.ipynb b/examples/configurations.ipynb new file mode 100644 index 000000000..56ceafc3c --- /dev/null +++ b/examples/configurations.ipynb @@ -0,0 +1,495 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0c604560-881d-4b25-8a30-3fd9f60d1dfe", + "metadata": {}, + "source": [ + "# Working with configuration" + ] + }, + { + "cell_type": "markdown", + "id": "a2fb9adf-08bf-47ac-8e66-dd5a2c8f2a47", + "metadata": {}, + "source": [ + " ---\n", + "## Table of contents\n", + "\n", + "- [Built-in configurations](#built_in_configurations)\n", + "- [User defined configurations](#user_defined_configurations)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73782b3d-6386-4ca5-8237-09156222f55f", + "metadata": {}, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "id": "584377bf-3950-4298-a311-bee18a496b5f", + "metadata": {}, + "outputs": [], + "source": [ + "from bids import BIDSLayout\n", + "from bids.tests import get_test_data_path\n", + "import os" + ] + }, + { + "cell_type": "markdown", + "id": "fcd01d5c-d5d6-4024-bd02-170e2ee696d7", + "metadata": {}, + "source": [ + "\n", + "## Built-in configurations" + ] + }, + { + "cell_type": "markdown", + "id": "7d20178c-cac8-4556-9b7f-99b23adb5482", + "metadata": {}, + "source": [ + "If we try to load a derivatives data by itself." + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "5cf20bb4-4639-4604-9faf-df83f33d138b", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = os.path.join(get_test_data_path(), \"synthetic\", \"derivatives\", \"fmriprep\")" + ] + }, + { + "cell_type": "markdown", + "id": "2369716d-5611-4903-b003-6e1a2aeaf998", + "metadata": {}, + "source": [ + "Without `validate=False` no subject is detected." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "2862e809-e7ed-4642-af0d-6b9928d2daae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BIDS Layout: ...synthetic/derivatives/fmriprep | Subjects: 0 | Sessions: 0 | Runs: 0\n" + ] + } + ], + "source": [ + "layout = BIDSLayout(data_path)\n", + "print(layout)" + ] + }, + { + "cell_type": "markdown", + "id": "25242b2e-bdae-4d33-b63c-e708417065af", + "metadata": {}, + "source": [ + "Note that this is equivalent to using the default pybids configuration and that none of the typical entities associated with derivatives (like `desc` for description) would be availaible for querying this layout or for parsing files." + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "f13d2ab2-d3dc-44e3-9011-7a180d75c288", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BIDS Layout: ...synthetic/derivatives/fmriprep | Subjects: 0 | Sessions: 0 | Runs: 0\n", + "dict_keys(['subject', 'session', 'task', 'acquisition', 'ceagent', 'reconstruction', 'direction', 'run', 'proc', 'modality', 'echo', 'flip', 'inv', 'mt', 'part', 'recording', 'space', 'suffix', 'scans', 'fmap', 'datatype', 'extension'])\n" + ] + }, + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout = BIDSLayout(data_path, config=['bids'])\n", + "print(layout)\n", + "print(layout.get_entities().keys())\n", + "\"desc\" in layout.get_entities()" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "3ea712e4-9484-4afb-a330-289f781f951d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'session': '01',\n", + " 'task': 'nback',\n", + " 'run': 1,\n", + " 'space': 'MNI152NLin2009cAsym',\n", + " 'suffix': 'bold',\n", + " 'extension': '.nii.gz'}" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "filename=\"sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz\"\n", + "# no `desc` entity reported\n", + "layout.parse_file_entities(filename)" + ] + }, + { + "cell_type": "markdown", + "id": "fcce032b-6b96-4d97-907d-63e6321c41eb", + "metadata": {}, + "source": [ + "But we can add the `derivatives` configuration to change this behavior." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "a0af3bd6-2f5f-45da-a755-5ade16cc051f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BIDS Layout: ...synthetic/derivatives/fmriprep | Subjects: 5 | Sessions: 10 | Runs: 10\n", + "dict_keys(['subject', 'session', 'task', 'acquisition', 'ceagent', 'reconstruction', 'direction', 'run', 'proc', 'modality', 'echo', 'flip', 'inv', 'mt', 'part', 'recording', 'space', 'suffix', 'scans', 'fmap', 'datatype', 'extension', 'atlas', 'roi', 'label', 'desc', 'from', 'to', 'mode', 'hemi', 'res', 'den', 'model', 'subset', 'TaskName', 'RepetitionTime'])\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout = BIDSLayout(data_path, config=['bids', 'derivatives'])\n", + "print(layout)\n", + "print(layout.get_entities().keys())\n", + "\"desc\" in layout.get_entities()" + ] + }, + { + "cell_type": "markdown", + "id": "830f5ca3-d26e-4703-b473-a3617f4f62eb", + "metadata": {}, + "source": [ + "And we can now query this layout for derivatives entities." + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "c8c3fdee-0748-47d4-9a66-178636b1d3b5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz']" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout.get(extension=\"nii.gz\", subject=\"01\", suffix=\"bold\", desc=\"preproc\", space=\"MNI152NLin2009cAsym\", return_type=\"filename\")" + ] + }, + { + "cell_type": "markdown", + "id": "8666eeb0-720f-484c-b359-4452cfcc5071", + "metadata": {}, + "source": [ + "And parse files for derivatives only entities." + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "db60b37d-60e1-49c0-b114-7bfb9d6f87d4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'session': '01',\n", + " 'task': 'nback',\n", + " 'run': 1,\n", + " 'space': 'MNI152NLin2009cAsym',\n", + " 'suffix': 'bold',\n", + " 'extension': '.nii.gz',\n", + " 'desc': 'preproc'}" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "filename=\"sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz\"\n", + "layout.parse_file_entities(filename)" + ] + }, + { + "cell_type": "markdown", + "id": "0a48e7da-8042-463f-916c-f1e819fac901", + "metadata": {}, + "source": [ + "\n", + "## User defined configurations" + ] + }, + { + "cell_type": "markdown", + "id": "85765cdb-e223-4e35-bb3f-4ea053d1ddce", + "metadata": {}, + "source": [ + "It is also possible to pass the path to a specific bids defined in a JSON file to override the defaults." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "283deae0-8b0e-4a1e-aab5-fb1821b084f1", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['subject', 'oligarchy', 'task', 'acquisition', 'ceagent', 'reconstruction', 'direction', 'run', 'proc', 'modality', 'echo', 'recording', 'space', 'suffix', 'scans', 'fmap', 'datatype', 'extension', 'atlas', 'roi', 'label', 'desc', 'from', 'to', 'mode', 'hemi', 'res', 'den', 'model', 'subset', 'TaskName', 'RepetitionTime'])\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_path = os.path.join(get_test_data_path(), \"..\", 'bids_specs_with_oligarchy.json')\n", + "layout = BIDSLayout(data_path, config=[config_path, \"derivatives\"])\n", + "print(layout.get_entities().keys())\n", + "\"oligarchy\" in layout.get_entities()" + ] + }, + { + "cell_type": "markdown", + "id": "1518b310-724a-4b0c-926d-ed8db5652c1e", + "metadata": {}, + "source": [ + "## Parsing files with a specific configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "id": "f89b6177-e2af-4aeb-ac09-fb95c67b99e1", + "metadata": {}, + "outputs": [], + "source": [ + "from bids.layout.models import Config" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "id": "94072857-98c5-40f6-8572-671167f4c1eb", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = os.path.join(get_test_data_path(), \"synthetic\")\n", + "filename = '/sub-03_ses-07_run-4_desc-preproc_bold.nii.gz'" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "id": "b088588a-b889-499a-bad5-98a7a8fe2506", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'subject': '03',\n", + " 'session': '07',\n", + " 'run': 4,\n", + " 'suffix': 'bold',\n", + " 'extension': '.nii.gz'}" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout = BIDSLayout(data_path)\n", + "config = Config.load('bids')\n", + "layout.parse_file_entities(filename, config=[config])" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "id": "32536e41-4bb0-4f98-bd6a-87ddb3ab1ba0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'subject': '03',\n", + " 'session': '07',\n", + " 'run': 4,\n", + " 'suffix': 'bold',\n", + " 'extension': '.nii.gz'}" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout = BIDSLayout(data_path)\n", + "layout.parse_file_entities(filename, config='bids')" + ] + }, + { + "cell_type": "markdown", + "id": "81206c9f-443a-420e-bd2a-70a0736c6299", + "metadata": {}, + "source": [ + "# TODO\n", + "make parsing with config work" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "id": "4876289f-d519-473c-8aba-686772df1055", + "metadata": {}, + "outputs": [], + "source": [ + "def test_parse_file_entities_from_layout(layout_synthetic):\n", + " layout = layout_synthetic\n", + " filename = '/sub-03_ses-07_run-4_desc-bleargh_sekret.nii.gz'\n", + "\n", + " # Test with entities taken from bids config\n", + " target = {'subject': '03', 'session': '07', 'run': 4, 'suffix': 'sekret',\n", + " 'extension': '.nii.gz'}\n", + " assert target == layout.parse_file_entities(filename, config='bids')\n", + " config = Config.load('bids')\n", + " assert target == layout.parse_file_entities(filename, config=[config])\n", + " assert target == layout.parse_file_entities(filename, scope='raw')\n", + "\n", + " # Test with default scope--i.e., everything\n", + " target = {'subject': '03', 'session': '07', 'run': 4, 'suffix': 'sekret',\n", + " 'desc': 'bleargh', 'extension': '.nii.gz'}\n", + " assert target == layout.parse_file_entities(filename)\n", + " # Test with only the fmriprep pipeline (which includes both configs)\n", + " assert target == layout.parse_file_entities(filename, scope='fmriprep')\n", + " assert target == layout.parse_file_entities(filename, scope='derivatives')" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "id": "450db2ad-2c2b-4f32-978b-e68b0f7f3e6d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'desc': 'preproc'}" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout = BIDSLayout(data_path, derivatives=True)\n", + "layout.parse_file_entities(filename, config='derivatives', scope='fmriprep')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/derivatives.ipynb b/examples/derivatives.ipynb new file mode 100644 index 000000000..6afcb39bd --- /dev/null +++ b/examples/derivatives.ipynb @@ -0,0 +1,592 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7b0edfd7-1bd3-4827-a447-b1aa2609bf0e", + "metadata": {}, + "source": [ + "# Dealing with BIDS derivatives" + ] + }, + { + "cell_type": "markdown", + "id": "695b9e43-641c-4426-b83e-9c0ae211c1de", + "metadata": {}, + "source": [ + "There are 2 ways to deal with a BIDS derivatives dataset.\n", + "\n", + "- if it is nested within a BIDS `raw` dataset, both datasets can be indexed at once\n", + "- if you have a \"standalone\" BIDS `derivative`\n" + ] + }, + { + "cell_type": "markdown", + "id": "5fbc6fd1-032c-48a7-bd63-4d06107e4605", + "metadata": {}, + "source": [ + "---\n", + "## Nested derivatives\n", + "\n", + "By default, `BIDSLayout` objects are initialized without scanning contained `derivatives/` directories. \n", + "\n", + "But you can easily ensure that all derivatives files are loaded and endowed with the extra structure specified in the [derivatives configuration file](https://github.com/bids-standard/pybids/blob/master/bids/layout/config/derivatives.json).\n", + "\n", + "To know more how to use the configurations, check the `configurations` notebook." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ba50f3ea-1f12-4d14-ac9d-e37aa6c5eb7c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "b2b1c58b-fb28-4d1a-b0ef-3809b6ac30e8", + "metadata": {}, + "outputs": [], + "source": [ + "from bids import BIDSLayout\n", + "from bids.tests import get_test_data_path\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "423dafc2-3693-476b-8922-df3f4a0a319a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing layout with: /home/remi/github/pybids/bids/tests/data/synthetic\n" + ] + } + ], + "source": [ + "# Define paths to root and derivatives folders\n", + "data_path = os.path.join(get_test_data_path(), \"synthetic\")\n", + "print(f\"Initializing layout with: {data_path}\")" + ] + }, + { + "cell_type": "markdown", + "id": "3c090552-305b-4553-be6f-0f0cd0abfcae", + "metadata": {}, + "source": [ + "Let's quickly view the nested derivatives dataset.\n", + "\n", + "**Note** This may not work on your system if you do not have the `tree` function installed" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ac99d97b-fecf-41d8-a66b-ea443e60c31c", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + }, + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[01;34m../bids/tests/data/synthetic\u001b[00m\n", + "├── \u001b[01;34mcode\u001b[00m\n", + "├── \u001b[01;34mderivatives\u001b[00m\n", + "│   └── \u001b[01;34mfmriprep\u001b[00m\n", + "│   ├── \u001b[01;34msub-01\u001b[00m\n", + "│   ├── \u001b[01;34msub-02\u001b[00m\n", + "│   ├── \u001b[01;34msub-03\u001b[00m\n", + "│   ├── \u001b[01;34msub-04\u001b[00m\n", + "│   └── \u001b[01;34msub-05\u001b[00m\n", + "├── \u001b[01;34msub-01\u001b[00m\n", + "│   ├── \u001b[01;34mses-01\u001b[00m\n", + "│   │   ├── \u001b[01;34manat\u001b[00m\n", + "│   │   ├── \u001b[01;34mdwi\u001b[00m\n", + "│   │   ├── \u001b[01;34mfmap\u001b[00m\n", + "│   │   └── \u001b[01;34mfunc\u001b[00m\n", + "│   └── \u001b[01;34mses-02\u001b[00m\n", + "│   ├── \u001b[01;34manat\u001b[00m\n", + "│   └── \u001b[01;34mfunc\u001b[00m\n", + "├── \u001b[01;34msub-02\u001b[00m\n", + "│   ├── \u001b[01;34mses-01\u001b[00m\n", + "│   │   ├── \u001b[01;34manat\u001b[00m\n", + "│   │   ├── \u001b[01;34mdwi\u001b[00m\n", + "│   │   ├── \u001b[01;34mfmap\u001b[00m\n", + "│   │   └── \u001b[01;34mfunc\u001b[00m\n", + "│   └── \u001b[01;34mses-02\u001b[00m\n", + "│   ├── \u001b[01;34manat\u001b[00m\n", + "│   └── \u001b[01;34mfunc\u001b[00m\n", + "├── \u001b[01;34msub-03\u001b[00m\n", + "│   ├── \u001b[01;34mses-01\u001b[00m\n", + "│   │   ├── \u001b[01;34manat\u001b[00m\n", + "│   │   ├── \u001b[01;34mdwi\u001b[00m\n", + "│   │   ├── \u001b[01;34mfmap\u001b[00m\n", + "│   │   └── \u001b[01;34mfunc\u001b[00m\n", + "│   └── \u001b[01;34mses-02\u001b[00m\n", + "│   ├── \u001b[01;34manat\u001b[00m\n", + "│   └── \u001b[01;34mfunc\u001b[00m\n", + "├── \u001b[01;34msub-04\u001b[00m\n", + "│   ├── \u001b[01;34mses-01\u001b[00m\n", + "│   │   ├── \u001b[01;34manat\u001b[00m\n", + "│   │   ├── \u001b[01;34mdwi\u001b[00m\n", + "│   │   ├── \u001b[01;34mfmap\u001b[00m\n", + "│   │   └── \u001b[01;34mfunc\u001b[00m\n", + "│   └── \u001b[01;34mses-02\u001b[00m\n", + "│   ├── \u001b[01;34manat\u001b[00m\n", + "│   └── \u001b[01;34mfunc\u001b[00m\n", + "└── \u001b[01;34msub-05\u001b[00m\n", + " ├── \u001b[01;34mses-01\u001b[00m\n", + " │   ├── \u001b[01;34manat\u001b[00m\n", + " │   ├── \u001b[01;34mdwi\u001b[00m\n", + " │   ├── \u001b[01;34mfmap\u001b[00m\n", + " │   └── \u001b[01;34mfunc\u001b[00m\n", + " └── \u001b[01;34mses-02\u001b[00m\n", + " ├── \u001b[01;34manat\u001b[00m\n", + " └── \u001b[01;34mfunc\u001b[00m\n", + "\n", + "53 directories\n" + ] + } + ], + "source": [ + "!tree -d -L 3 ../bids/tests/data/synthetic" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "55a16cf2-663f-4e53-ad1a-a153b3038120", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/remi/github/pybids/bids/layout/validation.py:151: UserWarning: The PipelineDescription field was superseded by GeneratedBy in BIDS 1.4.0. You can use ``pybids upgrade`` to update your derivative dataset.\n", + " warnings.warn(\"The PipelineDescription field was superseded \"\n" + ] + }, + { + "data": { + "text/plain": [ + "BIDS Layout: ...bids/bids/tests/data/synthetic | Subjects: 5 | Sessions: 10 | Runs: 10" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "layout = BIDSLayout(data_path, derivatives=True)\n", + "layout" + ] + }, + { + "cell_type": "markdown", + "id": "3d33e57e-d986-4267-a323-68981f92029f", + "metadata": {}, + "source": [ + "The `scope` argument to `get()` specifies which part of the project to look in. \n", + "\n", + "By default, valid values are `'bids'` (for the \"raw\" BIDS project that excludes derivatives) and `'derivatives'` (for all BIDS-derivatives files). \n", + "\n", + "You can also pass the names of individual derivatives pipelines (e.g., passing `'fmriprep'` would search only in a `/derivatives/fmriprep` folder). Either a string or a list of strings can be passed.\n", + "\n", + "The following call returns the filenames of all derivatives files." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "976f6412-774d-437c-8669-f4c2eb0ea72e", + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + }, + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/dataset_description.json',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_desc-confounds_regressors.tsv',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/task-nback_bold.json',\n", + " '/home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep/task-rest_bold.json']" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Get all files in derivatives\n", + "layout.get(scope=\"derivatives\", return_type=\"file\")" + ] + }, + { + "cell_type": "markdown", + "id": "7ae36c29-c9af-4caf-882e-091a69e09608", + "metadata": {}, + "source": [ + "---\n", + "## Standalone BIDS derivatives\n", + "\n", + "If you only have a BIDS \"derivatives\" that is not nested within a BIDS \"raw\" dataset, you can still index and query it as usual but you must skip the validation when using `BIDSlayout`.\n", + "\n", + "Here we can simulate this directly indexing the fmriprep derivatives that we were using above." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "cc1a73a3-0d71-4758-af1b-d5e31259f946", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing layout with: /home/remi/github/pybids/bids/tests/data/synthetic/derivatives/fmriprep\n" + ] + } + ], + "source": [ + "derivatives_path = os.path.join(get_test_data_path(), \"synthetic\", \"derivatives\", \"fmriprep\")\n", + "print(f\"Initializing layout with: {derivatives_path}\")\n", + "\n", + "derivatives = BIDSLayout(derivatives_path, validate=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "5e51fce9-2328-4684-9423-4ac5d1f39a8f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['02', '04', '03', '01', '05']" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "derivatives.get_subjects()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/filenames.ipynb b/examples/filenames.ipynb new file mode 100644 index 000000000..2bee8e9ca --- /dev/null +++ b/examples/filenames.ipynb @@ -0,0 +1,404 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6265d50b-68d1-4150-b708-5528021e3d59", + "metadata": {}, + "source": [ + "# BIDS filenames and path construction\n", + "\n", + "You may want to create valid BIDS filenames for files that are new or hypothetical that would sit within your BIDS project. \n", + "\n", + "This is useful when you know what entity values you need to write out to, but don't want to deal with looking up the precise BIDS file-naming syntax. \n", + "\n", + "In the example below, imagine we've created a new file containing stimulus presentation information, and we want to save it to a `.tsv.gz` file, per the BIDS naming conventions. \n", + "\n", + "All we need to do is define a dictionary with the name components, and `build_path` takes care of the rest (including injecting sub-directories!):\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d911e0ad-1722-467a-9416-2eb4bb7fe5ef", + "metadata": {}, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "bc49c3d5-8515-4b7b-aaa0-67ffcbba9337", + "metadata": {}, + "outputs": [], + "source": [ + "from bids import BIDSLayout\n", + "from bids.tests import get_test_data_path\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "660b8ce2-f972-49e6-badd-142414efea4f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BIDS Layout: .../pybids/bids/tests/data/7t_trt | Subjects: 10 | Sessions: 20 | Runs: 20" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Here we're using an example BIDS dataset that's bundled with the pybids tests\n", + "data_path = os.path.join(get_test_data_path(), \"7t_trt\")\n", + "\n", + "# Initialize the layout\n", + "raw = BIDSLayout(data_path)\n", + "raw" + ] + }, + { + "cell_type": "markdown", + "id": "452662ca-1ca4-40ef-8136-361e738ffdeb", + "metadata": {}, + "source": [ + "Let's pretend we are about to create some derivatives data for that dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1f68a6ec-abd1-4c93-b654-b9e41f3a195a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BIDS Layout: ...data/7t_trt/derivatives/pybids | Subjects: 0 | Sessions: 0 | Runs: 0" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pipeline_name = \"pybids\"\n", + "derivative_dir = os.path.join(raw.root, \"derivatives\", pipeline_name)\n", + "\n", + "if not os.path.exists(derivative_dir):\n", + " os.makedirs(derivative_dir)\n", + "derivative = BIDSLayout(derivative_dir, validate=False)\n", + "derivative" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "0586749a-67d3-47f2-b9f5-49823f685077", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'acquisition': 'fullbrain',\n", + " 'datatype': 'func',\n", + " 'extension': '.nii.gz',\n", + " 'run': 1,\n", + " 'session': '1',\n", + " 'subject': '01',\n", + " 'suffix': 'bold',\n", + " 'task': 'rest'}" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bf = raw.get(subject=\"01\", session=\"1\", run=1, suffix=\"bold\", extension=\"nii.gz\")\n", + "entities = bf[0].get_entities()\n", + "entities" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "5b76b2d5-47e1-4f18-bb64-655c5caa8338", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'/home/remi/github/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-fullbrain_run-1_bold.nii.gz'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "raw.build_path(entities)" + ] + }, + { + "cell_type": "markdown", + "id": "dc0507b4-e1d2-4d31-969d-4f38198f326f", + "metadata": {}, + "source": [ + "You can also use `build_path` in more sophisticated ways—for example, by defining your own set of matching templates that cover cases not supported by BIDS out of the box. \n", + "\n", + "For example, suppose you want to create a template for naming a new z-stat file. \n", + "\n", + "You could do something like:" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "8acdd5dd-a6b0-41cd-9ebe-8ecca45ae3e4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sub-{subject}/[ses-{session}]/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_rec-{reconstruction}][_run-{run}][_echo-{echo}][_desc-{desc}]_{suffix}.{extension}\n" + ] + }, + { + "data": { + "text/plain": [ + "'/home/remi/github/pybids/bids/tests/data/7t_trt/derivatives/pybids/sub-01/ses-1/sub-01_ses-1_task-rest_acq-fullbrain_run-1_desc-mean_bold.nii.gz'" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Define the pattern to build out of the components passed in the dictionary\n", + "filename_pattern = (\n", + " \"sub-{subject}\"\n", + " + \"[_ses-{session}]\"\n", + " + \"_task-{task}\"\n", + " + \"[_acq-{acquisition}]\"\n", + " + \"[_rec-{reconstruction}]\"\n", + " + \"[_run-{run}]\"\n", + " + \"[_echo-{echo}]\"\n", + " + \"[_desc-{desc}]\"\n", + " + \"_{suffix}.{extension}\"\n", + ")\n", + "pattern = os.path.join(\"sub-{subject}\", \"[ses-{session}]\", filename_pattern)\n", + "print(pattern)\n", + "\n", + "entities[\"desc\"] = \"mean\"\n", + "\n", + "# Notice we pass the new pattern as the second argument\n", + "derivative.build_path(entities, pattern, validate=False)" + ] + }, + { + "cell_type": "markdown", + "id": "eb774262-8ca6-4ae9-a49e-6949f13fd1bb", + "metadata": {}, + "source": [ + "Note that in the above example, we set `validate=False` to ensure that the standard BIDS file validator doesn't run (because the pattern we defined isn't actually compliant with the BIDS specification)." + ] + }, + { + "cell_type": "markdown", + "id": "c8e21def-270c-4155-8bd1-61e8c6a93c5c", + "metadata": {}, + "source": [ + "### Writing to files" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2c4244d4-a128-48cf-a0d3-0cd5550556d9", + "metadata": {}, + "outputs": [], + "source": [ + "def set_dataset_description(is_derivative=True):\n", + "\n", + " content = {\n", + " \"Name\": \"dataset name\",\n", + " \"BIDSVersion\": \"1.6.0\",\n", + " \"DatasetType\": \"raw\",\n", + " \"License\": \"\",\n", + " \"Authors\": [\"\", \"\"],\n", + " \"Acknowledgements\": \"Special thanks to \",\n", + " \"HowToAcknowledge\": \"Please cite this paper: \",\n", + " \"Funding\": [\"\", \"\"],\n", + " \"EthicsApprovals\": [\"\"],\n", + " \"ReferencesAndLinks\": [\"\", \"\"],\n", + " \"DatasetDOI\": \"doi:\",\n", + " \"HEDVersion\": \"\",\n", + " }\n", + "\n", + " if is_derivative:\n", + " content[\"GeneratedBy\"] = [\n", + " {\n", + " \"Name\": \"\",\n", + " \"Version\": \"\",\n", + " \"Container\": {\"Type\": \"\", \"Tag\": \"\"},\n", + " \"Description\": \"\",\n", + " \"CodeURL\": \"\",\n", + " },\n", + " ]\n", + "\n", + " content[\"SourceDatasets\"] = [\n", + " {\n", + " \"DOI\": \"doi:\",\n", + " \"URL\": \"\",\n", + " \"Version\": \"\",\n", + " }\n", + " ]\n", + "\n", + " return content" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "d73d1007-053d-4016-832e-5f75fb9218d7", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from bids.layout.writing import write_to_file" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "c6c52009-b610-47d5-a656-294c624d20fd", + "metadata": {}, + "outputs": [], + "source": [ + "entities = {\"suffix\": \"dataset_description\", \"extension\": \".json\"}\n", + "\n", + "content = set_dataset_description()\n", + "\n", + "# derivative.write_to_file(entities, json.dumps(content), validate=False, strict=False)\n", + "\n", + "write_to_file(\n", + " root=derivative.root, path=\"dataset_description.json\", contents=json.dumps(content)\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "c589aa14-e590-4923-83de-c734cd56dfa7", + "metadata": {}, + "source": [ + "### TODO\n", + "\n", + "write json for derivatives" + ] + }, + { + "cell_type": "markdown", + "id": "485201b5-e761-4ec4-aa83-82981f56cd07", + "metadata": { + "tags": [] + }, + "source": [ + "## Other utilities\n", + "\n", + "### Filename parsing\n", + "Say you have a filename, and you want to manually extract BIDS entities from it. The `parse_file_entities` method provides the facility:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "bc599eae-05af-4235-99f7-f57c809dc420", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'subject': '01', 'run': 1, 'suffix': 'T2w', 'extension': '.nii.gz'}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path = \"/a/fake/path/to/a/BIDS/file/sub-01_run-1_T2w.nii.gz\"\n", + "raw.parse_file_entities(path)" + ] + }, + { + "cell_type": "markdown", + "id": "0c67050c-f23b-454c-9858-f6c17d4f14ee", + "metadata": {}, + "source": [ + "A version of this utility independent of a specific layout is available at `bids.layout` ([doc](https://bids-standard.github.io/pybids/generated/bids.layout.parse_file_entities.html#bids.layout.parse_file_entities))." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "8e5de108-4caa-4baa-8883-9eb2c52b6fd0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'subject': '01', 'run': 1, 'suffix': 'T2w', 'extension': '.nii.gz'}" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from bids.layout import parse_file_entities\n", + "\n", + "path = \"/a/fake/path/to/a/BIDS/file/sub-01_run-1_T2w.nii.gz\"\n", + "parse_file_entities(path)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/pybids_tutorial.ipynb b/examples/pybids_tutorial.ipynb deleted file mode 100644 index eabb8627c..000000000 --- a/examples/pybids_tutorial.ipynb +++ /dev/null @@ -1,1998 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Introduction to `pybids`\n", - "\n", - "[`pybids`](https://github.com/bids-standard/pybids) is a tool to query, summarize and manipulate data using the BIDS standard. \n", - "In this tutorial we will use a `pybids` test dataset to illustrate some of the functionality of `pybids.layout`" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:23.628184Z", - "start_time": "2018-08-01T20:05:22.060937Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "from bids import BIDSLayout\n", - "from bids.tests import get_test_data_path\n", - "import os" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The `BIDSLayout`\n", - "\n", - "At the core of pybids is the `BIDSLayout` object. A `BIDSLayout` is a lightweight Python class that represents a BIDS project file tree and provides a variety of helpful methods for querying and manipulating BIDS files. While the `BIDSLayout` initializer has a large number of arguments you can use to control the way files are indexed and accessed, you will most commonly initialize a `BIDSLayout` by passing in the BIDS dataset root location as a single argument:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:23.739377Z", - "start_time": "2018-08-01T20:05:23.630505Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "BIDS Layout: .../pybids/bids/tests/data/7t_trt | Subjects: 10 | Sessions: 20 | Runs: 20" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Here we're using an example BIDS dataset that's bundled with the pybids tests\n", - "data_path = os.path.join(get_test_data_path(), '7t_trt')\n", - "\n", - "# Initialize the layout\n", - "layout = BIDSLayout(data_path)\n", - "\n", - "# Print some basic information about the layout\n", - "layout" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Querying the `BIDSLayout`\n", - "When we initialize a `BIDSLayout`, all of the files and metadata found under the specified root folder are indexed. This can take a few seconds (or, for very large datasets, a minute or two). Once initialization is complete, we can start querying the `BIDSLayout` in various ways. The workhorse method is [`.get()`](https://bids-standard.github.io/pybids/generated/bids.grabbids.BIDSLayout.html#bids.grabbids.BIDSLayout.get). If we call `.get()` with no additional arguments, we get back a list of all the BIDS files in our dataset:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "There are 339 files in the layout.\n", - "\n", - "The first 10 files are:\n" - ] - }, - { - "data": { - "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ,\n", - " ]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "all_files = layout.get()\n", - "print(\"There are {} files in the layout.\".format(len(all_files)))\n", - "print(\"\\nThe first 10 files are:\")\n", - "all_files[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The returned object is a Python list. By default, each element in the list is a `BIDSFile` object. We discuss the `BIDSFile` object in much more detail below. For now, let's simplify things and work with just filenames:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/dataset_description.json',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/participants.tsv',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/README',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/anat/sub-01_ses-1_T1map.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/anat/sub-01_ses-1_T1w.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_magnitude1.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_magnitude2.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_phasediff.json',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-1_phasediff.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/fmap/sub-01_ses-1_run-2_magnitude1.nii.gz']" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "layout.get(return_type='filename')[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This time, we get back only the names of the files.\n", - "\n", - "### Filtering files by entities\n", - "The utility of the `BIDSLayout` would be pretty limited if all we could do was retrieve a list of all files in the dataset. Fortunately, the `.get()` method accepts all kinds of arguments that allow us to filter the result set based on specified criteria. In fact, we can pass *any* BIDS-defined keywords (or, as they're called in PyBIDS, *entities*) as constraints. For example, here's how we would retrieve all BOLD runs with `.nii.gz` extensions for subject `'01'`:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-fullbrain_run-1_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-fullbrain_run-2_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-prefrontal_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-2/func/sub-01_ses-2_task-rest_acq-fullbrain_run-1_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-2/func/sub-01_ses-2_task-rest_acq-fullbrain_run-2_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01/ses-2/func/sub-01_ses-2_task-rest_acq-prefrontal_bold.nii.gz']" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Retrieve filenames of all BOLD runs for subject 01\n", - "layout.get(subject='01', extension='nii.gz', suffix='bold', return_type='filename')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you're wondering what entities you can pass in as filtering arguments, the answer is contained in the `.json` configuration files [housed here](https://github.com/bids-standard/pybids/tree/master/bids/layout/config). To save you the trouble, here are a few of the most common entities:\n", - "\n", - "* `suffix`: The part of a BIDS filename just before the extension (e.g., `'bold'`, `'events'`, `'physio'`, etc.).\n", - "* `subject`: The subject label\n", - "* `session`: The session label\n", - "* `run`: The run index\n", - "* `task`: The task name\n", - "\n", - "New entities are continually being defined as the spec grows, and in principle (though not always in practice), PyBIDS should be aware of all entities that are defined in the BIDS specification.\n", - "\n", - "### Filtering by metadata\n", - "All of the entities listed above are found in the names of BIDS files. But sometimes we want to search for files based not just on their names, but also based on metadata defined (per the BIDS spec) in JSON files. Fortunately for us, when we initialize a `BIDSLayout`, all metadata files associated with BIDS files are automatically indexed. This means we can pass any key that occurs in any JSON file in our project as an argument to `.get()`. We can combine these with any number of core BIDS entities (like `subject`, `run`, etc.).\n", - "\n", - "For example, say we want to retrieve all files where (a) the value of `SamplingFrequency` (a metadata key) is `100`, (b) the `acquisition` type is `'prefrontal'`, and (c) the subject is `'01'` or `'02'`. Here's how we can do that:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Retrieve all files where SamplingFrequency (a metadata key) = 100\n", - "# and acquisition = prefrontal, for the first two subjects\n", - "layout.get(subject=['01', '02'], SamplingFrequency=100, acquisition=\"prefrontal\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that we passed a list in for `subject` rather than just a string. This principle applies to all filters: you can always pass in a list instead of a single value, and this will be interpreted as a logical disjunction (i.e., a file must match any one of the provided values).\n", - "\n", - "### Other `return_type` values\n", - "While we'll typically want to work with either `BIDSFile` objects or filenames, we can also ask `get()` to return unique values (or ids) of particular entities. For example, say we want to know which subjects have at least one `T1w` file. We can request that information by setting `return_type='id'`. When using this option, we also need to specify a target entity (or metadata keyword) called `target`. This combination tells the `BIDSLayout` to return the unique values for the specified `target` entity. For example, in the next example, we ask for all of the unique subject IDs that have at least one file with a `T1w` suffix:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:23.964766Z", - "start_time": "2018-08-01T20:05:23.957477Z" - }, - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "['01', '02', '03', '04', '05', '06', '07', '08', '09', '10']" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Ask get() to return the ids of subjects that have T1w files\n", - "layout.get(return_type='id', target='subject', suffix='T1w')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If our `target` is a BIDS entity that corresponds to a particular directory in the BIDS spec (e.g., `subject` or `session`) we can also use `return_type='dir'` to get all matching subdirectories:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:23.983125Z", - "start_time": "2018-08-01T20:05:23.975085Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "['/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-01',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-02',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-03',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-04',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-05',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-06',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-07',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-08',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-09',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/7t_trt/sub-10']" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "layout.get(return_type='dir', target='subject')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Other `get()` options\n", - "The `.get()` method has a number of other useful arguments that control its behavior. We won't discuss these in detail here, but briefly, here are a couple worth knowing about:\n", - "* `regex_search`: If you set this to `True`, string filter argument values will be interpreted as regular expressions.\n", - "* `scope`: If your BIDS dataset contains BIDS-derivatives sub-datasets, you can specify the scope (e.g., `derivatives`, or a BIDS-Derivatives pipeline name) of the search space." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The `BIDSFile`\n", - "When you call `.get()` on a `BIDSLayout`, the default returned values are objects of class `BIDSFile`. A `BIDSFile` is a lightweight container for individual files in a BIDS dataset. It provides easy access to a variety of useful attributes and methods. Let's take a closer look. First, let's pick a random file from our existing `layout`." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:23.926278Z", - "start_time": "2018-08-01T20:05:23.741189Z" - }, - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Pick the 15th file in the dataset\n", - "bf = layout.get()[15]\n", - "\n", - "# Print it\n", - "bf" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here are some of the attributes and methods available to us in a `BIDSFile` (note that some of these are only available for certain subclasses of `BIDSFile`; e.g., you can't call `get_image()` on a `BIDSFile` that doesn't correspond to an image file!):\n", - "* `.path`: The full path of the associated file\n", - "* `.filename`: The associated file's filename (without directory)\n", - "* `.dirname`: The directory containing the file\n", - "* `.get_entities()`: Returns information about entities associated with this `BIDSFile` (optionally including metadata)\n", - "* `.get_image()`: Returns the file contents as a nibabel image (only works for image files)\n", - "* `.get_df()`: Get file contents as a pandas DataFrame (only works for TSV files)\n", - "* `.get_metadata()`: Returns a dictionary of all metadata found in associated JSON files\n", - "* `.get_associations()`: Returns a list of all files associated with this one in some way\n", - "\n", - "Let's see some of these in action." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'acquisition': 'fullbrain',\n", - " 'datatype': 'func',\n", - " 'extension': 'tsv.gz',\n", - " 'run': 1,\n", - " 'session': '1',\n", - " 'subject': '01',\n", - " 'suffix': 'physio',\n", - " 'task': 'rest'}" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Print all the entities associated with this file, and their values\n", - "bf.get_entities()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'Columns': ['cardiac', 'respiratory', 'trigger', 'oxygen saturation'],\n", - " 'SamplingFrequency': 100,\n", - " 'StartTime': 0}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Print all the metadata associated with this file\n", - "bf.get_metadata()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'Columns': ['cardiac', 'respiratory', 'trigger', 'oxygen saturation'],\n", - " 'SamplingFrequency': 100,\n", - " 'StartTime': 0,\n", - " 'acquisition': 'fullbrain',\n", - " 'datatype': 'func',\n", - " 'extension': 'tsv.gz',\n", - " 'run': 1,\n", - " 'session': '1',\n", - " 'subject': '01',\n", - " 'suffix': 'physio',\n", - " 'task': 'rest'}" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# We can the union of both of the above in one shot like this\n", - "bf.get_entities(metadata='all')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here are all the files associated with our target file in some way. Notice how we get back both the JSON sidecar for our target file, and the BOLD run that our target file contains physiological recordings for." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ]" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bf.get_associations()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "slideshow": { - "slide_type": "slide" - } - }, - "source": [ - "In cases where a file has a `.tsv.gz` or `.tsv` extension, it will automatically be created as a `BIDSDataFile`, and we can easily grab the contents as a pandas `DataFrame`:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
onsetrespiratorycardiac
00.0-0.7573420.048933
10.1-0.7968510.355185
20.2-0.8332150.626669
30.3-0.8662910.836810
40.4-0.8959480.965038
\n", - "
" - ], - "text/plain": [ - " onset respiratory cardiac\n", - "0 0.0 -0.757342 0.048933\n", - "1 0.1 -0.796851 0.355185\n", - "2 0.2 -0.833215 0.626669\n", - "3 0.3 -0.866291 0.836810\n", - "4 0.4 -0.895948 0.965038" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Use a different test dataset--one that contains physio recording files\n", - "data_path = os.path.join(get_test_data_path(), 'synthetic')\n", - "layout2 = BIDSLayout(data_path)\n", - "\n", - "# Get the first physiological recording file\n", - "recfile = layout2.get(suffix='physio')[0]\n", - "\n", - "# Get contents as a DataFrame and show the first few rows\n", - "df = recfile.get_df()\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "While it would have been easy enough to read the contents of the file ourselves with pandas' `read_csv()` method, notice that in the above example, `get_df()` saved us the trouble of having to read the physiological recording file's metadata, pull out the column names and sampling rate, and add timing information.\n", - "\n", - "Mind you, if we don't *want* the timing information, we can ignore it:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
respiratorycardiac
0-0.7573420.048933
1-0.7968510.355185
2-0.8332150.626669
3-0.8662910.836810
4-0.8959480.965038
\n", - "
" - ], - "text/plain": [ - " respiratory cardiac\n", - "0 -0.757342 0.048933\n", - "1 -0.796851 0.355185\n", - "2 -0.833215 0.626669\n", - "3 -0.866291 0.836810\n", - "4 -0.895948 0.965038" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "recfile.get_df(include_timing=False).head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Other utilities\n", - "\n", - "### Filename parsing\n", - "Say you have a filename, and you want to manually extract BIDS entities from it. The `parse_file_entities` method provides the facility:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:24.035216Z", - "start_time": "2018-08-01T20:05:24.030080Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'subject': '01', 'run': 1, 'suffix': 'T2w', 'extension': 'nii.gz'}" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "path = \"/a/fake/path/to/a/BIDS/file/sub-01_run-1_T2w.nii.gz\"\n", - "layout.parse_file_entities(path)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A version of this utility independent of a specific layout is available at `bids.layout` ([doc](https://bids-standard.github.io/pybids/generated/bids.layout.parse_file_entities.html#bids.layout.parse_file_entities)) - " - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'extension': 'nii.gz', 'run': 1, 'subject': '01', 'suffix': 'T2w'}" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from bids.layout import parse_file_entities\n", - "\n", - "path = \"/a/fake/path/to/a/BIDS/file/sub-01_run-1_T2w.nii.gz\"\n", - "parse_file_entities(path)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Path construction\n", - "You may want to create valid BIDS filenames for files that are new or hypothetical that would sit within your BIDS project. This is useful when you know what entity values you need to write out to, but don't want to deal with looking up the precise BIDS file-naming syntax. In the example below, imagine we've created a new file containing stimulus presentation information, and we want to save it to a `.tsv.gz` file, per the BIDS naming conventions. All we need to do is define a dictionary with the name components, and `build_path` takes care of the rest (including injecting sub-directories!):" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:24.049418Z", - "start_time": "2018-08-01T20:05:24.044544Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "'sub-01/func/sub-01_task-nback_run-2_bold.nii.gz'" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "entities = {\n", - " 'subject': '01',\n", - " 'run': 2,\n", - " 'task': 'nback',\n", - " 'suffix': 'bold'\n", - "}\n", - "\n", - "layout.build_path(entities)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:24.064220Z", - "start_time": "2018-08-01T20:05:24.058906Z" - }, - "scrolled": false - }, - "source": [ - "You can also use `build_path` in more sophisticated ways—for example, by defining your own set of matching templates that cover cases not supported by BIDS out of the box. For example, suppose you want to create a template for naming a new z-stat file. You could do something like:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'sub-01_task-nback_run-2_z.nii.gz'" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Define the pattern to build out of the components passed in the dictionary\n", - "pattern = \"sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_rec-{reconstruction}][_run-{run}][_echo-{echo}]_{suffix}.nii.gz\",\n", - "\n", - "entities = {\n", - " 'subject': '01',\n", - " 'run': 2,\n", - " 'task': 'nback',\n", - " 'suffix': 'z'\n", - "}\n", - "\n", - "# Notice we pass the new pattern as the second argument\n", - "layout.build_path(entities, pattern, validate=False)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that in the above example, we set `validate=False` to ensure that the standard BIDS file validator doesn't run (because the pattern we defined isn't actually compliant with the BIDS specification)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Loading derivatives\n", - "\n", - "By default, `BIDSLayout` objects are initialized without scanning contained `derivatives/` directories. But you can easily ensure that all derivatives files are loaded and endowed with the extra structure specified in the [derivatives config file](https://github.com/bids-standard/pybids/blob/master/bids/layout/config/derivatives.json):" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:24.228683Z", - "start_time": "2018-08-01T20:05:24.066251Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "BIDS Layout: ...bids/bids/tests/data/synthetic | Subjects: 5 | Sessions: 10 | Runs: 10" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Define paths to root and derivatives folders\n", - "root = os.path.join(get_test_data_path(), 'synthetic')\n", - "layout2 = BIDSLayout(root, derivatives=True)\n", - "layout2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `scope` argument to `get()` specifies which part of the project to look in. By default, valid values are `'bids'` (for the \"raw\" BIDS project that excludes derivatives) and `'derivatives'` (for all BIDS-derivatives files). You can also pass the names of individual derivatives pipelines (e.g., passing `'fmriprep'` would search only in a `/derivatives/fmriprep` folder). Either a string or a list of strings can be passed.\n", - "\n", - "The following call returns the filenames of all derivatives files." - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:24.245649Z", - "start_time": "2018-08-01T20:05:24.230490Z" - }, - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "['/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/dataset_description.json',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-01/ses-02/func/sub-01_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-01/func/sub-02_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-02/ses-02/func/sub-02_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-01/func/sub-03_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-03/ses-02/func/sub-03_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-01/func/sub-04_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-04/ses-02/func/sub-04_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-01/func/sub-05_ses-01_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-01_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-nback_run-02_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_desc-confounds_regressors.tsv.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-brain_mask.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-brain_mask.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-preproc_bold.nii',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/sub-05/ses-02/func/sub-05_ses-02_task-rest_space-T1w_desc-preproc_bold.nii.gz',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/task-nback_bold.json',\n", - " '/Users/tal/Dropbox/Code/pybids/bids/tests/data/synthetic/derivatives/fmriprep/task-rest_bold.json']" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get all files in derivatives\n", - "layout2.get(scope='derivatives', return_type='file')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting a `BIDSLayout` to a pandas `Dataframe`\n", - "If you want a summary of all the files in your `BIDSLayout`, but don't want to have to iterate `BIDSFile` objects and extract their entities, you can get a nice bird's-eye view of your dataset using the `to_df()` method." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:24.275066Z", - "start_time": "2018-08-01T20:05:24.248179Z" - }, - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
entitypathacquisitiondatatypeextensionfmaprunscanssessionsubjectsuffixtask
0/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNjsonNaNNaNNaNNaNNaNdescriptionNaN
1/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNtsvNaNNaNNaNNaNNaNparticipantsNaN
2/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNanatnii.gzNaNNaNNaN101T1mapNaN
3/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNanatnii.gzNaNNaNNaN101T1wNaN
4/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNfmapnii.gzmagnitude11NaN101magnitude1NaN
\n", - "
" - ], - "text/plain": [ - "entity path acquisition \\\n", - "0 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN \n", - "1 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN \n", - "2 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN \n", - "3 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN \n", - "4 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN \n", - "\n", - "entity datatype extension fmap run scans session subject \\\n", - "0 NaN json NaN NaN NaN NaN NaN \n", - "1 NaN tsv NaN NaN NaN NaN NaN \n", - "2 anat nii.gz NaN NaN NaN 1 01 \n", - "3 anat nii.gz NaN NaN NaN 1 01 \n", - "4 fmap nii.gz magnitude1 1 NaN 1 01 \n", - "\n", - "entity suffix task \n", - "0 description NaN \n", - "1 participants NaN \n", - "2 T1map NaN \n", - "3 T1w NaN \n", - "4 magnitude1 NaN " - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Convert the layout to a pandas dataframe\n", - "df = layout.to_df()\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also include metadata in the result if we like (which may blow up our `DataFrame` if we have a large dataset). Note that in this case, most of our cells will have missing values." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
entitypathCogAtlasIDColumnsEchoTimeEchoTime1EchoTime2EffectiveEchoSpacingIntendedForPhaseEncodingDirectionRepetitionTime...acquisitiondatatypeextensionfmaprunscanssessionsubjectsuffixtask
0/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNjsonNaNNaNNaNNaNNaNdescriptionNaN
1/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNtsvNaNNaNNaNNaNNaNparticipantsNaN
2/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNanatnii.gzNaNNaNNaN101T1mapNaN
3/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNanatnii.gzNaNNaNNaN101T1wNaN
4/Users/tal/Dropbox/Code/pybids/bids/tests/data...NaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNfmapnii.gzmagnitude11NaN101magnitude1NaN
\n", - "

5 rows × 25 columns

\n", - "
" - ], - "text/plain": [ - "entity path CogAtlasID Columns \\\n", - "0 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN NaN \n", - "1 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN NaN \n", - "2 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN NaN \n", - "3 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN NaN \n", - "4 /Users/tal/Dropbox/Code/pybids/bids/tests/data... NaN NaN \n", - "\n", - "entity EchoTime EchoTime1 EchoTime2 EffectiveEchoSpacing IntendedFor \\\n", - "0 NaN NaN NaN NaN NaN \n", - "1 NaN NaN NaN NaN NaN \n", - "2 NaN NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN NaN \n", - "4 NaN NaN NaN NaN NaN \n", - "\n", - "entity PhaseEncodingDirection RepetitionTime ... acquisition datatype \\\n", - "0 NaN NaN ... NaN NaN \n", - "1 NaN NaN ... NaN NaN \n", - "2 NaN NaN ... NaN anat \n", - "3 NaN NaN ... NaN anat \n", - "4 NaN NaN ... NaN fmap \n", - "\n", - "entity extension fmap run scans session subject suffix task \n", - "0 json NaN NaN NaN NaN NaN description NaN \n", - "1 tsv NaN NaN NaN NaN NaN participants NaN \n", - "2 nii.gz NaN NaN NaN 1 01 T1map NaN \n", - "3 nii.gz NaN NaN NaN 1 01 T1w NaN \n", - "4 nii.gz magnitude1 1 NaN 1 01 magnitude1 NaN \n", - "\n", - "[5 rows x 25 columns]" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "layout.to_df(metadata=True).head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Retrieving BIDS variables \n", - "BIDS variables are stored in .tsv files at the run, session, subject, or dataset level. You can retrieve these variables with `layout.get_collections()`. The resulting objects can be converted to dataframes and merged with the layout to associate the variables with corresponding scans.\n", - "\n", - "In the following example, we request all subject-level variable data available anywhere in the BIDS project, and merge the results into a single `DataFrame` (by default, we'll get back a single `BIDSVariableCollection` object for each subject). " - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:26.693372Z", - "start_time": "2018-08-01T20:05:24.276799Z" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
suffixsessionsubjectCCPT_FN_countCCPT_FP_countCCPT_avg_FN_RTCCPT_avg_FP_RTCCPT_avg_succ_RTCCPT_succ_countcaffeine_daily...relative_water_intakespecific_vaguesubject_idsurroundingssystolic_blood_pressure_leftsystolic_blood_pressure_rightthirstvigilancevigilance_nyc-qwords
0sessions1010.01.0NaN507.0500.77083396.00.5...7.095.01.00.0108.0109.09.09.0100.0100.0
1sessions1020.05.0NaN297.6351.72916796.00.0...1.0100.02.070.099.0100.02.07.0100.0100.0
2sessions1030.01.0NaN441.0426.71875096.01.0...3.0100.03.010.0122.0128.03.08.0100.00.0
3sessions1040.01.0NaN443.0417.90625096.00.1...5.080.04.00.0130.0110.06.05.0100.085.0
4sessions1050.02.0NaN355.5372.11458396.00.0...5.075.05.080.0105.0117.07.07.060.030.0
\n", - "

5 rows × 97 columns

\n", - "
" - ], - "text/plain": [ - " suffix session subject CCPT_FN_count CCPT_FP_count CCPT_avg_FN_RT \\\n", - "0 sessions 1 01 0.0 1.0 NaN \n", - "1 sessions 1 02 0.0 5.0 NaN \n", - "2 sessions 1 03 0.0 1.0 NaN \n", - "3 sessions 1 04 0.0 1.0 NaN \n", - "4 sessions 1 05 0.0 2.0 NaN \n", - "\n", - " CCPT_avg_FP_RT CCPT_avg_succ_RT CCPT_succ_count caffeine_daily ... \\\n", - "0 507.0 500.770833 96.0 0.5 ... \n", - "1 297.6 351.729167 96.0 0.0 ... \n", - "2 441.0 426.718750 96.0 1.0 ... \n", - "3 443.0 417.906250 96.0 0.1 ... \n", - "4 355.5 372.114583 96.0 0.0 ... \n", - "\n", - " relative_water_intake specific_vague subject_id surroundings \\\n", - "0 7.0 95.0 1.0 0.0 \n", - "1 1.0 100.0 2.0 70.0 \n", - "2 3.0 100.0 3.0 10.0 \n", - "3 5.0 80.0 4.0 0.0 \n", - "4 5.0 75.0 5.0 80.0 \n", - "\n", - " systolic_blood_pressure_left systolic_blood_pressure_right thirst \\\n", - "0 108.0 109.0 9.0 \n", - "1 99.0 100.0 2.0 \n", - "2 122.0 128.0 3.0 \n", - "3 130.0 110.0 6.0 \n", - "4 105.0 117.0 7.0 \n", - "\n", - " vigilance vigilance_nyc-q words \n", - "0 9.0 100.0 100.0 \n", - "1 7.0 100.0 100.0 \n", - "2 8.0 100.0 0.0 \n", - "3 5.0 100.0 85.0 \n", - "4 7.0 60.0 30.0 \n", - "\n", - "[5 rows x 97 columns]" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get subject variables as a dataframe and merge them back in with the layout\n", - "subj_df = layout.get_collections(level='subject', merge=True).to_df()\n", - "subj_df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## BIDSValidator\n", - "\n", - "`pybids` implicitly imports a `BIDSValidator` class from the separate [`bids-validator`](https://github.com/bids-standard/bids-validator) package. You can use the `BIDSValidator` to determine whether a filepath is a valid BIDS filepath, as well as answering questions about what kind of data it represents. Note, however, that this implementation of the BIDS validator is *not* necessarily up-to-date with the JavaScript version available online. Moreover, the Python validator only tests individual files, and is currently unable to validate entire BIDS datasets. For that, you should use the [online BIDS validator](https://bids-standard.github.io/bids-validator/)." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:27.763448Z", - "start_time": "2018-08-01T20:05:27.749652Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from bids import BIDSValidator\n", - "\n", - "# Note that when using the bids validator, the filepath MUST be relative to the top level bids directory\n", - "validator = BIDSValidator()\n", - "validator.is_bids('/sub-02/ses-01/anat/sub-02_ses-01_T2w.nii.gz')" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:27.773052Z", - "start_time": "2018-08-01T20:05:27.765263Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Can decide if a filepath represents a file part of the specification\n", - "validator.is_file('/sub-02/ses-01/anat/sub-02_ses-01_T2w.json')" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Can check if a file is at the top level of the dataset\n", - "validator.is_top_level('/dataset_description.json')" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# or subject (or session) level\n", - "validator.is_subject_level('/dataset_description.json')" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "validator.is_session_level('/sub-02/ses-01/sub-02_ses-01_scans.json')" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "ExecuteTime": { - "end_time": "2018-08-01T20:05:27.780022Z", - "start_time": "2018-08-01T20:05:27.775281Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Can decide if a filepath represents phenotypic data\n", - "validator.is_phenotypic('/sub-02/ses-01/anat/sub-02_ses-01_T2w.nii.gz')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.8" - }, - "toc": { - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "toc_cell": false, - "toc_position": {}, - "toc_section_display": "block", - "toc_window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/reports_tutorial.ipynb b/examples/reports.ipynb similarity index 85% rename from examples/reports_tutorial.ipynb rename to examples/reports.ipynb index 82492fc70..ddbdf1713 100644 --- a/examples/reports_tutorial.ipynb +++ b/examples/reports.ipynb @@ -7,28 +7,32 @@ "source": [ "# Writing methods reports with `pybids`\n", "\n", - "This tutorial \n" + "This tutorial shows how to automatically generate a short \"method section\" to describe a BIDS dataset.\n", + "\n", + "This part of pybids is under development and not all imaging modalities are supported.\n" ] }, { "cell_type": "code", - "execution_count": 17, - "id": "959473c9", + "execution_count": 1, + "id": "dc26f62f-9f70-47da-9e10-f3a873c388c5", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ - "%load_ext autoreload\n", - "%autoreload 2\n", + "# lint with black\n", + "%load_ext lab_black\n", "\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1203313a-9b12-4ae5-bf9c-1acf3a388e2b", + "metadata": {}, + "outputs": [], + "source": [ "from bids import BIDSLayout\n", "from bids.reports import BIDSReport\n", "from bids.tests import get_test_data_path\n", @@ -37,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 3, "id": "f85ceea3", "metadata": {}, "outputs": [], @@ -53,18 +57,18 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 4, "id": "9e705137", "metadata": {}, "outputs": [], "source": [ "# Initialize a report for the dataset\n", - "report = BIDSReport(layout)\n" + "report = BIDSReport(layout)" ] }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 5, "id": "e152516d", "metadata": {}, "outputs": [ @@ -72,26 +76,28 @@ "name": "stderr", "output_type": "stream", "text": [ + "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-02_ses-01_magnitude1.nii.gz not yet supported.\n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", + "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-02_ses-01_magnitude2.nii.gz not yet supported.\n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", + "/home/remi/github/pybids/bids/layout/models.py:213: UserWarning: Accessing entities as attributes is deprecated as of 0.7. Please use the .entities dictionary instead (i.e., .entities['run'] instead of .run.\n", + " warnings.warn(\"Accessing entities as attributes is deprecated as \"\n", "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-01_ses-01_magnitude1.nii.gz not yet supported.\n", - " \n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-01_ses-01_magnitude2.nii.gz not yet supported.\n", - " \n", - "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-03_ses-01_magnitude1.nii.gz not yet supported.\n", - " \n", - "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-03_ses-01_magnitude2.nii.gz not yet supported.\n", - " \n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-05_ses-01_magnitude1.nii.gz not yet supported.\n", - " \n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-05_ses-01_magnitude2.nii.gz not yet supported.\n", - " \n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-04_ses-01_magnitude1.nii.gz not yet supported.\n", - " \n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-04_ses-01_magnitude2.nii.gz not yet supported.\n", - " \n", - "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-02_ses-01_magnitude1.nii.gz not yet supported.\n", - " \n", - "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-02_ses-01_magnitude2.nii.gz not yet supported.\n", - " \n" + " warnings.warn(group[0].filename + \" not yet supported.\")\n", + "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-03_ses-01_magnitude1.nii.gz not yet supported.\n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n", + "/home/remi/github/pybids/bids/reports/parsing.py:387: UserWarning: sub-03_ses-01_magnitude2.nii.gz not yet supported.\n", + " warnings.warn(group[0].filename + \" not yet supported.\")\n" ] }, { @@ -105,12 +111,12 @@ ], "source": [ "# Method generate returns a Counter of unique descriptions across subjects\n", - "descriptions = report.generate()\n" + "descriptions = report.generate()" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 6, "id": "53b1d147", "metadata": { "scrolled": true @@ -120,12 +126,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "In session 01, MR data were acquired using a UNKNOWN-Tesla MANUFACTURER MODEL MRI scanner.\n", + "In session 02, MR data were acquired using a UNKNOWN-Tesla MANUFACTURER MODEL MRI scanner.\n", "\tOne run of T1-weighted single-echo structural MRI data were collected (256 slices; repetition time, TR=2500ms; echo time, TE=2.9ms; flip angle, FA=8; field of view, FOV=256x256mm; matrix size=256x256; voxel size=1x1x1mm).\n", "\tOne run of T1-weighted single-echo structural MRI data were collected (256 slices; repetition time, TR=2500ms; echo time, TE=2.9ms; flip angle, FA=8; field of view, FOV=256x256mm; matrix size=256x256; voxel size=1x1x1mm).\n", "\tOne run of diffusion-weighted (dMRI) data were collected (repetition time, TR=8400ms; echo time, TE=90ms; flip angle, FA=90; field of view, FOV=128x128mm; voxel size=2x2x2mm; matrix size=64x64; b-values of 0 and 1000 acquired; 64 diffusion directions).\n", - "\tOne run of diffusion-weighted (dMRI) data were collected (repetition time, TR=8400ms; echo time, TE=90ms; flip angle, FA=90; field of view, FOV=128x128mm; voxel size=2x2x2mm; matrix size=64x64; b-values of 0 and 1000 acquired; 64 diffusion directions).\n", - "\tOne run of diffusion-weighted (dMRI) data were collected (repetition time, TR=8400ms; echo time, TE=90ms; flip angle, FA=90; field of view, FOV=128x128mm; voxel size=2x2x2mm; matrix size=64x64; b-values of 0 and 1000 acquired; 64 diffusion directions).\n", "\tA field map (phase encoding: anterior to posterior; 256 slices; repetition time, TR=400ms; echo time 1 / 2, TE1/2=5190007.65ms; flip angle, FA=60.0; field of view, FOV=256x256mm; matrix size=256x256; voxel size=1x1x1mm) was acquired for the first and second runs of the N-Back BOLD scan.\n", "\tTwo runs of N-Back single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", "\tTwo runs of N-Back single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", @@ -137,12 +141,10 @@ "\tTwo runs of N-Back single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", "\tOne run of Rest single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", "\tOne run of Rest single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", - "\tIn session 02, MR data were acquired using a UNKNOWN-Tesla MANUFACTURER MODEL MRI scanner.\n", + "\tIn session 01, MR data were acquired using a UNKNOWN-Tesla MANUFACTURER MODEL MRI scanner.\n", "\tOne run of T1-weighted single-echo structural MRI data were collected (256 slices; repetition time, TR=2500ms; echo time, TE=2.9ms; flip angle, FA=8; field of view, FOV=256x256mm; matrix size=256x256; voxel size=1x1x1mm).\n", "\tOne run of T1-weighted single-echo structural MRI data were collected (256 slices; repetition time, TR=2500ms; echo time, TE=2.9ms; flip angle, FA=8; field of view, FOV=256x256mm; matrix size=256x256; voxel size=1x1x1mm).\n", "\tOne run of diffusion-weighted (dMRI) data were collected (repetition time, TR=8400ms; echo time, TE=90ms; flip angle, FA=90; field of view, FOV=128x128mm; voxel size=2x2x2mm; matrix size=64x64; b-values of 0 and 1000 acquired; 64 diffusion directions).\n", - "\tOne run of diffusion-weighted (dMRI) data were collected (repetition time, TR=8400ms; echo time, TE=90ms; flip angle, FA=90; field of view, FOV=128x128mm; voxel size=2x2x2mm; matrix size=64x64; b-values of 0 and 1000 acquired; 64 diffusion directions).\n", - "\tOne run of diffusion-weighted (dMRI) data were collected (repetition time, TR=8400ms; echo time, TE=90ms; flip angle, FA=90; field of view, FOV=128x128mm; voxel size=2x2x2mm; matrix size=64x64; b-values of 0 and 1000 acquired; 64 diffusion directions).\n", "\tA field map (phase encoding: anterior to posterior; 256 slices; repetition time, TR=400ms; echo time 1 / 2, TE1/2=5190007.65ms; flip angle, FA=60.0; field of view, FOV=256x256mm; matrix size=256x256; voxel size=1x1x1mm) was acquired for the first and second runs of the N-Back BOLD scan.\n", "\tTwo runs of N-Back single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", "\tTwo runs of N-Back single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", @@ -155,7 +157,7 @@ "\tOne run of Rest single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", "\tOne run of Rest single-echo fMRI data were collected (64 slices; repetition time, TR=2500ms; echo time, TE=30ms; flip angle, FA=UNKNOWN; field of view, FOV=128x128mm; matrix size=64x64; voxel size=2x2x2mm). Run duration was 2:40 minutes, during which 64 volumes were acquired.\n", "\n", - "Dicoms were converted to NIfTI-1 format. This section was (in part) generated automatically using pybids (0.13.2.post0.dev185).\n" + "Dicoms were converted to NIfTI-1 format. This section was (in part) generated automatically using pybids (0.14.0.post0.dev61).\n" ] } ], diff --git a/examples/statsmodels_tutorial.ipynb b/examples/statsmodels.ipynb similarity index 62% rename from examples/statsmodels_tutorial.ipynb rename to examples/statsmodels.ipynb index 694e22bb4..15ca6dd10 100644 --- a/examples/statsmodels_tutorial.ipynb +++ b/examples/statsmodels.ipynb @@ -4,10 +4,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## PyBIDS BIDS-StatsModels tutorial\n", + "# PyBIDS BIDS-StatsModels tutorial\n", "A minimalistic tutorial illustrating usage of the tools in the `bids.modeling` module—most notably, `BIDSStatsModelsGraph` and its various components." ] }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, { "cell_type": "code", "execution_count": 1, @@ -17,57 +27,192 @@ "%load_ext autoreload\n", "%autoreload 2\n", "\n", - "import pandas as pd\n", + "import json\n", + "\n", "import numpy as np\n", + "from os.path import join\n", + "import pandas as pd\n", + "\n", "from bids.modeling import BIDSStatsModelsGraph\n", "from bids.layout import BIDSLayout\n", - "from bids.tests import get_test_data_path\n", - "from os.path import join\n", - "import json" + "from bids.tests import get_test_data_path" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Load BIDSLayout\n", - "Standard stuff: load the `BIDSLayout` object (we'll use the ds005 dataset bundled with PyBIDS tests) and read in one of the included model files (`ds005/models/ds-005_type-test_model.json`)." + "## Load the layout and the BIDS model\n", + "\n", + "We load the `BIDSLayout` object (we'll use the ds005 dataset bundled with PyBIDS tests) and read in one of the included model files (`ds005/models/ds-005_type-test_model.json`)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, + "outputs": [], + "source": [ + "layout_path = join(get_test_data_path(), \"ds005\")\n", + "layout = BIDSLayout(layout_path)\n", + "json_file = join(layout_path, \"models\", \"ds-005_type-test_model.json\")\n", + "spec = json.load(open(json_file, \"r\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualize the content of the model." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, "outputs": [ { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "/Users/tal/Dropbox/Code/pybids/bids/layout/models.py:152: FutureWarning: The 'extension' entity currently excludes the leading dot ('.'). As of version 0.14.0, it will include the leading dot. To suppress this warning and include the leading dot, use `bids.config.set_option('extension_initial_dot', True)`.\n", - " FutureWarning)\n" + "{\n", + " \"Name\": \"test_model\",\n", + " \"Description\": \"simple test model\",\n", + " \"Nodes\": [\n", + " {\n", + " \"Name\": \"run\",\n", + " \"Level\": \"Run\",\n", + " \"GroupBy\": [\n", + " \"run\",\n", + " \"subject\"\n", + " ],\n", + " \"Model\": {\n", + " \"X\": [\n", + " \"RT\",\n", + " \"gain\"\n", + " ],\n", + " \"Formula\": \"0 + RT * gain\"\n", + " },\n", + " \"Transformations\": [\n", + " {\n", + " \"Name\": \"Factor\",\n", + " \"Input\": \"trial_type\"\n", + " },\n", + " {\n", + " \"Name\": \"Rename\",\n", + " \"Input\": \"trial_type.parametric gain\",\n", + " \"Output\": \"gain\"\n", + " },\n", + " {\n", + " \"Name\": \"Scale\",\n", + " \"Input\": \"RT\"\n", + " }\n", + " ],\n", + " \"DummyContrasts\": {\n", + " \"Test\": \"t\"\n", + " }\n", + " },\n", + " {\n", + " \"Name\": \"participant\",\n", + " \"Level\": \"Subject\",\n", + " \"GroupBy\": [\n", + " \"subject\",\n", + " \"contrast\"\n", + " ],\n", + " \"Model\": {\n", + " \"X\": [\n", + " 1\n", + " ]\n", + " },\n", + " \"Contrasts\": [\n", + " {\n", + " \"Name\": 1,\n", + " \"ConditionList\": [1],\n", + " \"Weights\": [1],\n", + " \"Test\": \"FEMA\"\n", + " }\n", + " ]\n", + " },\n", + " {\n", + " \"Name\": \"by-group\",\n", + " \"Level\": \"Dataset\",\n", + " \"GroupBy\": [\n", + " \"sex\"\n", + " ],\n", + " \"Model\": {\n", + " \"X\": [\n", + " 1\n", + " ]\n", + " },\n", + " \"DummyContrasts\": {\n", + " \"Conditions\": [1],\n", + " \"Test\": \"t\"\n", + " }\n", + " },\n", + " {\n", + " \"Name\": \"group-diff\",\n", + " \"Level\": \"Dataset\",\n", + " \"GroupBy\": [],\n", + " \"Model\": {\n", + " \"X\": [\n", + " 1,\n", + " \"sex\"\n", + " ]\n", + " },\n", + " \"DummyContrasts\": {\n", + " \"Test\": \"t\"\n", + " }\n", + " }\n", + " ],\n", + " \"Edges\": [\n", + " {\n", + " \"Source\": \"run\",\n", + " \"Destination\": \"participant\"\n", + " },\n", + " {\n", + " \"Source\": \"participant\",\n", + " \"Destination\": \"by-group\"\n", + " },\n", + " {\n", + " \"Source\": \"participant\",\n", + " \"Destination\": \"group-diff\"\n", + " }\n", + " ]\n", + "}\n" ] } ], "source": [ - "layout_path = join(get_test_data_path(), 'ds005')\n", - "layout = BIDSLayout(layout_path)\n", - "json_file = join(layout_path, 'models', 'ds-005_type-test_model.json')\n", - "spec = json.load(open(json_file, 'r'))" + "!cat ../bids/tests/data/ds005/models/ds-005_type-test_model.json" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [] + }, "source": [ - "### Initialize the graph\n", - "The `BIDSStatsModelsGraph` is the primary interface to design data, model constructions, etc. We build it from a `BIDSLayout` and the contents of a JSON model file." + "## Initialize the graph\n", + "\n", + "The `BIDSStatsModelsGraph` is the primary interface to design data, model constructions, etc. \n", + "\n", + "We build it from a `BIDSLayout` and the contents of a JSON model file." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/remi/github/pybids/bids/modeling/statsmodels.py:64: UserWarning: [Node run]:Transformations reformatted to {'transformer': 'pybids-transforms-v1', 'instructions': [{'name': 'Factor', 'input': 'trial_type'}, {'name': 'Rename', 'input': 'trial_type.parametric gain', 'output': 'gain'}, {'name': 'Scale', 'input': 'RT'}]}\n", + " warnings.warn(f\"[Node {node['name']}]:\"\n" + ] + } + ], "source": [ "graph = BIDSStatsModelsGraph(layout, spec)" ] @@ -76,8 +221,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Load variables from BIDS dataset\n", - "We will typically want to load variables into BIDS \"collections\" from the BIDS project. The `scan_length` argument is only necessary here because the test dataset doesn't actually include nifti image headers, so duration of scans can't be inferred. In typical use, you can call this without arguments." + "## Load variables from BIDS dataset\n", + "\n", + "We will typically want to load variables into BIDS \"collections\" from the BIDS project. \n", + "\n", + "The `scan_length` argument is only necessary here because the test dataset doesn't actually include nifti image headers, so duration of scans can't be inferred. \n", + "\n", + "In typical use, you can call this without arguments." ] }, { @@ -93,13 +243,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Access specific nodes\n", - "Now that the graph is loaded, we can start interacting with its nodes. We'll typically start with the root node, which will usually contain the run-level model information. We can either access the `.root_node`, or use `get_node()` to get the node by its unique name (defined in the JSON file)." + "## Access specific nodes\n", + "Now that the graph is loaded, we can start interacting with its nodes. \n", + "\n", + "We'll typically start with the root node, which will usually contain the run-level model information. \n", + "\n", + "We can either access the `.root_node`, or use `get_node()` to get the node by its unique name (defined in the JSON file)." ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -111,22 +265,33 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Executing a node\n", - "We can \"run\" each node to produce design matrices for each unique combination of entities/inputs we want. This is determined by the grouping structure. When working with the API directly, this is indicated via the `group_by` argument to a `.run()` method. In this case, we're indicating that the design information should be set up separately for every unique combination of `run` and `subject`.\n", + "## Executing a node\n", + "We can \"run\" each node to produce design matrices for each unique combination of entities/inputs we want.\n", + "\n", + "This is determined by the grouping structure.\n", + "\n", + "When working with the API directly, this is indicated via the `group_by` argument to a `.run()` method. \n", + "\n", + "In this case, we're indicating that the design information should be set up separately for every unique combination of `run` and `subject`.\n", "\n", - "Note that we need to include `subject` even though this is a strictly run-level model, because if we only pass `['run']`, there will only be 3 separate analyses conducted: one for run 1, one for run 2, and one for run 3. Whereas what we actually want is for the procedure to be done separately for each unique combination of the 3 runs and 16 subjects (i.e., 48 times)." + "Note that we need to include `subject` even though this is a strictly run-level model, because if we only pass `['run']`, there will only be 3 separate analyses conducted: \n", + "- one for run 1, \n", + "- one for run 2, \n", + "- and one for run 3. \n", + "\n", + "Whereas what we actually want is for the procedure to be done separately for each unique combination of the 3 runs and 16 subjects (i.e., 48 times)." ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "# force_dense controls whether the output for run-level design matrices\n", "# will be resampled to a uniform \"dense\" representation, or left alone\n", "# as a sparse representation if possible.\n", - "specs = root_node.run(group_by=['run', 'subject'], force_dense=False)" + "specs = root_node.run(group_by=[\"run\", \"subject\"], force_dense=False)" ] }, { @@ -140,12 +305,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The result is a list of objects of type `BIDSStatsModelsNodeOutput`. This is a lightweight container that stores design information and various other useful pieces of information. There should one element in the list for each unique combination of the grouping variables (in this case, run and subject):" + "The result is a list of objects of type `BIDSStatsModelsNodeOutput`. \n", + "\n", + "This is a lightweight container that stores design information and various other useful pieces of information. \n", + "\n", + "There should one element in the list for each unique combination of the grouping variables (in this case, run and subject):" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -154,7 +323,7 @@ "48" ] }, - "execution_count": 7, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -167,12 +336,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's take a closer look at the `BIDSStatsModelsNodeOutput`. First, we have an `.entities` attribute that tells us what levels of the grouping variables this output corresponds to:" + "Let's take a closer look at the `BIDSStatsModelsNodeOutput`. \n", + "\n", + "First, we have an `.entities` attribute that tells us what levels of the grouping variables this output corresponds to:" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -181,7 +352,7 @@ "{'run': 1, 'subject': '01'}" ] }, - "execution_count": 8, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -199,7 +370,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -317,7 +488,7 @@ "[86 rows x 3 columns]" ] }, - "execution_count": 9, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -330,23 +501,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Here we have a column for each of the contrasts specified in the model (with the same name as the contrast). We can access the contrasts too, via—you guessed it—`.contrasts`:" + "Here we have a column for each of the contrasts specified in the model (with the same name as the contrast). \n", + "\n", + "We can access the contrasts too, via — you guessed it — `.contrasts`:" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[ContrastInfo(name='RT', conditions=['RT'], weights=[1], type='t', entities={'run': 1, 'subject': '01', 'contrast': 'RT'}),\n", - " ContrastInfo(name='gain', conditions=['gain'], weights=[1], type='t', entities={'run': 1, 'subject': '01', 'contrast': 'gain'}),\n", - " ContrastInfo(name='RT:gain', conditions=['RT:gain'], weights=[1], type='t', entities={'run': 1, 'subject': '01', 'contrast': 'RT:gain'})]" + "[ContrastInfo(name='RT:gain', conditions=['RT:gain'], weights=[1], test='t', entities={'run': 1, 'subject': '01', 'contrast': 'RT:gain'}),\n", + " ContrastInfo(name='gain', conditions=['gain'], weights=[1], test='t', entities={'run': 1, 'subject': '01', 'contrast': 'gain'}),\n", + " ContrastInfo(name='RT', conditions=['RT'], weights=[1], test='t', entities={'run': 1, 'subject': '01', 'contrast': 'RT'})]" ] }, - "execution_count": 10, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -359,16 +532,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Each `ContrastInfo` is a named tuple with fields that map directly on the definition of contrasts in the BIDS-StatsModels specification. The only addition is the inclusion of an `.entities` field that stores a dictionary of the entities that identify what subset of our data the contrast applies to.\n", + "Each `ContrastInfo` is a named tuple with fields that map directly on the definition of contrasts in the BIDS-StatsModels specification. \n", + "\n", + "The only addition is the inclusion of an `.entities` field that stores a dictionary of the entities that identify what subset of our data the contrast applies to.\n", + "\n", + "One thing you might be puzzled by, looking at the output of the `.X` call above, is the absence of any timing information. \n", + "\n", + "`.X` is supposed to give us a design matrix, but how come the output only has the actual values for each column, and no information about event timing? How are we supposed to know what the onsets, durations, etc. of each event are?\n", + "\n", + "The answer is that `.X` contains *only* the actual values that go into the design matrix, and not any metadata—no matter how important. \n", "\n", - "One thing you might be puzzled by, looking at the output of the `.X` call above, is the absence of any timing information. `.X` is supposed to give us a design matrix, but how come the output only has the actual values for each column, and no information about event timing? How are we supposed to know what the onsets, durations, etc. of each event are?\n", + "Fortunately, that metadata is available to us. \n", "\n", - "The answer is that `.X` contains *only* the actual values that go into the design matrix, and not any metadata—no matter how important. Fortunately, that metadata is available to us. It's conveniently stored in a `.metadata` attribute on the `BIDSStatsModelsNodeOutput` object." + "It's conveniently stored in a `.metadata` attribute on the `BIDSStatsModelsNodeOutput` object." ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -534,7 +715,7 @@ "[86 rows x 7 columns]" ] }, - "execution_count": 11, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -547,7 +728,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There's a 1-to-1 mapping from rows in `.X` to rows in `.metadata`. This means you can, if you like, simply concatenate the two along the column axis to get one big DataFrame with everything. But by maintaining a default separation, it's made very clear to us which columns are properly a part of the design, and which contain additional metadata." + "There's a 1-to-1 mapping from rows in `.X` to rows in `.metadata`. \n", + "\n", + "This means you can, if you like, simply concatenate the two along the column axis to get one big DataFrame with everything. \n", + "\n", + "But by maintaining a default separation, it's made very clear to us which columns are properly a part of the design, and which contain additional metadata." ] }, { @@ -555,21 +740,29 @@ "metadata": {}, "source": [ "### Traversing the graph\n", - "So far we've executed the root node, which by definition required no inputs from any previous node. But in typical workflows, we'll be passing outputs from one node in as inputs to another. For example, we often want to take the run-level parameter estimates and pass them to a subject-level model that does nothing but average over runs within each subject. This requires us to somehow traverse the graph based on the edges specified in the BIDS-StatsModel document. We can do that by taking advantage of each node's `.children` attribute, which contains a list of `BIDSStatsModelsEdge` named tuples that specify an edge between two nodes." + "So far we've executed the root node, which by definition required no inputs from any previous node. \n", + "\n", + "But in typical workflows, we'll be passing outputs from one node in as inputs to another. \n", + "\n", + "For example, we often want to take the run-level parameter estimates and pass them to a subject-level model that does nothing but average over runs within each subject. \n", + "\n", + "This requires us to somehow traverse the graph based on the edges specified in the BIDS-StatsModel document. \n", + "\n", + "We can do that by taking advantage of each node's `.children` attribute, which contains a list of `BIDSStatsModelsEdge` named tuples that specify an edge between two nodes." ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[BIDSStatsModelsEdge(source=, destination=, group_by=['subject', 'contrast'])]" + "[BIDSStatsModelsEdge(source=, destination=, filter={})]" ] }, - "execution_count": 12, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -587,7 +780,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -596,7 +789,7 @@ "('subject', 'participant')" ] }, - "execution_count": 13, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -613,16 +806,21 @@ "We assign the first connected node to `next_node`, and print out its `level` and `name` for inspection (both are session).\n", "\n", "### Passing in inputs\n", - "Armed with that, we can run the session node and proceed and before. However, there's a twist: whereas the root node only needs to know about variables loaded directly from the `BIDSLayout` (which we achieved with that `.load_collections()` call earlier), the session node can't get the inputs it needs from the `BIDSLayout`, because there aren't any (at least in this particular dataset). What we want to do at the session level is average over our run-level estimates within-session. But to do that, we need to actually pass in information about those runs!\n", "\n", - "The way we do this is to pass, as the first argument to `.run()`, a list of `ContrastInfo` objects informing our node about what inputs it should use to construct its design matrices. The typical use pattern is to pass one concatenated list containing *all* of the outputs from the previous level that we want to pass on. Note that we may not want to pass *all* of the outputs forward. For example, suppose that 2 out of 48 run-level models failed during the estimation process. We might not want to keep passing information about those 2 runs forward, as we can't compute them. So we can always filter the list of `ContrastInfo` objects we received from the previous node before we pass them on to the next node. (We could also do other things, like rename each `ContrastInfo` to use whatever naming scheme our software prefers; modifying the entities; and so on. But we won't do any of that here.)\n", + "Armed with that, we can run the session node and proceed and before. \n", + "\n", + "However, there's a twist: whereas the root node only needs to know about variables loaded directly from the `BIDSLayout` (which we achieved with that `.load_collections()` call earlier), the session node can't get the inputs it needs from the `BIDSLayout`, because there aren't any (at least in this particular dataset). What we want to do at the session level is average over our run-level estimates within-session. But to do that, we need to actually pass in information about those runs!\n", + "\n", + "The way we do this is to pass, as the first argument to `.run()`, a list of `ContrastInfo` objects informing our node about what inputs it should use to construct its design matrices. \n", + "\n", + "The typical use pattern is to pass one concatenated list containing *all* of the outputs from the previous level that we want to pass on. Note that we may not want to pass *all* of the outputs forward. For example, suppose that 2 out of 48 run-level models failed during the estimation process. We might not want to keep passing information about those 2 runs forward, as we can't compute them. So we can always filter the list of `ContrastInfo` objects we received from the previous node before we pass them on to the next node. (We could also do other things, like rename each `ContrastInfo` to use whatever naming scheme our software prefers; modifying the entities; and so on. But we won't do any of that here.)\n", "\n", "Let's concatenate the 48 outputs we got from the previous level and drop the last 2, in preparation for passing them forward to our `next_node`:" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 32, "metadata": {}, "outputs": [ { @@ -631,13 +829,14 @@ "138" ] }, - "execution_count": 14, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from itertools import chain\n", + "\n", "contrasts = list(chain(*[s.contrasts for s in specs[:-2]]))\n", "len(contrasts)" ] @@ -653,7 +852,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 38, "metadata": {}, "outputs": [ { @@ -662,13 +861,13 @@ "48" ] }, - "execution_count": 15, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "sess_specs = next_node.run(contrasts, group_by=['subject', 'contrast'])\n", + "sess_specs = next_node.run(contrasts, group_by=[\"subject\", \"contrast\"])\n", "len(sess_specs)" ] }, @@ -683,16 +882,16 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[ContrastInfo(name='RT', conditions=['RT'], weights=[1], type='FEMA', entities={'contrast': 'RT', 'subject': '01'})]" + "[ContrastInfo(name='RT:gain', conditions=['RT:gain'], weights=[1], test='FEMA', entities={'contrast': 'RT:gain', 'subject': '01'})]" ] }, - "execution_count": 16, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -703,7 +902,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 35, "metadata": {}, "outputs": [ { @@ -727,7 +926,7 @@ " \n", " \n", " \n", - " RT\n", + " RT:gain\n", " contrast\n", " run\n", " subject\n", @@ -737,21 +936,21 @@ " \n", " 0\n", " 1\n", - " RT\n", + " RT:gain\n", " 1\n", " 01\n", " \n", " \n", " 1\n", " 1\n", - " RT\n", + " RT:gain\n", " 2\n", " 01\n", " \n", " \n", " 2\n", " 1\n", - " RT\n", + " RT:gain\n", " 3\n", " 01\n", " \n", @@ -760,13 +959,13 @@ "" ], "text/plain": [ - " RT contrast run subject\n", - "0 1 RT 1 01\n", - "1 1 RT 2 01\n", - "2 1 RT 3 01" + " RT:gain contrast run subject\n", + "0 1 RT:gain 1 01\n", + "1 1 RT:gain 2 01\n", + "2 1 RT:gain 3 01" ] }, - "execution_count": 17, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } @@ -802,7 +1001,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.9" + "version": "3.8.0" } }, "nbformat": 4, diff --git a/examples/validation.ipynb b/examples/validation.ipynb new file mode 100644 index 000000000..2274fa518 --- /dev/null +++ b/examples/validation.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "73a35393-3dac-4916-8d68-7c52fb181dca", + "metadata": {}, + "source": [ + "# BIDSValidator\n", + "\n", + "`pybids` implicitly imports a `BIDSValidator` class from the separate [bids-validator](https://github.com/bids-standard/bids-validator) package. \n", + "\n", + "You can use the `BIDSValidator` to determine whether a filepath is a valid BIDS filepath, as well as answering questions about what kind of data it represents. \n", + "\n", + "---\n", + "\n", + "**Note** \n", + "\n", + "This implementation of the BIDS validator is *NOT* necessarily up-to-date with the JavaScript version available online. \n", + "\n", + "Moreover, the Python validator only tests individual files, and is currently unable to validate entire BIDS datasets. \n", + "\n", + "For that, you should use the [online BIDS validator](https://bids-standard.github.io/bids-validator/).\n", + "\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2a6964bc-4a6c-4ba7-be48-5875138287e8", + "metadata": {}, + "outputs": [], + "source": [ + "# lint with black\n", + "%load_ext lab_black" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6a3e97b9-b371-4004-be63-392166e23135", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from bids import BIDSValidator\n", + "\n", + "# Note that when using the bids validator, the filepath MUST be relative to the top level bids directory\n", + "validator = BIDSValidator()\n", + "validator.is_bids(\"/sub-02/ses-01/anat/sub-02_ses-01_T2w.nii.gz\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2aa3f029-d165-447e-8824-08eb353cfaec", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Can decide if a filepath represents a file part of the specification\n", + "validator.is_file(\"/sub-02/ses-01/anat/sub-02_ses-01_T2w.json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "13bfc796-be8a-4b12-bde1-333f1bdd99cc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Can check if a file is at the top level of the dataset\n", + "validator.is_top_level(\"/dataset_description.json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8c9865b9-b281-4723-8879-5a8260bf7156", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# or subject (or session) level\n", + "validator.is_subject_level(\"/dataset_description.json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4af8ca80-610f-4cfc-ae1e-f394d1a3384e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "validator.is_session_level(\"/sub-02/ses-01/sub-02_ses-01_scans.json\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "42d03d45-b127-4a7a-bb7e-4497854557e5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Can decide if a filepath represents phenotypic data\n", + "validator.is_phenotypic(\"/sub-02/ses-01/anat/sub-02_ses-01_T2w.nii.gz\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}