Skip to content
Snippets Groups Projects
05_nifti.ipynb 3.89 KiB
Newer Older
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# NIfTI images and python\n",
    "\n",
    "The [nibabel](http://nipy.org/nibabel/) module is used to read and write NIfTI images and also some other medical imaging formats (e.g., ANALYZE, GIFTI, MINC, MGH).  This module is included within the FSL python environment.\n",
    "\n",
    "## Reading images\n",
    "\n",
    "It is easy to read an image:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import nibabel as nib\n",
    "filename = '/usr/local/fsl/data/standard/MNI152_T1_1mm.nii.gz'\n",
    "imobj = nib.load(filename, mmap=False)\n",
    "# display header object\n",
    "imhdr = imobj.header\n",
    "# extract data (as an numpy array)\n",
    "imdat = imobj.get_data().astype(float)\n",
    "print(imdat.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Make sure you use the full filename, including the .nii.gz extension.\n",
    "\n",
    "Reading the data off the disk is not done until `get_data()` is called.\n",
    "\n",
    "> Pitfall:\n",
    ">\n",
    "> The option `mmap=False`is necessary as turns off memory mapping, which otherwise would be invoked for uncompressed NIfTI files but not for compressed files. Since some functionality behaves differently on memory mapped objects, it is advisable to turn this off.\n",
    "\n",
    "Once the data is read into a numpy array then it is easily manipulated.\n",
    "\n",
    "> We recommend converting it to float at the start to avoid problems with integer arithmetic and overflow, though this is not compulsory.\n",
    "\n",
    "## Header info\n",
    "\n",
    "There are many methods available on the header object - for example, look at `dir(imhdr)` or `help(imhdr)` or the [nibabel webpage about NIfTI images](http://nipy.org/nibabel/nifti_images.html)\n",
    "\n",
    "### Voxel sizes\n",
    "\n",
    "Dimensions of the voxels, in mm, can be found from:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxsize = imhdr.get_zooms()\n",
    "print(voxsize)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Coordinate orientations and mappings\n",
    "\n",
    "Information about the NIfTI qform and sform matrices can be extracted like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sform = imhdr.get_sform()\n",
    "sformcode = imhdr['sform_code']\n",
    "qform = imhdr.get_qform()\n",
    "qformcode = imhdr['qform_code']\n",
    "print(qformcode)\n",
    "print(qform)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Writing images\n",
    "\n",
    "If you have created a modified image by making or modifying a numpy array then you need to put this into a NIfTI image object in order to save it to a file.  The easiest way to do this is to copy all the header info from an existing image like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "newdata = imdat * imdat\n",
    "newhdr = imhdr.copy()\n",
    "newobj = nib.nifti1.Nifti1Image(newdata, None, header=newhdr)\n",
    "nib.save(newobj, \"mynewname.nii.gz\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "where `newdata` is the numpy array (the above is a random example only) and `imhdr` is the existing image header (as above).\n",
    "\n",
    "If the dimensions of the image are different, then extra modifications will be required.  For this, or for making an image from scratch, see the [nibabel documentation](http://nipy.org/nibabel/nifti_images.html) on NIfTI images."
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}