Package usage: radtools

Pamela Russell

2018-10-15

Overview

radtools provides utilities to explore images in the two leading medical image formats: DICOM and NIfTI. Where possible, generic functions seamlessly handle both formats. When necessary or useful, specialized functions are provided for a specific image format. This vignette demonstrates how to read image data into R, extract data and metadata, and view images.

Image file formats

DICOM

DICOM (Digital Imaging and Communication in Medicine) is a standard for management of medical images and image metadata. The DICOM standard specifies a file format definition. Each DICOM file includes image pixel data and embedded metadata. Our package assumes each DICOM file contains one two-dimensional image slice.

DICOM metadata is embedded in each file and allows image series to be reconstructed from multiple files via shared metadata identifying the patient, etc. DICOM files can be analyzed individually as single slices, or a directory containing an entire image series can be analyzed as one three-dimensional image.

NIfTI

NIfTI (Neuroimaging Informatics Technology Initiative) format is an adaptation of the previous ANALYZE format that solves several challenges with the older format. NIfTI images can be a single file containing the image and metadata (.nii) or pair of files storing the image and metadata separately (.hdr/.img), and can be compressed. Image data can have up to seven dimensions. The first three dimensions are reserved for spatial dimensions and the optional fourth dimension defines time points. Unlike DICOM format, the NIfTI format specifies a constant-size header with a fixed set of metadata attributes.

This article provides an excellent introduction to NIfTI-1 format.

Our package supports NIfTI-1 format. The recently developed NIfTI-2 is very similar to NIfTI-1, and permits storage of more datapoints in each dimension. NIfTI-2 is not bitwise compatible with NIfTI-1. We will add support for NIfTI-2 if demand exists. This article provides more background on the differences between NIfTI-1 and NIfTI-2.

Import the package

library(radtools)

Reading data from files

DICOM

The read_dicom function reads a DICOM dataset from a single file or a directory containing multiple slices. The returned value is a list with attributes hdr and img, each with an element for each slice of the image.

Read a single slice from one .dcm file:

Read a 3D image from a directory containing one .dcm file per slice:

NIfTI

NIfTI format uses one .nii file or two files (.hdr and .img) to capture an entire image series. The files can be gzipped or not.

The read_nifti1 function handles any of these cases, and returns a list containing one element of class nifti.

Read a 3D NIfTI image from .hdr and .img files:

Read a 4D NIfTI image from a .nii.gz file:

Extracting image metadata

Generic metadata functions

Get image dimensions or number of slices:

A typical DICOM dataset will only use a subset of the available metadata attributes, while NIfTI headers always include the same set of attributes. Get the actual metadata attributes for a dataset:

The header_value function returns the attribute value for a given header attribute. If the dataset is a DICOM dataset with multiple slices, it returns a vector of values across slices. NIfTI datasets do not have slice-specific metadata.

DICOM-specific metadata functions

Each DICOM file has its own header containing metadata for one slice.

Get the metadata for all slices as a matrix, where rows are attributes and columns are slices:

group element name code slice_1 slice_2
0002 0000 GroupLength UL 196 196
0002 0001 FileMetaInformationVersion OB  
0002 0002 MediaStorageSOPClassUID UI 1.2.840.10008.5.1.4.1.1.4 1.2.840.10008.5.1.4.1.1.4
0002 0003 MediaStorageSOPInstanceUID UI 1.3.6.1.4.1.14519.5.2.1.7307.2101.420604470287150790758949858236 1.3.6.1.4.1.14519.5.2.1.7307.2101.192741832082705219013781007567
0002 0010 TransferSyntaxUID UI 1.2.840.10008.1.2.1 1.2.840.10008.1.2.1
0002 0012 ImplementationClassUID UI 1.2.40.0.13.1.1.1 1.2.40.0.13.1.1.1
0002 0013 ImplementationVersionName SH dcm4che-1.4.31 dcm4che-1.4.31
0008 0005 SpecificCharacterSet CS ISO_IR 100 ISO_IR 100
0008 0008 ImageType CS ORIGINAL PRIMARY M NORM DIS2D ORIGINAL PRIMARY M NORM DIS2D
0008 0012 InstanceCreationDate DA 20030816 20030816

Many metadata attributes will be identical for all slices. Get a list of these contstant attributes and their values:

NIfTI-specific metadata functions

As NIfTI images can have more than three dimensions, a simple function returns the number of dimensions:

A function is provided to get all metadata attributes and values as a named list:

Extracting image data

The image itself can be extracted as a matrix of pixel intensities using a generic function:

mat_dicom_2d <- img_data_to_mat(dicom_data_2d)
dim(mat_dicom_2d)
#> [1] 384 384   1
mat_dicom_3d <- img_data_to_mat(dicom_data_3d)
dim(mat_dicom_3d)
#> [1] 384 384  19
mat_nifti_3d <- img_data_to_mat(nifti_data_3d)
dim(mat_nifti_3d)
#> [1]  91 109  91
mat_nifti_4d <- img_data_to_mat(nifti_data_4d)
dim(mat_nifti_4d)
#> [1]  64  64  21 180

For images with more than three dimensions (e.g. some NIfTI datasets), you can hold the additional dimensions constant and just get a 3D matrix by selecting a single coordinate for each dimension:

mat_nifti_4d_to_3d <- img_data_to_3D_mat(nifti_data_4d, coord_extra_dim = 90)
dim(mat_nifti_4d_to_3d)
#> [1] 64 64 21

Viewing images

The view_slice function is generic and works for DICOM or NIfTI data.

View a single-slice dataset:

view_slice(dicom_data_2d)

View one slice of a 3D image:

view_slice(dicom_data_3d, slice = 10)

