diff --git a/advanced_programming/object_oriented_programming.ipynb b/advanced_programming/object_oriented_programming.ipynb index 464962c57eaaf5934d70391f5f13d21faad780c5..4f7818aa81728712a276ee7e783fc7264e053268 100644 --- a/advanced_programming/object_oriented_programming.ipynb +++ b/advanced_programming/object_oriented_programming.ipynb @@ -469,7 +469,7 @@ "\n", " def run(self, output=None):\n", "\n", - " data = np.array(self.img.get_data())\n", + " data = np.array(self.img.get_fdata())\n", "\n", " for oper, value in self.operations:\n", "\n", @@ -477,7 +477,7 @@ " # If not, we assume that\n", " # it is a scalar/numpy array.\n", " if isinstance(value, nib.nifti1.Nifti1Image):\n", - " value = value.get_data()\n", + " value = value.get_fdata()\n", "\n", " if oper == 'add':\n", " data = data + value\n", @@ -521,8 +521,8 @@ "\n", "outimg = fm.run()\n", "\n", - "norigvox = (inimg .get_data() > 0).sum()\n", - "nmaskvox = (outimg.get_data() > 0).sum()\n", + "norigvox = (inimg .get_fdata() > 0).sum()\n", + "nmaskvox = (outimg.get_fdata() > 0).sum()\n", "\n", "print(f'Number of voxels >0 in original image: {norigvox}')\n", "print(f'Number of voxels >0 in masked image: {nmaskvox}')" @@ -578,7 +578,7 @@ "\n", " def run(self, output=None):\n", "\n", - " data = np.array(self.img.get_data())\n", + " data = np.array(self.img.get_fdata())\n", "\n", " for oper, value in self.operations:\n", "\n", @@ -586,7 +586,7 @@ " # If not, we assume that\n", " # it is a scalar/numpy array.\n", " if isinstance(value, nib.nifti1.Nifti1Image):\n", - " value = value.get_data()\n", + " value = value.get_fdata()\n", "\n", " if oper == 'add':\n", " data = data + value\n", @@ -627,8 +627,8 @@ "\n", "outimg = FSLMaths(inimg).mul(mask).add(-10).run()\n", "\n", - "norigvox = (inimg .get_data() > 0).sum()\n", - "nmaskvox = (outimg.get_data() > 0).sum()\n", + "norigvox = (inimg .get_fdata() > 0).sum()\n", + "nmaskvox = (outimg.get_fdata() > 0).sum()\n", "\n", "print(f'Number of voxels >0 in original image: {norigvox}')\n", "print(f'Number of voxels >0 in masked image: {nmaskvox}')" @@ -1492,7 +1492,7 @@ "\n", " def run(self, output=None):\n", "\n", - " data = np.array(self.img.get_data())\n", + " data = np.array(self.img.get_fdata())\n", "\n", " for oper, value in self.operations:\n", "\n", @@ -1588,7 +1588,7 @@ "\n", " def run(self, output=None):\n", "\n", - " data = np.array(self.img.get_data())\n", + " data = np.array(self.img.get_fdata())\n", "\n", " for oper, value in self.operations:\n", " FSLMaths.opCounters[oper] = self.opCounters.get(oper, 0) + 1" diff --git a/advanced_programming/object_oriented_programming.md b/advanced_programming/object_oriented_programming.md index 32efe5bf13955eef978a2b9efb85b066ad28dbf8..2662490f44b1a0f3129bb0dc8ad3fddb8757afd1 100644 --- a/advanced_programming/object_oriented_programming.md +++ b/advanced_programming/object_oriented_programming.md @@ -378,7 +378,7 @@ class FSLMaths(object): def run(self, output=None): - data = np.array(self.img.get_data()) + data = np.array(self.img.get_fdata()) for oper, value in self.operations: @@ -386,7 +386,7 @@ class FSLMaths(object): # If not, we assume that # it is a scalar/numpy array. if isinstance(value, nib.nifti1.Nifti1Image): - value = value.get_data() + value = value.get_fdata() if oper == 'add': data = data + value @@ -422,8 +422,8 @@ fm.add(-10) outimg = fm.run() -norigvox = (inimg .get_data() > 0).sum() -nmaskvox = (outimg.get_data() > 0).sum() +norigvox = (inimg .get_fdata() > 0).sum() +nmaskvox = (outimg.get_fdata() > 0).sum() print(f'Number of voxels >0 in original image: {norigvox}') print(f'Number of voxels >0 in masked image: {nmaskvox}') @@ -470,7 +470,7 @@ class FSLMaths(object): def run(self, output=None): - data = np.array(self.img.get_data()) + data = np.array(self.img.get_fdata()) for oper, value in self.operations: @@ -478,7 +478,7 @@ class FSLMaths(object): # If not, we assume that # it is a scalar/numpy array. if isinstance(value, nib.nifti1.Nifti1Image): - value = value.get_data() + value = value.get_fdata() if oper == 'add': data = data + value @@ -511,8 +511,8 @@ mask = nib.load(fmask) outimg = FSLMaths(inimg).mul(mask).add(-10).run() -norigvox = (inimg .get_data() > 0).sum() -nmaskvox = (outimg.get_data() > 0).sum() +norigvox = (inimg .get_fdata() > 0).sum() +nmaskvox = (outimg.get_fdata() > 0).sum() print(f'Number of voxels >0 in original image: {norigvox}') print(f'Number of voxels >0 in masked image: {nmaskvox}') @@ -1213,7 +1213,7 @@ class FSLMaths(object): def run(self, output=None): - data = np.array(self.img.get_data()) + data = np.array(self.img.get_fdata()) for oper, value in self.operations: @@ -1294,7 +1294,7 @@ class FSLMaths(object): def run(self, output=None): - data = np.array(self.img.get_data()) + data = np.array(self.img.get_fdata()) for oper, value in self.operations: FSLMaths.opCounters[oper] = self.opCounters.get(oper, 0) + 1 diff --git a/applications/data_visualisation/fsleyes_render.md b/applications/data_visualisation/fsleyes_render.md index e8787558c1aed3f44fd1a9ca9ad04806dbf7d007..161c5f37a278b6f8dba3d68178dcd28a6ccb6acd 100644 --- a/applications/data_visualisation/fsleyes_render.md +++ b/applications/data_visualisation/fsleyes_render.md @@ -1,6 +1,6 @@ # Creating figures and movies with FSLeyes -You may be familiar with using FSLeyes for looking at your data. Perhaps you have taken screenshots and pasted those into a talk or a paper. Here we will learn how to script such things and ask FSLeyes to create complex figures directly from the command line. +You may be familiar with using FSLeyes for looking at your data. Perhaps you have taken screenshots and pasted those into a talk or a paper. Here we will learn how to script such things and ask FSLeyes to create complex figures directly from the command line. This has several advantages. For example, you can re-create the same or similar figures simply by editing the script, instead of re-doing all the FSLeyes tinkering. It is also useful if you need to create complex figures for many datasets/subjects. @@ -15,9 +15,9 @@ This has several advantages. For example, you can re-create the same or similar <a class="anchor" id="create-png"></a> ## Using fsleyes render -The first thing we will learn is how to generate a complex command line for FSLeyes. +The first thing we will learn is how to generate a complex command line for FSLeyes. -Everything you can set manually by clicking on the FSLeyes graphical interface can be reproduced through the command line. You can learn all about the command line arguments by reading the [documentation](https://open.win.ox.ac.uk/pages/fsl/fsleyes/fsleyes/userdoc/command_line.html) or looking at the FSLeyes full help (`fsleyes -fh`). +Everything you can set manually by clicking on the FSLeyes graphical interface can be reproduced through the command line. You can learn all about the command line arguments by reading the [documentation](https://open.win.ox.ac.uk/pages/fsl/fsleyes/fsleyes/userdoc/command_line.html) or looking at the FSLeyes full help (`fsleyes -fh`). Here we will instead cheat and use the lazy approach. We will first use the graphical interface to produce a nice looking image. Then we will generate a full command line in FSLeyes and use that as the basis for creating more similar figures. @@ -29,7 +29,7 @@ fsleyes -std1mm & ``` -Let's make this brain look funkier. Start by toggling off the sagittal and coronal views. We only want to see the axial view. +Let's make this brain look funkier. Start by toggling off the sagittal and coronal views. We only want to see the axial view. Next, toggle off the location cursor. You should now see this: @@ -42,18 +42,18 @@ Now change the colormap to "Cool" (of course), and open the Overlay display pane - Change the colourmap resolution from 256 to 7 - Change the Display range to min=1000 and max=8000 -Close the display panel and open the View settings (spanner below cogwheel), then change the background color to be white. +Close the display panel and open the View settings (spanner below cogwheel), then change the background color to be white. If you did the above you should now see: <img src="data/snapshot2.png" alt="snapshot2" style="width:400px;"/> -Now wouldn't it be nice if one could generate the same thing from scratch without going through the above steps by hand? Here is how you do it: +Now wouldn't it be nice if one could generate the same thing from scratch without going through the above steps by hand? Here is how you do it: **Settings -> Ortho View 1 -> Show command line for scene** -You can even click on copy to clipboard. Do that, then open a new text file (e.g. with emacs) and paste the result into the text file. The command you get looks very long so I am highlighting in <span style="color:blue">blue</span> the bit about the scene and in <span style="color:red">red</span> the bit about the overlay. +You can even click on copy to clipboard. Do that, then open a new text file (e.g. with emacs) and paste the result into the text file. The command you get looks very long so I am highlighting in <span style="color:blue">blue</span> the bit about the scene and in <span style="color:red">red</span> the bit about the overlay. ---- @@ -68,7 +68,7 @@ If you run it all in a Terminal it will open FSLeyes and set it up to look like Now as I said the command line is long and contains many things that are default behaviour anyway. So let's strip it down a little bit as it will make this document shorter. In the below, I am only keeping a subset of the options, but I did not add new ones: ```bash -fsleyes --scene ortho --hideLabels --layout horizontal --hidex --hidey --hideCursor --bgColour 1.0 1.0 1.0 --fgColour 0.0 0.0 0.0 /usr/local/fsl/data/standard/MNI152_T1_1mm.nii.gz --overlayType volume --cmap cool --displayRange 1000.0 8000.0 --cmapResolution 7 --interpolation spline +fsleyes --scene ortho --hideLabels --layout horizontal --hidex --hidey --hideCursor --bgColour 1.0 1.0 1.0 --fgColour 0.0 0.0 0.0 /usr/local/fsl/data/standard/MNI152_T1_1mm.nii.gz --overlayType volume --cmap cool --displayRange 1000.0 8000.0 --cmapResolution 7 --interpolation spline ``` @@ -79,7 +79,7 @@ fsleyes --scene ortho --hideLabels --layout horizontal --hidex --hidey --hideCur Instead of opening FSLeyes, we want to create an image (a PNG for example) to use in a presentation. This can be done very simply by using the above command and adding a render flag to fsleyes: ``` -fsleyes render -outputfile my_image.png <rest of the command> +fsleyes render -of my_image.png <rest of the command> ``` Run the above code (make sure you replace `<rest of the command>` with the rest of the FSLeyes command we created earlier). This should now output a PNG file. Have a look at it! @@ -98,7 +98,7 @@ First, make sure that you have ImageMagick installed. To do that, go to your ter We will re-use the previous render command. Start by copying that into a text editor. You can use the code below: ```bash -fsleyes render --outfile my_image.png --scene ortho --hideLabels --layout horizontal --hidex --hidey --hideCursor --bgColour 1.0 1.0 1.0 --fgColour 0.0 0.0 0.0 /usr/local/fsl/data/standard/MNI152_T1_1mm.nii.gz --overlayType volume --cmap cool --displayRange 1000.0 8000.0 --cmapResolution 7 --interpolation spline +fsleyes render --outfile my_image.png --scene ortho --hideLabels --layout horizontal --hidex --hidey --hideCursor --bgColour 1.0 1.0 1.0 --fgColour 0.0 0.0 0.0 /usr/local/fsl/data/standard/MNI152_T1_1mm.nii.gz --overlayType volume --cmap cool --displayRange 1000.0 8000.0 --cmapResolution 7 --interpolation spline ``` Now to change the z-location, we will use the `-voxelLoc` flag. We will also use a FOR loop to change the location, and store a different PNG at each step. Here is what the code will look like (copy it onto your text editor): @@ -111,7 +111,7 @@ mkdir -p my_folder for ((z=0;z<=181;z+=4));do zzz=`$FSLDIR/bin/zeropad $z 3` echo "Slice $zzz" - + out=my_folder/image_${zzz}.png fsleyes render --outfile $out --voxelLoc 91 109 $z $rest_of_command done @@ -119,7 +119,7 @@ done Examine the above script line by line. We first create a variable called `rest_of_command` containing all the extra stuff for display that does not change in the FOR loop. -We then use a FOR loop, where we go through every fourth z-slice (can you see that?). We create a variable called `zzz` inside the loop. This is to use for naming the output PNG files so that they are listed in the same order as the z-slices (e.g. instead of image_1.png we have image_001.png). +We then use a FOR loop, where we go through every fourth z-slice (can you see that?). We create a variable called `zzz` inside the loop. This is to use for naming the output PNG files so that they are listed in the same order as the z-slices (e.g. instead of image_1.png we have image_001.png). Run this script and you should see that many PNGs will get created, one per slice. @@ -129,7 +129,7 @@ Now to combine all these PNGs into a single GIF, run the below ImageMagick comma convert -delay 5 my_folder/image_???.png -loop 0 my_movie.gif ``` -Have a look at the GIF. On a mac you can simply use the space bar on your keyboard to preview the GIF. +Have a look at the GIF. On a mac you can simply use the space bar on your keyboard to preview the GIF. It is still missing the changing text. We will also use ImageMagick for this. Below is the same script as before but with the addition of a call to `convert` that adds the text: @@ -141,10 +141,10 @@ mkdir -p my_folder for ((z=0;z<=181;z+=4));do zzz=`$FSLDIR/bin/zeropad $z 3` echo "Slice $zzz" - + out=my_folder/image_${zzz}.png fsleyes render --outfile $out --voxelLoc 91 109 $z $rest_of_command - + # Bit that adds annotation to the image out_annot=my_folder/image_annot_${zzz}.png convert $out \ @@ -200,7 +200,7 @@ Ok I know that looks a little scary. Let's make the following changes. Open the - Change the colourmap to Yellow - Change the display range to min=1000, max=5000 -- Turn the brain upside down +- Turn the brain upside down - Add two clipping planes Copy the command line that creates this scene as we have done before (Settings->3D View 1->Show command line for scence). @@ -215,7 +215,7 @@ for ((angle1=0,angle2=180;angle1<=16;angle1++,angle2--));do echo $angle1 $angle2 fsleyes render --outfile $outputfolder/grot_`zeropad $angle1 3`.png [INSERT THE COMMAND HERE AND PUT IN $angle1 AND $angle2 WHERE YOU THINK THEY SHOULD GO ] - + done ``` @@ -236,7 +236,7 @@ You should be able to see this GIF: By now hopefully you have seen how you can combine the power of intuitively interacting with the FSLeyes graphical interface and the power of bash scripting. We'll do one more example of creating a nice graphic and then rendering it in a bash script. This one will look very nice. -Run the code below. It will open FSLeyes, with a 2mm MNI brain, and will also load the XTRACT tracts atlas. +Run the code below. It will open FSLeyes, with a 2mm MNI brain, and will also load the XTRACT tracts atlas. ```bash fsleyes -std $FSLDIR/data/atlases/XTRACT/xtract-tract-atlases-prob-1mm & @@ -258,7 +258,7 @@ Do the following: [This](data/tracts.txt) is what I got after doing the above (feel free to use that). -Now use FSleyes render to create a nice looking figure. We will also control the DPI (digits per inch) of this figure, as some journal publishers insist that you have good quality images. +Now use FSleyes render to create a nice looking figure. We will also control the DPI (digits per inch) of this figure, as some journal publishers insist that you have good quality images. ``` fsleyes render --outfile my_tract.png --size 800 600 <COPY REST OF THE COMMAND HERE> @@ -271,12 +271,12 @@ If you want to compare what you produced to what I made, have a look at [this](d ---- -Ok one last thing. Let's imagine that you want to check that your registration has worked properly and also wanted to make a PNG to show others that it does. +Ok one last thing. Let's imagine that you want to check that your registration has worked properly and also wanted to make a PNG to show others that it does. For this, we will need two images that have been aligned with each other. These two are included with the practical material: ``` -fsleyes data/example_func2highres.nii.gz data/highres.nii.gz & +fsleyes data/example_func2highres.nii.gz data/highres.nii.gz & ``` Then follow this recipe: diff --git a/applications/data_visualisation/matplotlib.ipynb b/applications/data_visualisation/matplotlib.ipynb index 1092f9bcf346f743c08a66a6d2d7f21577920cfa..9745aec50499c9dd44158a7aa8a73186b467ac84 100644 --- a/applications/data_visualisation/matplotlib.ipynb +++ b/applications/data_visualisation/matplotlib.ipynb @@ -331,7 +331,7 @@ "import nibabel as nib\n", "import os.path as op\n", "nim = nib.load(op.expandvars('${FSLDIR}/data/standard/MNI152_T1_1mm.nii.gz'), mmap=False)\n", - "imdat = nim.get_data().astype(float)\n", + "imdat = nim.get_fdata()\n", "imslc = imdat[:,:,70]\n", "plt.imshow(imslc, cmap=plt.cm.gray)\n", "plt.colorbar()\n", diff --git a/applications/data_visualisation/matplotlib.md b/applications/data_visualisation/matplotlib.md index 1035ae2b2ac8fa596a2764ad072d0237eb40b3e2..c8e6b82fe789600eea6904d69f2911689fc47b61 100644 --- a/applications/data_visualisation/matplotlib.md +++ b/applications/data_visualisation/matplotlib.md @@ -1,7 +1,7 @@ # Matplotlib tutorial -The main plotting library in python is `matplotlib`. -It provides a simple interface to just explore the data, +The main plotting library in python is `matplotlib`. +It provides a simple interface to just explore the data, while also having a lot of flexibility to create publication-worthy plots. In fact, the vast majority of python-produced plots in papers will be either produced directly using matplotlib or by one of the many plotting libraries built on top of @@ -9,7 +9,7 @@ matplotlib (such as [seaborn](https://seaborn.pydata.org/) or [nilearn](https:// Like everything in python, there is a lot of help available online (just google it or ask your local pythonista). A particularly useful resource for matplotlib is the [gallery](https://matplotlib.org/gallery/index.html). -Here you can find a wide range of plots. +Here you can find a wide range of plots. Just find one that looks like what you want to do and click on it to see (and copy) the code used to generate the plot. ## Contents @@ -113,7 +113,7 @@ plt.legend(loc='upper left') <a class="anchor" id="error"></a> ### Adding error bars -If your data is not completely perfect and has for some obscure reason some uncertainty associated with it, +If your data is not completely perfect and has for some obscure reason some uncertainty associated with it, you can plot these using `plt.error`: ``` x = np.arange(5) @@ -155,7 +155,7 @@ The main command for displaying images is `plt.imshow` (use `plt.pcolor` for cas import nibabel as nib import os.path as op nim = nib.load(op.expandvars('${FSLDIR}/data/standard/MNI152_T1_1mm.nii.gz'), mmap=False) -imdat = nim.get_data().astype(float) +imdat = nim.get_fdata() imslc = imdat[:,:,70] plt.imshow(imslc, cmap=plt.cm.gray) plt.colorbar() @@ -195,7 +195,7 @@ for more detail. <a class="anchor" id="OO"></a> ## Using the object-oriented interface -In the examples above we simply added multiple lines/points/bars/images +In the examples above we simply added multiple lines/points/bars/images (collectively called [artists](https://matplotlib.org/stable/tutorials/intermediate/artists.html) in matplotlib) to a single plot. To prettify this plots, we first need to know what all the features are called: @@ -234,13 +234,13 @@ Let's have a look at this line in more detail plt.getp(ax.lines[0]) ``` This shows us all the properties stored about this line, -including its coordinates in many different formats +including its coordinates in many different formats (`data`, `path`, `xdata`, `ydata`, or `xydata`), the line style and width (`linestyle`, `linewidth`), `color`, etc. <a class="anchor" id="subplots"></a> ## Multiple plots (i.e., subplots) -As stated one of the strengths of the object-oriented interface is that it is easier to work with multiple plots. +As stated one of the strengths of the object-oriented interface is that it is easier to work with multiple plots. While we could do this in the procedural interface: ``` plt.subplot(221) @@ -263,7 +263,7 @@ axes[0, 1].set_title("Upper right") axes[1, 0].set_title("Lower left") axes[1, 1].set_title("Lower right") ``` -Here we use `plt.subplots`, which creates both a new figure for us and a grid of sub-plots. +Here we use `plt.subplots`, which creates both a new figure for us and a grid of sub-plots. The returned `axes` object is in this case a 2x2 array of `Axes` objects, to which we set the title using the normal numpy indexing. > Seaborn is great for creating grids of closely related plots. Before you spent a lot of time implementing your own have a look if seaborn already has what you want on their [gallery](https://seaborn.pydata.org/examples/index.html) @@ -394,7 +394,7 @@ Add `plt.show()` to the end of your script (or save the figure to a file using ` <a class="anchor" id="backends"></a> ### Changing where the image appears: backends -Matplotlib works across a wide range of environments: Linux, Mac OS, Windows, in the browser, and more. +Matplotlib works across a wide range of environments: Linux, Mac OS, Windows, in the browser, and more. The exact detail of how to show you your plot will be different across all of these environments. This procedure used to translate your `Figure`/`Axes` objects into an actual visualisation is called the backend. @@ -412,5 +412,5 @@ In python scripts, this will give you a syntax error and you should instead use: import matplotlib matplotlib.use("MacOSX") ``` -Usually, the default backend will be fine, so you will not have to set it. -Note that setting it explicitly will make your script less portable. \ No newline at end of file +Usually, the default backend will be fine, so you will not have to set it. +Note that setting it explicitly will make your script less portable.