diff --git a/notebooks/basic_data_input_bids.ipynb b/notebooks/basic_data_input_bids.ipynb old mode 100644 new mode 100755 index 215ae23..b6e4d67 --- a/notebooks/basic_data_input_bids.ipynb +++ b/notebooks/basic_data_input_bids.ipynb @@ -2,7 +2,10 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "## Data input for BIDS datasets\n", "`DataGrabber` and `SelectFiles` are great if you are dealing with generic datasets with arbitrary organization. However, if you have decided to use Brain Imaging Data Structure (BIDS) to organize your data (or got your hands on a BIDS dataset) you can take advantage of a formal structure BIDS imposes. In this short tutorial, you will learn how to do this." @@ -10,7 +13,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "## `pybids` - a Python API for working with BIDS datasets\n", "`pybids` is a lightweight python API for querying BIDS folder structure for specific files and metadata. You can install it from PyPi:\n", @@ -22,7 +28,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "## The `layout` object and simple queries\n", "To begin working with pybids we need to initialize a layout object. We will need it to do all of our queries" @@ -31,7 +40,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "from bids.layout import BIDSLayout\n", @@ -41,7 +54,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "!tree -L 4 /data/ds000114/" @@ -49,7 +66,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "Let's figure out what are the subject labels in this dataset" ] @@ -57,7 +77,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get_subjects()" @@ -65,7 +89,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "What modalities are included in this dataset?" ] @@ -73,7 +100,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get_modalities()" @@ -81,7 +112,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "Which different data types are included in this dataset?" ] @@ -89,7 +123,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get_types(modality='func')" @@ -97,7 +135,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "What are the different tasks included in this dataset?" ] @@ -105,7 +146,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get_tasks()" @@ -113,7 +158,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "We can also ask for all of the data for a particular subject and one modality." ] @@ -121,7 +169,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get(subject='01', modality=\"anat\", session=\"test\")" @@ -129,7 +181,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "We can also ask for a specific subset of data. Note that we are using extension filter to get just the imaging data (BIDS allows both .nii and .nii.gz so we need to include both)." ] @@ -137,7 +192,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get(subject='01', type='bold', extensions=['nii', 'nii.gz'])" @@ -145,7 +204,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "You probably noticed that this method does not only return the file paths, but objects with relevant query fields. We can easily extract just the file paths." ] @@ -153,7 +215,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get(subject='01', type='bold', extensions=['nii', 'nii.gz'], return_type='file')" @@ -161,7 +227,10 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Exercise 1:\n", "List all files for the \"linebisection\" task for subject 02." @@ -171,7 +240,10 @@ "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden", + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown", "solution2_first": true }, "outputs": [], @@ -183,7 +255,10 @@ "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden" + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown" }, "outputs": [], "source": [ @@ -195,89 +270,105 @@ }, { "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Including `pybids` in your `nipype` workflow\n", - "This is great, but what we really want is to include this into our `nipype` workflows. How to do this? We can create our own custom `BIDSDataGrabber` using a `Function` Interface. First, we need a plain Python function that for a given subject label and dataset location will return a list of BOLD files." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "deletable": true, + "editable": true + }, "source": [ - "def get_niftis(subject_id, data_dir):\n", - " # Remember that all the necessary imports need to be INSIDE the function for the Function Interface to work!\n", - " from bids.layout import BIDSLayout\n", - " \n", - " layout = BIDSLayout(data_dir)\n", - " \n", - " bolds = layout.get(subject=subject_id, type=\"bold\", return_type='file', extensions=['nii', 'nii.gz'])\n", - " \n", - " return bolds" + "## `BIDSDataGrabber`: Including `pybids` in your `nipype` workflow\n", + "This is great, but what we really want is to include this into our nipype workflows. To do this, we can import `BIDSDataGrabber`, which provides an `Interface` for `BIDSLayout.get`" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ - "get_niftis('01', '/data/ds000114')" + "from nipype.interfaces.io import BIDSDataGrabber\n", + "from nipype.pipeline import Node, MapNode, Workflow\n", + "from nipype.interfaces.utility import Function\n", + "\n", + "bg = Node(BIDSDataGrabber(), name='bids-grabber')\n", + "bg.inputs.base_dir = '/data/ds000114'" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ - "Ok we got our function. Now we need to wrap it inside a Node object." + "You can define static filters, that will apply to all queries, by modifying the appropriate input" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ - "from nipype.pipeline import Node, MapNode, Workflow\n", - "from nipype.interfaces.utility import IdentityInterface, Function" + "bg.inputs.subject = '01'\n", + "res = bg.run()\n", + "res.outputs" ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, "source": [ - "BIDSDataGrabber = Node(Function(function=get_niftis, input_names=[\"subject_id\",\n", - " \"data_dir\"],\n", - " output_names=[\"bolds\"]), name=\"BIDSDataGrabber\")\n", - "BIDSDataGrabber.inputs.data_dir = \"/data/ds000114\"" + "Note that by default `BIDSDataGrabber` will fetch `nifti` files matching modality `func` and `anat`, and output them as two output fields. \n", + "\n", + "To define custom fields, simply define the arguments to pass to `BIDSLayout.get` as dictionary, like so:" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ - "BIDSDataGrabber.inputs.subject_id='01'\n", - "res = BIDSDataGrabber.run()\n", + "bg.inputs.output_query = {'bolds': dict(type='bold')}\n", + "res = bg.run()\n", "res.outputs" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ - "Works like a charm! (hopefully :) Lets put it in a workflow. We are not going to analyze any data, but for demonstration purposes, we will add a couple of nodes that pretend to analyze their inputs" + "This results in a single output field `bold`, which returns all files with `type:bold` for `subject:\"01\"` \n", + "\n", + "Now, lets put it in a workflow. We are not going to analyze any data, but for demonstration purposes, we will add a couple of nodes that pretend to analyze their inputs" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "def printMe(paths):\n", @@ -290,17 +381,24 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "wf = Workflow(name=\"bids_demo\")\n", - "wf.connect(BIDSDataGrabber, \"bolds\", analyzeBOLD, \"paths\")\n", + "wf.connect(bg, \"bolds\", analyzeBOLD, \"paths\")\n", "wf.run()" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Exercise 2:\n", "Modify the `BIDSDataGrabber` and the workflow to collect T1ws images for subject `10`." @@ -310,7 +408,10 @@ "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden", + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown", "solution2_first": true }, "outputs": [], @@ -322,54 +423,61 @@ "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden" + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown" }, "outputs": [], "source": [ "from nipype.pipeline import Node, MapNode, Workflow\n", - "from nipype.interfaces.utility import IdentityInterface, Function\n", - "\n", - "def get_T1w(subject_id, data_dir):\n", - " from bids.layout import BIDSLayout\n", - " \n", - " layout = BIDSLayout(data_dir)\n", - " \n", - " T1w = layout.get(subject=subject_id, modality=\"anat\", return_type='file')\n", - " \n", - " return T1w\n", + "from nipype.interfaces.io import BIDSDataGrabber\n", "\n", - "ex2_BIDSDataGrabber = Node(Function(function=get_T1w, \n", - " input_names=[\"subject_id\", \"data_dir\"],\n", - " output_names=[\"T1w\"]), \n", - " name=\"ex2\")\n", - "ex2_BIDSDataGrabber.inputs.data_dir = \"/data/ds000114\"\n", + "ex2_BIDSDataGrabber = BIDSDataGrabber()\n", + "ex2_BIDSDataGrabber.inputs.base_dir = '/data/ds000114'\n", + "ex2_BIDSDataGrabber.inputs.subject = '10'\n", + "ex2_BIDSDataGrabber.inputs.output_query = {'T1w': dict(modality='anat')}\n", "\n", - "ex2_BIDSDataGrabber.inputs.subject_id='10'\n", "ex2_res = ex2_BIDSDataGrabber.run()\n", "ex2_res.outputs" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "## Iterating over subject labels\n", - "In the previous example, we demonstrated how to use `pybids` to \"analyze\" one subject. How can we scale it for all subjects? Easy - using `iterables` (more in [Iteration/Iterables](basic_iteration.ipynb)." + "In the previous example, we demonstrated how to use `pybids` to \"analyze\" one subject. How can we scale it for all subjects? Easy - using `iterables` (more in [Iteration/Iterables](basic_iteration.ipynb))." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ - "BIDSDataGrabber.iterables = ('subject_id', layout.get_subjects()[:2])\n", + "bg_all = Node(BIDSDataGrabber(), name='bids-grabber')\n", + "bg_all.inputs.base_dir = '/data/ds000114'\n", + "bg_all.inputs.output_query = {'bolds': dict(type='bold')}\n", + "bg_all.iterables = ('subject', layout.get_subjects()[:2])\n", + "wf = Workflow(name=\"bids_demo\")\n", + "wf.connect(bg_all, \"bolds\", analyzeBOLD, \"paths\")\n", "wf.run()" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "## Accessing additional metadata\n", "Querying different files is nice, but sometimes you want to access more metadata. For example `RepetitionTime`. `pybids` can help with that as well" @@ -378,7 +486,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "layout.get_metadata('/data/ds000114/sub-01/ses-test/func/sub-01_ses-test_task-fingerfootlips_bold.nii.gz')" @@ -386,16 +498,23 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ - "Can we incorporate this into our pipeline? Yes, we can!\n", + "Can we incorporate this into our pipeline? Yes, we can! To do so, let's use a `Function` node to use `BIDSLayout` in a custom way.\n", "(More about MapNode in [MapNode](basic_mapnodes.ipynb))" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, "outputs": [], "source": [ "def printMetadata(path, data_dir):\n", @@ -411,17 +530,25 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true, + "scrolled": false + }, "outputs": [], "source": [ "wf = Workflow(name=\"bids_demo\")\n", - "wf.connect(BIDSDataGrabber, \"bolds\", analyzeBOLD2, \"path\")\n", + "wf.connect(bg, \"bolds\", analyzeBOLD2, \"path\")\n", "wf.run()" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "### Exercise 3:\n", "Modify the `printMetadata` function to also print `EchoTime` " @@ -431,7 +558,10 @@ "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden", + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown", "solution2_first": true }, "outputs": [], @@ -443,39 +573,30 @@ "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden" + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown" }, "outputs": [], "source": [ "from nipype.pipeline import Node, MapNode, Workflow\n", - "from nipype.interfaces.utility import IdentityInterface, Function\n", - "\n", - "# let's start from BidsDataGrabber again\n", - "def get_niftis(subject_id, data_dir):\n", - " # Remember that all the necesary imports need to be INSIDE the function \n", - " # for the Function Interface to work!\n", - " from bids.layout import BIDSLayout\n", - " \n", - " layout = BIDSLayout(data_dir)\n", - " \n", - " bolds = layout.get(subject=subject_id, type=\"bold\", return_type='file', extensions=['nii', 'nii.gz'])\n", - " \n", - " return bolds\n", - "\n", + "from nipype.interfaces.io import BIDSDataGrabber\n", "\n", - "ex3_BIDSDataGrabber = Node(Function(function=get_niftis, \n", - " input_names=[\"subject_id\", \"data_dir\"],\n", - " output_names=[\"bolds\"]), \n", - " name=\"ex3_BIDSDataGrabber\")\n", - "ex3_BIDSDataGrabber.inputs.data_dir = \"/data/ds000114\"\n", - "ex3_BIDSDataGrabber.inputs.subject_id='01'" + "ex3_BIDSDataGrabber = Node(BIDSDataGrabber(), name='bids-grabber')\n", + "ex3_BIDSDataGrabber.inputs.base_dir = '/data/ds000114'\n", + "ex3_BIDSDataGrabber.inputs.subject = '01'\n", + "ex3_BIDSDataGrabber.inputs.output_query = {'bolds': dict(type='bold')}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "solution2": "hidden" + "collapsed": true, + "deletable": true, + "editable": true, + "solution2": "shown" }, "outputs": [], "source": [ @@ -516,7 +637,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.6" } }, "nbformat": 4,