view_slice(nifti_data_3d, slice = 20)

A function is also provided to view a slice of an intensity matrix instead of a DICOM or NIfTI data object. In particular, this is useful for viewing slices of NIfTI images with more than three dimensions. In that case, you can create a 3D matrix by holding extra dimensions constant using img_data_to_3D_mat, then pass that matrix to view_slice_mat.

view_slice_mat(mat_nifti_4d_to_3d, slice = 10)

Other functionality

Exploring the DICOM standard

Several functions are provided to explore aspects of the DICOM standard itself. These functions do not use or analyze any actual data.

Get the DICOM standard version reported here, the web URL describing the standard, and the time it was accessed during package development:

The DICOM standard specifies a tag, name, and keyword for each allowable metadata attribute. The following functions return complete lists of these attributes. These functions are self-contained and the orderings of the returned lists do not correspond.

Tags:

Names:

Keywords:

You can also search the DICOM standard for attribute names and keywords matching a given string.

dicom_search_header_names("manufacturer")
#>  [1] "Application Manufacturer"                          
#>  [2] "Application Setup Manufacturer"                    
#>  [3] "Component Manufacturer"                            
#>  [4] "Detector Manufacturer Name"                        
#>  [5] "Detector Manufacturer's Model Name"                
#>  [6] "Hardcopy Device Manufacturer"                      
#>  [7] "Hardcopy Device Manufacturer's Model Name"         
#>  [8] "Information From Manufacturer Sequence"            
#>  [9] "IOL Manufacturer"                                  
#> [10] "Manufacturer"                                      
#> [11] "Manufacturer's Model Name"                         
#> [12] "Manufacturer's Related Model Group"                
#> [13] "Modifying Device Manufacturer"                     
#> [14] "Notification From Manufacturer Sequence"           
#> [15] "Receive Coil Manufacturer Name"                    
#> [16] "Secondary Capture Device Manufacturer"             
#> [17] "Secondary Capture Device Manufacturer's Model Name"
#> [18] "Source Applicator Manufacturer"                    
#> [19] "Source Manufacturer"                               
#> [20] "Transmit Coil Manufacturer Name"                   
#> [21] "Wedge Manufacturer Name"
dicom_search_header_keywords("manufacturer")
#>  [1] "ApplicationManufacturer"                    
#>  [2] "ApplicationSetupManufacturer"               
#>  [3] "ComponentManufacturer"                      
#>  [4] "DetectorManufacturerModelName"              
#>  [5] "DetectorManufacturerName"                   
#>  [6] "HardcopyDeviceManufacturer"                 
#>  [7] "HardcopyDeviceManufacturerModelName"        
#>  [8] "InformationFromManufacturerSequence"        
#>  [9] "IOLManufacturer"                            
#> [10] "Manufacturer"                               
#> [11] "ManufacturerModelName"                      
#> [12] "ManufacturerRelatedModelGroup"              
#> [13] "ModifyingDeviceManufacturer"                
#> [14] "NotificationFromManufacturerSequence"       
#> [15] "ReceiveCoilManufacturerName"                
#> [16] "SecondaryCaptureDeviceManufacturer"         
#> [17] "SecondaryCaptureDeviceManufacturerModelName"
#> [18] "SourceApplicatorManufacturer"               
#> [19] "SourceManufacturer"                         
#> [20] "TransmitCoilManufacturerName"               
#> [21] "WedgeManufacturerName"

Session info

sessionInfo()
#> R version 3.4.3 (2017-11-30)
#> Platform: x86_64-apple-darwin15.6.0 (64-bit)
#> Running under: macOS High Sierra 10.13.6
#> 
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
#> 
#> locale:
#> [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] bindrcpp_0.2.2 radtools_1.0.0 knitr_1.20    
#> 
#> loaded via a namespace (and not attached):
#>  [1] tidyselect_0.2.4    purrr_0.2.5         splines_3.4.3      
#>  [4] lattice_0.20-35     colorspace_1.3-2    htmltools_0.3.6    
#>  [7] yaml_2.2.0          base64enc_0.1-3     survival_2.42-6    
#> [10] rlang_0.2.1         pillar_1.3.0        foreign_0.8-71     
#> [13] glue_1.3.0          RColorBrewer_1.1-2  bindr_0.1.1        
#> [16] plyr_1.8.4          stringr_1.3.1       munsell_0.5.0      
#> [19] gtable_0.2.0        RNifti_0.8.1        htmlwidgets_1.2    
#> [22] oro.dicom_0.5.0     evaluate_0.11       latticeExtra_0.6-28
#> [25] highr_0.7           htmlTable_1.12      Rcpp_0.12.18       
#> [28] acepack_1.4.1       scales_0.5.0        backports_1.1.2    
#> [31] checkmate_1.8.5     Hmisc_4.1-1         abind_1.4-5        
#> [34] gridExtra_2.3       ggplot2_3.0.0       digest_0.6.15      
#> [37] stringi_1.2.4       dplyr_0.7.6         grid_3.4.3         
#> [40] rprojroot_1.3-2     tools_3.4.3         bitops_1.0-6       
#> [43] magrittr_1.5        lazyeval_0.2.1      tibble_1.4.2       
#> [46] Formula_1.2-3       cluster_2.0.7-1     crayon_1.3.4       
#> [49] pkgconfig_2.0.1     Matrix_1.2-14       data.table_1.11.4  
#> [52] oro.nifti_0.9.1     assertthat_0.2.0    rmarkdown_1.10     
#> [55] rstudioapi_0.7      R6_2.2.2            rpart_4.1-13       
#> [58] nnet_7.3-12         compiler_3.4.3