Uploading NIFTIs

Uploading NIFTIs

There are several mechanisms for uploading DICOM sessions into XNAT that are quite well documented (e.g. in the upload menu in your instance of XNAT or here) but there’s much less documentation available for uploading NIFTI images, though in research at least, NIFTIS are the norm.  So here are a few tips for uploading niftis to your DPUK imaging platform node.  I’ll start with manually uploading NIFTI files, which gives an idea of how xnat can handle non-dicom files and then talk about scripting file uploads which can be done at lowish level with the curl commandline program, or via the python scripting language.  My preferred method is to use python, but understanding the manual and commandline API are useful to understanding how to script uploads with python.

Manually

If you are just getting started and you only have one or two scans to upload, then there could be some paedagogic and/or pragmatic value to manually uploading the images with the “Manage Files” dialogue.

If you first create a subject and then add an “MR Session” experiment then you will see this form, where you can define the sequences (scans in XNAT language) that you wish to store for this scan (session in XNAT language)
Having created a session, you’ll need to use the Manage Files action to open this diaglogue and then first create a “NIFTI” folder for each sequence.
Having created the folders you will be able to use the “Upload Files” to add the nifti files appropriately.  You will be asked “Would you like the contents of this archive file to be extracted on the server? Press ‘OK’ to extract or ‘Cancel’ to proceed with upload without extracting.” You should click the incorrectly named cancel button to upload the .nii.gz file.

I’ve used XNAT 1.7 for the screenshots here as I find no differences between 1.6.5 and 1.7.x in this area and the DPUK imaging platform will be migrating to xnat 1.7 before too long.

Using Bash / Curl

For more than one or two scans, the manual method is time consuming and its more convenient to use the XNAT REST API which allows you automate the upload process.   One of the most direct ways of doing this is to use CURL on the linux/OSX commandline.

Following a similar pattern to the one we have used in the manual upload, we can upload NIFTI files in BASH with parameters, $url, $user, $pass, $project, $subject, $experiment, $scan and $filepath previously defined.  First we need to create the scan (which is xnat terminology for a sequence) if it doesnt already exist.

scan_exists=$(curl -silent -I -u $user:$pass $url/data/archive/projects/$project/subjects/$subject/experiments/$experiment/scans/$scan)
if [[ $scan_exists == HTTP/1.1\ 200* ]]; then
 echo "scan found: $scan"
else
 scan_created=$(curl -silent -X PUT -u $user:$pass $url/data/archive/projects/$project/subjects/$subject/experiments/$experiment/scans/$scan?xsiType=xnat\:mrScanData)
 echo "MR Scan created: $scan $scan_created"
fi

And then create the NIFTI folder for that scan:

resources=$(curl -sb -H -u $user:$pass $url/data/archive/projects/$project/subjects/$subject/experiments/$experiment/scans/$scan/resources?format=csv)
# create NIFTI resource type if not already present
if [[ $(echo "$resources" | grep "NIFTI" | wc -l) == 0 ]]; then
  curl -X PUT -u $user:$pass $url/data/archive/projects/$project/subjects/$subject/experiments/$experiment/scans/$scan/resources/NIFTI
  echo "NIFTI resource folder created for subject $subject, session $experiment, scan $scan"
fi

And finally upload a NIFTI file ($filepath has the full filepath of the NIFTI file):

filename=$(basename $filepath)
nifti_exists=$(curl -silent -I -u $user:$pass $url/data/archive/projects/$project/subjects/$subject/experiments/$experiment/scans/$scan/resources/NIFTI/files/$filename)
if [[ $nifti_exists == HTTP/1.1\ 200* ]]; then
  echo "Nifti file already exists: IGNORED"
else
  curl -u $user:$pass -X PUT --data-binary "@$filepath" "$url/data/archive/projects/$project/subjects/$subject/experiments/$experiment/scans/$scan/resources/NIFTI/files/$filename?format=NIFTI&inbody=true"
  echo "Nifti file uploaded: $filename"
fi

For DPUK users, there is a snippet (snippets are gitlab’s version of github’s gists) for uploading a nifti resource via bash and curl available on the developer portal at https://issues.dpuk.org/dpuk/node/snippets/1.

Using Python

You can use CURL directly, as shown above, but for the greater ease and flexibility pyxnat, a python wrapper for the xnat rest api comes in handy.  There is also a confusingly named python project, xnatpy, which in many ways is easier to use, but doesnt allow you to create subjects or sessions, which is why we’ve stuck with pyxnat here.

Shortcutting the same process as above, with variables of the same name, here’s how we can use pyxnat in python:

# This Python 2.7 file uses the following encoding: utf-8
import os
from pyxnat import Interface

url = "http://10.1.1.17"
user = "admin"
project = "test1"
subject = "sub001"
experiment = "sub001_MRI"
scan = "1"
filepath = "/data/T1.nii.gz"

# establish pyxnat session and connect to project
project = Interface(server=url, user=user, cachedir='/tmp').select.project(project)

# pyxnat will create the subject, experiment, scan and resource if they dont
# already exist (default types are fine in this case)
file = project.subject(subject).experiment(experiment).scan("1").resource("NIFTI").file(os.path.basename(filepath))
if not(file.exists()) and os.path.isfile(filepath):
    # Note that adding spaces for format and content and tags prevents "U U U" in the Manage Files modal.
    # FIXME: either use format, content and tags attributes or find a way not to have to add spaces
    file.put(filepath, format=" ", content=" ", tags=" ")

# set the scan type
project.subject(subject).experiment(experiment).scan(scan).attrs.set("type","T1")

In this example, I’ve shown a shortcut for creating the various objects in one call but I then have to label the scan in a separate instruction.  Alternatively,  I could have used a scan.create(details) instruction, though it would have less neat becuase I’d then have to create the resource in separate instruction. For DPUK users, there is an example script for uploading real data, the Cam-CAN niftis, using pyxnat available on the developer portal at https://issues.dpuk.org/dpuk/node/snippets/10.

Final words

Hopefully, there is enough here for you to get started.  Something to note is that unlike for DICOM sequences we wont get nice snaphot images generated for each sequence you upload with any of these methods as there isnt a default pipleline for doing this.  Finally, if you do upload NIFTI images to your project with one of these methods you should find that the data-freeze / sharing / requesting process works exactly as for dicom data on the DPUK imaging platform.