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.
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.
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.
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.
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.