Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No output and no error #341

Closed
muschellij2 opened this issue Sep 26, 2019 · 9 comments
Closed

No output and no error #341

muschellij2 opened this issue Sep 26, 2019 · 9 comments

Comments

@muschellij2
Copy link
Contributor

This may be related to https://www.nitrc.org/forum/forum.php?set=custom&forum_id=4442&style=nested&max_rows=50. This data is from
https://www.kaggle.com/c/rsna-intracranial-hemorrhage-detection/data (can be used for research purposes). Therefore, it's been heavily processed removing DICOM header fields.

The files attached are:

  • no_instance_48.zip - the 42 slices that had the same PatientID, StudyInstanceUID, and SeriesInstanceUID fields with no instance number
  • no_instance_32.zip - the 32 "unique" slices with no instance number
  • added_instance_32.zip - I added a InstanceNumber using dcmodify to try to convert

The Issue

I had seen

No nifti file is output, even though no errors are given if using the releases:

Chris Rorden's dcm2niiX version v1.0.20190902  (JP2:OpenJPEG) (JP-LS:CharLS) GCC5.5.0 (64-bit Linux)
Found 32 DICOM file(s)
Warning: Empty protocol name(s) (0018,1030)
Warning: Unable to determine manufacturer (0008,0070), so conversion is not tuned for vendor.
Warning: Unable to append protocol name (0018,1030) to filename (it is empty).
wget https://github.com/rordenlab/dcm2niix/releases/download/v1.0.20190902/dcm2niix_mac.zip -O dcm2nii.zip
unzip -j dcm2nii.zip

wget https://github.com/rordenlab/dcm2niix/files/3658961/no_instance_48.zip -O tmp.zip
unzip -j tmp.zip
rm tmp.zip
./dcm2niix -f %p_%t_%s ./ 
ls *.nii*
rm -f *.dcm *.json *.nii*

wget https://github.com/rordenlab/dcm2niix/files/3658961/no_instance_32.zip -O tmp.zip
unzip -j tmp.zip
rm tmp.zip
./dcm2niix ./ -f %p_%t_%s
  ls *.nii*
  rm -f *.dcm *.json *.nii*
  
wget https://github.com/rordenlab/dcm2niix/files/3658961/added_instance_32.zip -O tmp.zip
unzip -j tmp.zip
rm tmp.zip
./dcm2niix ./ -f %p_%t_%s
ls *.nii*
rm -f *.dcm *.json *.nii*
@neurolabusc
Copy link
Collaborator

Your lines
./dcm2niix ./ -f %p_%t_%s
should read
./dcm2niix -f %p_%t_%s ./
With this change, the conversion proceeds as well as can be expected given the inputs.

The last argument is always the input folder. While this might seem an unusual convention, it allows drag-and-drop conversion for Windows users.

As an aside, I am shocked that these images were downloaded from the RSNA web site. These are not valid DICOM datasets. The type 1 (required) tags StudyInstanceUID (0020,000d) and SeriesInstanceUID (0020,000E) are invalid. They are required to be a combination of only numeric characters and the period (i.e. the Character Repertoire for elements with the VR of "UI" must be in the range "0"-"9", "."). So tags like the ones below are not acceptable:

(0020,000d) UI [ID_b971875df5]                          #  14, 1 StudyInstanceUID
(0020,000e) UI [ID_237f8c4996]                          #  14, 1 SeriesInstanceUID

@muschellij2
Copy link
Contributor Author

muschellij2 commented Sep 26, 2019 via email

@neurolabusc
Copy link
Collaborator

This reflects a limitation with the input files not dcm2niix. Each input image has a DICOM-like header, but taken together the headers from different files conflict with each other. A tool like dcm2niix attempts to parse the meaning of a collection of DICOM files in the same way we parse a series of words together to comprehend sentences. Taken together, these files are like a random jumble of words that have no coherent meaning.

I think this dataset was designed to people could use a simple DICOM header reader written in their favorite language and use it to read each image independently. If you want to use dcm2niix, you must force it to read each single file in isolation (-s y) rather than reading them as a coherent collection of files. The Linux script would be something like:

for i in *.dcm
do
  dcm2niix -b n -s y -f %b -o ~/out "$i"
done

@muschellij2
Copy link
Contributor Author

muschellij2 commented Sep 27, 2019 via email

@muschellij2
Copy link
Contributor Author

OK - I think I have a finally reproducible example: Here is the data: data.zip

Load up Packages

library(dcm2niir)
library(dcmtk)
library(readr)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)
library(neurobase)
#> Loading required package: oro.nifti
#> oro.nifti 0.10.1
#> 
#> Attaching package: 'oro.nifti'
#> The following object is masked from 'package:dplyr':
#> 
#>     slice
#> Registered S3 method overwritten by 'R.oo':
#>   method        from       
#>   throw.default R.methodsS3

Download the data

url = "https://github.com/rordenlab/dcm2niix/files/3663869/data.zip"
destfile = tempfile(fileext = ".zip")
download.file(url, destfile)

Version of dcm2niix is the most up to date GitHub built from source

dcm2nii_version()
#> [1] "Chris Rorden's dcm2niiX version v1.0.20190902  Clang10.0.1 (64-bit MacOS)"
# install_dcm2nii(from_source = TRUE, overwrite = TRUE)

Here we are unzipping the data to a temporary file

exdir = tempfile()
dir.create(exdir)
unzip(destfile, exdir = exdir)
paths = list.files(pattern = ".dcm", path = exdir, full.names = TRUE)

Here is the header information:

# showing the image position patient
hdr = read_dicom_header(path = exdir, recursive = TRUE)
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename --recurse --scan-directories '/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file1285278f1db17' --scan-pattern  *.dcm
wide = wide_hdr(hdr)

sort(unique(hdr$name))
#>  [1] "BitsAllocated"                  "BitsStored"                    
#>  [3] "Columns"                        "FileMetaInformationGroupLength"
#>  [5] "FileMetaInformationVersion"     "HighBit"                       
#>  [7] "ImageOrientationPatient"        "ImagePositionPatient"          
#>  [9] "ImplementationClassUID"         "ImplementationVersionName"     
#> [11] "MediaStorageSOPClassUID"        "MediaStorageSOPInstanceUID"    
#> [13] "Modality"                       "PatientID"                     
#> [15] "PhotometricInterpretation"      "PixelData"                     
#> [17] "PixelRepresentation"            "PixelSpacing"                  
#> [19] "RescaleIntercept"               "RescaleSlope"                  
#> [21] "Rows"                           "SamplesPerPixel"               
#> [23] "SeriesInstanceUID"              "SOPInstanceUID"                
#> [25] "StudyID"                        "StudyInstanceUID"              
#> [27] "TransferSyntaxUID"              "WindowCenter"                  
#> [29] "WindowWidth"

DICOM Headers are missing

# no gantry tilt DICOM header!
any(grepl("ilt", tolower(hdr$name)))
#> [1] FALSE
any(grepl("instancenum", tolower(hdr$name)))
#> [1] FALSE

sub_bracket = function(x) {
  x = sub("^\\[", "", x)
  x = sub("\\]$", "", x)
  x = trimws(x)
}
parse_number_no_na = function(x) {
  x[ x %in% c("-", "-", "N/A")] = NA
  na_x = is.na(x)
  x = readr::parse_number(x, na = "")
  bad = is.na(x) & !na_x 
  stopifnot(!any(bad))
  x
}

wide = wide %>% 
  mutate(ipp = sub_bracket(gsub("\\\\", ",", ImagePositionPatient))) %>% 
  tidyr::separate(ipp, into = c("x", "y", "z"), remove = FALSE, sep = ",") %>% 
  mutate_at(vars(x, y, z), parse_number_no_na)

# order by z
wide = wide %>% 
  select(file, x, y, z, ipp) %>% 
  arrange(z)

Showing the image position patients (ordered for instance number later)

wide %>% 
  mutate(file = basename(file)) %>% 
  select(file, x, y, z) %>% 
  as.data.frame
#>                file         x            y         z
#> 1  ID_12a0d6d34.dcm -82.00099 -39.17097000  95.26095
#> 2  ID_12e3b6923.dcm -82.00099 -37.66793000 100.02969
#> 3  ID_6b15a7649.dcm -82.00099 -36.16490000 104.79843
#> 4  ID_7c08b7fb7.dcm -82.00099 -34.66185762 109.56717
#> 5  ID_6cb797177.dcm -82.00099 -33.15882000 114.33591
#> 6  ID_bb2a4a01c.dcm -82.00099 -31.65578000 119.10465
#> 7  ID_6dcedd2e1.dcm -82.00099 -30.15274000 123.87339
#> 8  ID_b494c2115.dcm -82.00099 -28.64971000 128.64213
#> 9  ID_ae7b11865.dcm -82.00099 -27.14667000 133.41087
#> 10 ID_21053fe7e.dcm -82.00099 -25.64363056 138.17961
#> 11 ID_f4891876d.dcm -82.00099 -24.14059000 142.94835
#> 12 ID_18aac96c0.dcm -82.00099 -22.63755000 147.71709
#> 13 ID_8a35660d5.dcm -82.00099 -21.13452000 152.48583
#> 14 ID_d4ea87a35.dcm -82.00099 -19.63148000 157.25457
#> 15 ID_0b0e59911.dcm -82.00099 -18.12844000 162.02331
#> 16 ID_97e5a203e.dcm -82.00099 -16.62540350 166.79205
#> 17 ID_ac39010dc.dcm -82.00099 -15.12237000 171.56079
#> 18 ID_4f0317d23.dcm -82.00099 -13.61933000 176.32953
#> 19 ID_362423b57.dcm -82.00099 -12.11629000 181.09826
#> 20 ID_dd3b5bf4e.dcm -82.00099 -10.61325000 185.86700
#> 21 ID_8f5d4b696.dcm -82.00099  -9.11021400 190.63574
#> 22 ID_66accd2e4.dcm -82.00099  -7.60717600 195.40448
#> 23 ID_17103c79e.dcm -82.00099  -6.10413900 200.17322
#> 24 ID_9a3bba619.dcm -82.00099  -4.60110100 204.94196
#> 25 ID_8d0ca7742.dcm -82.00099  -3.09806300 209.71070
#> 26 ID_c4575f13b.dcm -82.00099  -1.59502500 214.47944
#> 27 ID_3cb1b59bc.dcm -82.00099  -0.09198722 219.24818
#> 28 ID_c35d5c858.dcm -82.00099   1.41105063 224.01692
#> 29 ID_317330708.dcm -82.00099   2.91408847 228.78566
#> 30 ID_8144c7120.dcm -82.00099   4.41712631 233.55440
#> 31 ID_d7777de78.dcm -82.00099   5.92016416 238.32314

Here is the output of dcm2niix on the original data

d_res = dcm2nii(
  basedir = exdir,
  opts = " -v y ")
#> #Copying Files
#> # Converting to nii
#> '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file128521a45290d'
#> Warning in dcm2nii(basedir = exdir, opts = " -v y "): Result indicated an
#> error! Please check results.
d_res
#> $result
#> [1] 1
#> 
#> $nii_before
#> character(0)
#> 
#> $nii_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file128521a45290d/_0_3760890702.nii.gz"
#> 
#> $json_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file128521a45290d/_0_3760890702.json"
#> 
#> $json_before
#> character(0)
#> 
#> $cmd
#> [1] "'/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file128521a45290d'"
img = readnii(d_res$nii_after)
dim(img)
#> [1] 404 430  31
ortho2(window_img(img))

Let’s look at the last slice:

ortho2(window_img(img), xyz = c(202, 215, 1))

Copy the data

Here we are copying the data to a different folder to make instance number

tmpdir = tempfile()
dir.create(tmpdir)
file.copy(paths, tmpdir)
#>  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [15] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [29] TRUE TRUE TRUE

Here we are making the instance number spatial on z,
modifying the instance number

tmp_paths = file.path(tmpdir, basename(wide$file))
ind = seq_along(tmp_paths)
add_instance = function(file, index) {
  dcmtk::dcmodify(
    file = file,
    frontopts = paste0('-i "(0020,0013)=', index, '"')
  )
  hdr = read_dicom_header(file)
  new_inst = as.numeric(sub_bracket(hdr$value[hdr$name == "InstanceNumber"]))
  stopifnot(new_inst == index)
  print(new_inst)
  bakfile = paste0(file, ".bak")
  if (file.exists(bakfile)) {
    file.remove(bakfile)
  }
}
res = mapply(add_instance, tmp_paths, ind)
#> /usr/local/bin/dcmodify -i "(0020,0013)=1"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_12a0d6d34.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_12a0d6d34.dcm
#> [1] 1
#> /usr/local/bin/dcmodify -i "(0020,0013)=2"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_12e3b6923.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_12e3b6923.dcm
#> [1] 2
#> /usr/local/bin/dcmodify -i "(0020,0013)=3"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6b15a7649.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6b15a7649.dcm
#> [1] 3
#> /usr/local/bin/dcmodify -i "(0020,0013)=4"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_7c08b7fb7.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_7c08b7fb7.dcm
#> [1] 4
#> /usr/local/bin/dcmodify -i "(0020,0013)=5"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6cb797177.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6cb797177.dcm
#> [1] 5
#> /usr/local/bin/dcmodify -i "(0020,0013)=6"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_bb2a4a01c.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_bb2a4a01c.dcm
#> [1] 6
#> /usr/local/bin/dcmodify -i "(0020,0013)=7"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6dcedd2e1.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6dcedd2e1.dcm
#> [1] 7
#> /usr/local/bin/dcmodify -i "(0020,0013)=8"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_b494c2115.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_b494c2115.dcm
#> [1] 8
#> /usr/local/bin/dcmodify -i "(0020,0013)=9"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_ae7b11865.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_ae7b11865.dcm
#> [1] 9
#> /usr/local/bin/dcmodify -i "(0020,0013)=10"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_21053fe7e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_21053fe7e.dcm
#> [1] 10
#> /usr/local/bin/dcmodify -i "(0020,0013)=11"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_f4891876d.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_f4891876d.dcm
#> [1] 11
#> /usr/local/bin/dcmodify -i "(0020,0013)=12"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_18aac96c0.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_18aac96c0.dcm
#> [1] 12
#> /usr/local/bin/dcmodify -i "(0020,0013)=13"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8a35660d5.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8a35660d5.dcm
#> [1] 13
#> /usr/local/bin/dcmodify -i "(0020,0013)=14"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_d4ea87a35.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_d4ea87a35.dcm
#> [1] 14
#> /usr/local/bin/dcmodify -i "(0020,0013)=15"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_0b0e59911.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_0b0e59911.dcm
#> [1] 15
#> /usr/local/bin/dcmodify -i "(0020,0013)=16"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_97e5a203e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_97e5a203e.dcm
#> [1] 16
#> /usr/local/bin/dcmodify -i "(0020,0013)=17"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_ac39010dc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_ac39010dc.dcm
#> [1] 17
#> /usr/local/bin/dcmodify -i "(0020,0013)=18"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_4f0317d23.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_4f0317d23.dcm
#> [1] 18
#> /usr/local/bin/dcmodify -i "(0020,0013)=19"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_362423b57.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_362423b57.dcm
#> [1] 19
#> /usr/local/bin/dcmodify -i "(0020,0013)=20"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_dd3b5bf4e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_dd3b5bf4e.dcm
#> [1] 20
#> /usr/local/bin/dcmodify -i "(0020,0013)=21"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8f5d4b696.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8f5d4b696.dcm
#> [1] 21
#> /usr/local/bin/dcmodify -i "(0020,0013)=22"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_66accd2e4.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_66accd2e4.dcm
#> [1] 22
#> /usr/local/bin/dcmodify -i "(0020,0013)=23"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_17103c79e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_17103c79e.dcm
#> [1] 23
#> /usr/local/bin/dcmodify -i "(0020,0013)=24"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_9a3bba619.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_9a3bba619.dcm
#> [1] 24
#> /usr/local/bin/dcmodify -i "(0020,0013)=25"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8d0ca7742.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8d0ca7742.dcm
#> [1] 25
#> /usr/local/bin/dcmodify -i "(0020,0013)=26"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_c4575f13b.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_c4575f13b.dcm
#> [1] 26
#> /usr/local/bin/dcmodify -i "(0020,0013)=27"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_3cb1b59bc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_3cb1b59bc.dcm
#> [1] 27
#> /usr/local/bin/dcmodify -i "(0020,0013)=28"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_c35d5c858.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_c35d5c858.dcm
#> [1] 28
#> /usr/local/bin/dcmodify -i "(0020,0013)=29"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_317330708.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_317330708.dcm
#> [1] 29
#> /usr/local/bin/dcmodify -i "(0020,0013)=30"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8144c7120.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8144c7120.dcm
#> [1] 30
#> /usr/local/bin/dcmodify -i "(0020,0013)=31"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_d7777de78.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_d7777de78.dcm
#> [1] 31

Checking the instance number

tmp_hdr = lapply(tmp_paths, read_dicom_header)
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_12a0d6d34.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_12e3b6923.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6b15a7649.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_7c08b7fb7.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6cb797177.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_bb2a4a01c.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_6dcedd2e1.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_b494c2115.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_ae7b11865.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_21053fe7e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_f4891876d.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_18aac96c0.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8a35660d5.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_d4ea87a35.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_0b0e59911.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_97e5a203e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_ac39010dc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_4f0317d23.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_362423b57.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_dd3b5bf4e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8f5d4b696.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_66accd2e4.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_17103c79e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_9a3bba619.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8d0ca7742.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_c4575f13b.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_3cb1b59bc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_c35d5c858.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_317330708.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_8144c7120.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpZbpdM1/file128528591929/ID_d7777de78.dcm
tmp_hdr = bind_rows(tmp_hdr)
# arranging because reshaping can cause reordering of files
tmp_hdr = tmp_hdr %>% 
  mutate(file = factor(tmp_hdr$file, levels = tmp_paths)) %>% 
  arrange(file)
tmp_wide = wide_hdr(tmp_hdr)
tmp_wide$InstanceNumber
#>  [1] "[1]"  "[2]"  "[3]"  "[4]"  "[5]"  "[6]"  "[7]"  "[8]"  "[9]"  "[10]"
#> [11] "[11]" "[12]" "[13]" "[14]" "[15]" "[16]" "[17]" "[18]" "[19]" "[20]"
#> [21] "[21]" "[22]" "[23]" "[24]" "[25]" "[26]" "[27]" "[28]" "[29]" "[30]"
#> [31] "[31]"

Checking the output with filled in instance number

inst_res = dcm2nii(
  basedir = tmpdir,
  # files = tmp_paths,
  opts = " -v y ")
#> #Copying Files
#> # Converting to nii
#> '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file12852239d3ae9'
inst_res
#> $result
#> [1] 0
#> 
#> $nii_before
#> character(0)
#> 
#> $nii_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file12852239d3ae9/_0_3760890702.nii.gz"
#> 
#> $json_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file12852239d3ae9/_0_3760890702.json"
#> 
#> $json_before
#> character(0)
#> 
#> $cmd
#> [1] "'/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/RtmpZbpdM1/file12852239d3ae9'"
inst_img = readnii(inst_res$nii_after)
dim(inst_img)
#> [1] 404 430  31

Note the last slice

ortho2(window_img(inst_img))

Let’s look at the last slice:

ortho2(window_img(inst_img), xyz = c(202, 215, 1))

Created on 2019-09-27 by the reprex package (v0.3.0)

Session info
devtools::session_info()
#> ─ Session info ──────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.0 (2019-04-26)
#>  os       macOS Mojave 10.14.6        
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       America/New_York            
#>  date     2019-09-27                  
#> 
#> ─ Packages ──────────────────────────────────────────────────────────────
#>  package     * version    date       lib
#>  abind         1.4-5      2016-07-21 [1]
#>  assertthat    0.2.1      2019-03-21 [1]
#>  backports     1.1.4      2019-04-10 [1]
#>  bitops        1.0-6      2013-08-17 [1]
#>  callr         3.3.1      2019-07-18 [1]
#>  cli           1.1.0      2019-03-19 [1]
#>  crayon        1.3.4      2017-09-16 [1]
#>  curl          4.0        2019-07-22 [1]
#>  dcm2niir    * 0.6.8.1    2019-09-23 [1]
#>  dcmtk       * 0.6.8      2019-08-30 [1]
#>  desc          1.2.0      2019-07-10 [1]
#>  devtools      2.2.0.9000 2019-09-10 [1]
#>  digest        0.6.21     2019-09-20 [1]
#>  dplyr       * 0.8.3      2019-07-04 [1]
#>  DT            0.8        2019-08-07 [1]
#>  ellipsis      0.3.0      2019-09-20 [1]
#>  evaluate      0.14       2019-05-28 [1]
#>  fs            1.3.1      2019-05-06 [1]
#>  git2r         0.26.1     2019-06-29 [1]
#>  glue          1.3.1      2019-03-12 [1]
#>  highr         0.8        2019-03-20 [1]
#>  hms           0.5.1      2019-08-23 [1]
#>  htmltools     0.3.6      2017-04-28 [1]
#>  htmlwidgets   1.3        2018-09-30 [1]
#>  httr          1.4.1      2019-08-05 [1]
#>  knitr         1.24.3     2019-08-28 [1]
#>  lubridate     1.7.4      2018-04-11 [1]
#>  magrittr      1.5        2014-11-22 [1]
#>  matrixStats   0.55.0     2019-09-07 [1]
#>  memoise       1.1.0      2017-04-21 [1]
#>  mime          0.7        2019-06-11 [1]
#>  neurobase   * 1.27.11.2  2019-09-19 [1]
#>  oro.nifti   * 0.10.1     2019-08-12 [1]
#>  pillar        1.4.2      2019-06-29 [1]
#>  pkgbuild      1.0.5      2019-08-26 [1]
#>  pkgconfig     2.0.3      2019-09-22 [1]
#>  pkgload       1.0.2      2018-10-29 [1]
#>  prettyunits   1.0.2      2015-07-13 [1]
#>  processx      3.4.1      2019-07-18 [1]
#>  ps            1.3.0      2018-12-21 [1]
#>  purrr         0.3.2      2019-03-15 [1]
#>  R.methodsS3   1.7.1      2016-02-16 [1]
#>  R.oo          1.22.0     2018-04-22 [1]
#>  R.utils       2.9.0      2019-06-13 [1]
#>  R6            2.4.0      2019-02-14 [1]
#>  Rcpp          1.0.2      2019-07-25 [1]
#>  readr       * 1.3.1      2018-12-21 [1]
#>  remotes       2.1.0      2019-06-24 [1]
#>  rlang         0.4.0      2019-06-25 [1]
#>  rmarkdown     1.15       2019-08-21 [1]
#>  RNifti        0.11.1     2019-09-26 [1]
#>  rprojroot     1.3-2      2018-01-03 [1]
#>  sessioninfo   1.1.1      2018-11-05 [1]
#>  stringi       1.4.3      2019-03-12 [1]
#>  stringr       1.4.0      2019-02-10 [1]
#>  testthat      2.2.1      2019-07-25 [1]
#>  tibble        2.1.3      2019-06-06 [1]
#>  tidyr       * 0.8.3      2019-03-01 [1]
#>  tidyselect    0.2.5      2018-10-11 [1]
#>  usethis       1.5.1.9000 2019-08-15 [1]
#>  vctrs         0.2.0      2019-07-05 [1]
#>  withr         2.1.2      2018-03-15 [1]
#>  xfun          0.9        2019-08-21 [1]
#>  xml2          1.2.2      2019-08-09 [1]
#>  yaml          2.2.0      2018-07-25 [1]
#>  zeallot       0.1.0      2018-01-28 [1]
#>  source                            
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  local                             
#>  Github (muschellij2/desc@b0c374f) 
#>  Github (r-lib/devtools@d7f0915)   
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  Github (muschellij2/knitr@abcea3d)
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  local                             
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

@neurolabusc
Copy link
Collaborator

Thanks for your elegant example. This does reveal a bug where the first slice was not reloaded when the software had to fall back on slice position to infer spatial positions. The latest commit to the developmental branch (v1.0.20190927) should resolve this. My solution is very redundant and verbose, but it does seem robust. There are three main changes:

  • Fixes bug where reordering does not update the first slice.
  • While Instance Number (0020,0013) is Type 1 (required) by most imaging modalities, examples exist (as presented here) where this tag is omitted. In this situation, the absolute value of the CRC for the MediaStorageSOPInstanceUID (0002,0003) is used in place of the instance number. The intention is to avoid name clashing, in particular when renaming DICOMs (-r y). In this situation, the software might issue a spurious warning Missing images? Expected 31 images, but instance number (0020,0013) ranges from 252560071 to 734320434, though the user is also warned Instance number (0020,0013) not found. Maybe this can be made more elegant, but I would rather prevent name clashing.
  • If slice re-ordering resolves issues with spatial position, the messages reflect this:
Warning: Interslice distance varies in this volume (incompatible with NIfTI format).
Warning: Order specified by DICOM instance number is not spatial (reordering).
Slice re-ordering resolved inter-slice distance variability.

Please close this issue if you can validate that this commit handles your unusual images.

@muschellij2
Copy link
Contributor Author

I have merged my repo to the dev branch as rordenlab/dcm2niix:

Load up Packages

library(dcm2niir)
library(dcmtk)
library(readr)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr)
library(neurobase)
#> Loading required package: oro.nifti
#> oro.nifti 0.10.1
#> 
#> Attaching package: 'oro.nifti'
#> The following object is masked from 'package:dplyr':
#> 
#>     slice
#> Registered S3 method overwritten by 'R.oo':
#>   method        from       
#>   throw.default R.methodsS3

# install_dcm2nii(from_source = TRUE, overwrite = TRUE,
#                 # muschellij2 has the development merged
#                 git_url = "https://github.com/muschellij2/dcm2niix")

Download the data

url = "https://github.com/rordenlab/dcm2niix/files/3663869/data.zip"
destfile = tempfile(fileext = ".zip")
download.file(url, destfile)

Version of dcm2niix is the most up to date GitHub built from source

dcm2nii_version()
#> [1] "Chris Rorden's dcm2niiX version v1.0.20190927  Clang10.0.1 (64-bit MacOS)"
# install_dcm2nii(from_source = TRUE, overwrite = TRUE)

Here we are unzipping the data to a temporary file

exdir = tempfile()
dir.create(exdir)
unzip(destfile, exdir = exdir)
paths = list.files(pattern = ".dcm", path = exdir, full.names = TRUE)

Here is the header information:

# showing the image position patient
hdr = read_dicom_header(path = exdir, recursive = TRUE)
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename --recurse --scan-directories '/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file1693320b67fdb' --scan-pattern  *.dcm
wide = wide_hdr(hdr)

sort(unique(hdr$name))
#>  [1] "BitsAllocated"                  "BitsStored"                    
#>  [3] "Columns"                        "FileMetaInformationGroupLength"
#>  [5] "FileMetaInformationVersion"     "HighBit"                       
#>  [7] "ImageOrientationPatient"        "ImagePositionPatient"          
#>  [9] "ImplementationClassUID"         "ImplementationVersionName"     
#> [11] "MediaStorageSOPClassUID"        "MediaStorageSOPInstanceUID"    
#> [13] "Modality"                       "PatientID"                     
#> [15] "PhotometricInterpretation"      "PixelData"                     
#> [17] "PixelRepresentation"            "PixelSpacing"                  
#> [19] "RescaleIntercept"               "RescaleSlope"                  
#> [21] "Rows"                           "SamplesPerPixel"               
#> [23] "SeriesInstanceUID"              "SOPInstanceUID"                
#> [25] "StudyID"                        "StudyInstanceUID"              
#> [27] "TransferSyntaxUID"              "WindowCenter"                  
#> [29] "WindowWidth"

DICOM Headers are missing

# no gantry tilt DICOM header!
any(grepl("ilt", tolower(hdr$name)))
#> [1] FALSE
any(grepl("instancenum", tolower(hdr$name)))
#> [1] FALSE

sub_bracket = function(x) {
  x = sub("^\\[", "", x)
  x = sub("\\]$", "", x)
  x = trimws(x)
}
parse_number_no_na = function(x) {
  x[ x %in% c("-", "-", "N/A")] = NA
  na_x = is.na(x)
  x = readr::parse_number(x, na = "")
  bad = is.na(x) & !na_x 
  stopifnot(!any(bad))
  x
}

wide = wide %>% 
  mutate(ipp = sub_bracket(gsub("\\\\", ",", ImagePositionPatient))) %>% 
  tidyr::separate(ipp, into = c("x", "y", "z"), remove = FALSE, sep = ",") %>% 
  mutate_at(vars(x, y, z), parse_number_no_na)

# order by z
wide = wide %>% 
  select(file, x, y, z, ipp) %>% 
  arrange(z)

Showing the image position patients (ordered for instance number later)

wide %>% 
  mutate(file = basename(file)) %>% 
  select(file, x, y, z) %>% 
  as.data.frame
#>                file         x            y         z
#> 1  ID_12a0d6d34.dcm -82.00099 -39.17097000  95.26095
#> 2  ID_12e3b6923.dcm -82.00099 -37.66793000 100.02969
#> 3  ID_6b15a7649.dcm -82.00099 -36.16490000 104.79843
#> 4  ID_7c08b7fb7.dcm -82.00099 -34.66185762 109.56717
#> 5  ID_6cb797177.dcm -82.00099 -33.15882000 114.33591
#> 6  ID_bb2a4a01c.dcm -82.00099 -31.65578000 119.10465
#> 7  ID_6dcedd2e1.dcm -82.00099 -30.15274000 123.87339
#> 8  ID_b494c2115.dcm -82.00099 -28.64971000 128.64213
#> 9  ID_ae7b11865.dcm -82.00099 -27.14667000 133.41087
#> 10 ID_21053fe7e.dcm -82.00099 -25.64363056 138.17961
#> 11 ID_f4891876d.dcm -82.00099 -24.14059000 142.94835
#> 12 ID_18aac96c0.dcm -82.00099 -22.63755000 147.71709
#> 13 ID_8a35660d5.dcm -82.00099 -21.13452000 152.48583
#> 14 ID_d4ea87a35.dcm -82.00099 -19.63148000 157.25457
#> 15 ID_0b0e59911.dcm -82.00099 -18.12844000 162.02331
#> 16 ID_97e5a203e.dcm -82.00099 -16.62540350 166.79205
#> 17 ID_ac39010dc.dcm -82.00099 -15.12237000 171.56079
#> 18 ID_4f0317d23.dcm -82.00099 -13.61933000 176.32953
#> 19 ID_362423b57.dcm -82.00099 -12.11629000 181.09826
#> 20 ID_dd3b5bf4e.dcm -82.00099 -10.61325000 185.86700
#> 21 ID_8f5d4b696.dcm -82.00099  -9.11021400 190.63574
#> 22 ID_66accd2e4.dcm -82.00099  -7.60717600 195.40448
#> 23 ID_17103c79e.dcm -82.00099  -6.10413900 200.17322
#> 24 ID_9a3bba619.dcm -82.00099  -4.60110100 204.94196
#> 25 ID_8d0ca7742.dcm -82.00099  -3.09806300 209.71070
#> 26 ID_c4575f13b.dcm -82.00099  -1.59502500 214.47944
#> 27 ID_3cb1b59bc.dcm -82.00099  -0.09198722 219.24818
#> 28 ID_c35d5c858.dcm -82.00099   1.41105063 224.01692
#> 29 ID_317330708.dcm -82.00099   2.91408847 228.78566
#> 30 ID_8144c7120.dcm -82.00099   4.41712631 233.55440
#> 31 ID_d7777de78.dcm -82.00099   5.92016416 238.32314

Here is the output of dcm2niix on the original data

d_res = dcm2nii(
  basedir = exdir,
  opts = " -v y ")
#> #Copying Files
#> # Converting to nii
#> '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file16933486b22e5'
d_res
#> $result
#> [1] 0
#> 
#> $nii_before
#> character(0)
#> 
#> $nii_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file16933486b22e5/_0_3760890702.nii.gz"
#> 
#> $json_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file16933486b22e5/_0_3760890702.json"
#> 
#> $json_before
#> character(0)
#> 
#> $cmd
#> [1] "'/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file16933486b22e5'"
img = readnii(d_res$nii_after)
dim(img)
#> [1] 404 430  31
ortho2(window_img(img))

Let’s look at the last slice:

ortho2(window_img(img), xyz = c(202, 215, 1))

Copy the data

Here we are copying the data to a different folder to make instance number

tmpdir = tempfile()
dir.create(tmpdir)
file.copy(paths, tmpdir)
#>  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [15] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [29] TRUE TRUE TRUE

Here we are making the instance number spatial on z,
modifying the instance number

tmp_paths = file.path(tmpdir, basename(wide$file))
ind = seq_along(tmp_paths)
add_instance = function(file, index) {
  dcmtk::dcmodify(
    file = file,
    frontopts = paste0('-i "(0020,0013)=', index, '"')
  )
  hdr = read_dicom_header(file)
  new_inst = as.numeric(sub_bracket(hdr$value[hdr$name == "InstanceNumber"]))
  stopifnot(new_inst == index)
  print(new_inst)
  bakfile = paste0(file, ".bak")
  if (file.exists(bakfile)) {
    file.remove(bakfile)
  }
}
res = mapply(add_instance, tmp_paths, ind)
#> /usr/local/bin/dcmodify -i "(0020,0013)=1"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_12a0d6d34.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_12a0d6d34.dcm
#> [1] 1
#> /usr/local/bin/dcmodify -i "(0020,0013)=2"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_12e3b6923.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_12e3b6923.dcm
#> [1] 2
#> /usr/local/bin/dcmodify -i "(0020,0013)=3"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6b15a7649.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6b15a7649.dcm
#> [1] 3
#> /usr/local/bin/dcmodify -i "(0020,0013)=4"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_7c08b7fb7.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_7c08b7fb7.dcm
#> [1] 4
#> /usr/local/bin/dcmodify -i "(0020,0013)=5"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6cb797177.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6cb797177.dcm
#> [1] 5
#> /usr/local/bin/dcmodify -i "(0020,0013)=6"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_bb2a4a01c.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_bb2a4a01c.dcm
#> [1] 6
#> /usr/local/bin/dcmodify -i "(0020,0013)=7"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6dcedd2e1.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6dcedd2e1.dcm
#> [1] 7
#> /usr/local/bin/dcmodify -i "(0020,0013)=8"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_b494c2115.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_b494c2115.dcm
#> [1] 8
#> /usr/local/bin/dcmodify -i "(0020,0013)=9"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_ae7b11865.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_ae7b11865.dcm
#> [1] 9
#> /usr/local/bin/dcmodify -i "(0020,0013)=10"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_21053fe7e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_21053fe7e.dcm
#> [1] 10
#> /usr/local/bin/dcmodify -i "(0020,0013)=11"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_f4891876d.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_f4891876d.dcm
#> [1] 11
#> /usr/local/bin/dcmodify -i "(0020,0013)=12"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_18aac96c0.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_18aac96c0.dcm
#> [1] 12
#> /usr/local/bin/dcmodify -i "(0020,0013)=13"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8a35660d5.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8a35660d5.dcm
#> [1] 13
#> /usr/local/bin/dcmodify -i "(0020,0013)=14"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_d4ea87a35.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_d4ea87a35.dcm
#> [1] 14
#> /usr/local/bin/dcmodify -i "(0020,0013)=15"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_0b0e59911.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_0b0e59911.dcm
#> [1] 15
#> /usr/local/bin/dcmodify -i "(0020,0013)=16"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_97e5a203e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_97e5a203e.dcm
#> [1] 16
#> /usr/local/bin/dcmodify -i "(0020,0013)=17"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_ac39010dc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_ac39010dc.dcm
#> [1] 17
#> /usr/local/bin/dcmodify -i "(0020,0013)=18"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_4f0317d23.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_4f0317d23.dcm
#> [1] 18
#> /usr/local/bin/dcmodify -i "(0020,0013)=19"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_362423b57.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_362423b57.dcm
#> [1] 19
#> /usr/local/bin/dcmodify -i "(0020,0013)=20"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_dd3b5bf4e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_dd3b5bf4e.dcm
#> [1] 20
#> /usr/local/bin/dcmodify -i "(0020,0013)=21"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8f5d4b696.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8f5d4b696.dcm
#> [1] 21
#> /usr/local/bin/dcmodify -i "(0020,0013)=22"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_66accd2e4.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_66accd2e4.dcm
#> [1] 22
#> /usr/local/bin/dcmodify -i "(0020,0013)=23"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_17103c79e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_17103c79e.dcm
#> [1] 23
#> /usr/local/bin/dcmodify -i "(0020,0013)=24"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_9a3bba619.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_9a3bba619.dcm
#> [1] 24
#> /usr/local/bin/dcmodify -i "(0020,0013)=25"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8d0ca7742.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8d0ca7742.dcm
#> [1] 25
#> /usr/local/bin/dcmodify -i "(0020,0013)=26"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_c4575f13b.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_c4575f13b.dcm
#> [1] 26
#> /usr/local/bin/dcmodify -i "(0020,0013)=27"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_3cb1b59bc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_3cb1b59bc.dcm
#> [1] 27
#> /usr/local/bin/dcmodify -i "(0020,0013)=28"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_c35d5c858.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_c35d5c858.dcm
#> [1] 28
#> /usr/local/bin/dcmodify -i "(0020,0013)=29"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_317330708.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_317330708.dcm
#> [1] 29
#> /usr/local/bin/dcmodify -i "(0020,0013)=30"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8144c7120.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8144c7120.dcm
#> [1] 30
#> /usr/local/bin/dcmodify -i "(0020,0013)=31"  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_d7777de78.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_d7777de78.dcm
#> [1] 31

Checking the instance number

tmp_hdr = lapply(tmp_paths, read_dicom_header)
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_12a0d6d34.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_12e3b6923.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6b15a7649.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_7c08b7fb7.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6cb797177.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_bb2a4a01c.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_6dcedd2e1.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_b494c2115.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_ae7b11865.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_21053fe7e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_f4891876d.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_18aac96c0.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8a35660d5.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_d4ea87a35.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_0b0e59911.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_97e5a203e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_ac39010dc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_4f0317d23.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_362423b57.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_dd3b5bf4e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8f5d4b696.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_66accd2e4.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_17103c79e.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_9a3bba619.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8d0ca7742.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_c4575f13b.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_3cb1b59bc.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_c35d5c858.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_317330708.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_8144c7120.dcm
#> /usr/local/bin/dcmdump -q --print-all --load-short --print-filename  /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmp6D2UN0/file1693366adb53f/ID_d7777de78.dcm
tmp_hdr = bind_rows(tmp_hdr)
# arranging because reshaping can cause reordering of files
tmp_hdr = tmp_hdr %>% 
  mutate(file = factor(tmp_hdr$file, levels = tmp_paths)) %>% 
  arrange(file)
tmp_wide = wide_hdr(tmp_hdr)
tmp_wide$InstanceNumber
#>  [1] "[1]"  "[2]"  "[3]"  "[4]"  "[5]"  "[6]"  "[7]"  "[8]"  "[9]"  "[10]"
#> [11] "[11]" "[12]" "[13]" "[14]" "[15]" "[16]" "[17]" "[18]" "[19]" "[20]"
#> [21] "[21]" "[22]" "[23]" "[24]" "[25]" "[26]" "[27]" "[28]" "[29]" "[30]"
#> [31] "[31]"

Checking the output with filled in instance number

inst_res = dcm2nii(
  basedir = tmpdir,
  # files = tmp_paths,
  opts = " -v y ")
#> #Copying Files
#> # Converting to nii
#> '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file1693317a1a1db'
inst_res
#> $result
#> [1] 0
#> 
#> $nii_before
#> character(0)
#> 
#> $nii_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file1693317a1a1db/_0_3760890702.nii.gz"
#> 
#> $json_after
#> [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file1693317a1a1db/_0_3760890702.json"
#> 
#> $json_before
#> character(0)
#> 
#> $cmd
#> [1] "'/Library/Frameworks/R.framework/Versions/3.6/Resources/library/dcm2niir/dcm2niix'  -v y  '/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmp6D2UN0/file1693317a1a1db'"
inst_img = readnii(inst_res$nii_after)
dim(inst_img)
#> [1] 404 430  31

Note the last slice

ortho2(window_img(inst_img))

Let’s look at the last slice:

ortho2(window_img(inst_img), xyz = c(202, 215, 1))

All equal after the development updates

all.equal(img, inst_img)
#> [1] TRUE

Created on 2019-09-30 by the reprex package (v0.3.0)

Session info
devtools::session_info()
#> ─ Session info ──────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.0 (2019-04-26)
#>  os       macOS Mojave 10.14.6        
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       America/New_York            
#>  date     2019-09-30                  
#> 
#> ─ Packages ──────────────────────────────────────────────────────────────
#>  package     * version    date       lib
#>  abind         1.4-5      2016-07-21 [1]
#>  assertthat    0.2.1      2019-03-21 [1]
#>  backports     1.1.4      2019-04-10 [1]
#>  bitops        1.0-6      2013-08-17 [1]
#>  callr         3.3.1      2019-07-18 [1]
#>  cli           1.1.0      2019-03-19 [1]
#>  crayon        1.3.4      2017-09-16 [1]
#>  curl          4.0        2019-07-22 [1]
#>  dcm2niir    * 0.6.8.1    2019-09-30 [1]
#>  dcmtk       * 0.6.8.1    2019-09-27 [1]
#>  desc          1.2.0      2019-07-10 [1]
#>  devtools      2.2.0.9000 2019-09-10 [1]
#>  digest        0.6.21     2019-09-20 [1]
#>  dplyr       * 0.8.3      2019-07-04 [1]
#>  DT            0.8        2019-08-07 [1]
#>  ellipsis      0.3.0      2019-09-20 [1]
#>  evaluate      0.14       2019-05-28 [1]
#>  fs            1.3.1      2019-05-06 [1]
#>  git2r         0.26.1     2019-06-29 [1]
#>  glue          1.3.1      2019-03-12 [1]
#>  highr         0.8        2019-03-20 [1]
#>  hms           0.5.1      2019-08-23 [1]
#>  htmltools     0.3.6      2017-04-28 [1]
#>  htmlwidgets   1.3        2018-09-30 [1]
#>  httr          1.4.1      2019-08-05 [1]
#>  knitr         1.24.3     2019-08-28 [1]
#>  lubridate     1.7.4      2018-04-11 [1]
#>  magrittr      1.5        2014-11-22 [1]
#>  matrixStats   0.55.0     2019-09-07 [1]
#>  memoise       1.1.0      2017-04-21 [1]
#>  mime          0.7        2019-06-11 [1]
#>  neurobase   * 1.27.11.2  2019-09-19 [1]
#>  oro.nifti   * 0.10.1     2019-08-12 [1]
#>  pillar        1.4.2      2019-06-29 [1]
#>  pkgbuild      1.0.5      2019-08-26 [1]
#>  pkgconfig     2.0.3      2019-09-22 [1]
#>  pkgload       1.0.2      2018-10-29 [1]
#>  prettyunits   1.0.2      2015-07-13 [1]
#>  processx      3.4.1      2019-07-18 [1]
#>  ps            1.3.0      2018-12-21 [1]
#>  purrr         0.3.2      2019-03-15 [1]
#>  R.methodsS3   1.7.1      2016-02-16 [1]
#>  R.oo          1.22.0     2018-04-22 [1]
#>  R.utils       2.9.0      2019-06-13 [1]
#>  R6            2.4.0      2019-02-14 [1]
#>  Rcpp          1.0.2      2019-07-25 [1]
#>  readr       * 1.3.1      2018-12-21 [1]
#>  remotes       2.1.0      2019-06-24 [1]
#>  rlang         0.4.0      2019-06-25 [1]
#>  rmarkdown     1.15       2019-08-21 [1]
#>  RNifti        0.11.1     2019-09-26 [1]
#>  rprojroot     1.3-2      2018-01-03 [1]
#>  sessioninfo   1.1.1      2018-11-05 [1]
#>  stringi       1.4.3      2019-03-12 [1]
#>  stringr       1.4.0      2019-02-10 [1]
#>  testthat      2.2.1      2019-07-25 [1]
#>  tibble        2.1.3      2019-06-06 [1]
#>  tidyr       * 0.8.3      2019-03-01 [1]
#>  tidyselect    0.2.5      2018-10-11 [1]
#>  usethis       1.5.1.9000 2019-08-15 [1]
#>  vctrs         0.2.0      2019-07-05 [1]
#>  withr         2.1.2      2018-03-15 [1]
#>  xfun          0.9        2019-08-21 [1]
#>  xml2          1.2.2      2019-08-09 [1]
#>  yaml          2.2.0      2018-07-25 [1]
#>  zeallot       0.1.0      2018-01-28 [1]
#>  source                            
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  local                             
#>  Github (muschellij2/desc@b0c374f) 
#>  Github (r-lib/devtools@d7f0915)   
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  Github (muschellij2/knitr@abcea3d)
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  local                             
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  local                             
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#>  CRAN (R 3.6.0)                    
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

@muschellij2
Copy link
Contributor Author

As an aside, is it possible to:

  1. Do the bookkeeping of the DICOM file to the slice of the NIfTI image. This is crucial as we're trying to do slice-specific prediction.
  2. Implement a flag for not doing gantry tilt correction and/or interpolation (or being able to turn on GA correction but not interpolation). The rationale is that if the bookkeeping may not be great or easy, then just keeping the NIfTI with a 1-to-1 correspondence with the DICOM may be useful in radiological aspects but violate the NIfTI standards and cause some malformed NIfTIs.
  3. Do neither, but put in the development pipeline a flag to always give both the corrected and non-corrected (aka I'm relying on both coming out and not just the corrected and want to make sure future behavior keeps that)

@neurolabusc
Copy link
Collaborator

I would suggest you fork the dcm2niix repository and customize nii_dicom_batch.cpp for your desires.

  1. to save the order of DICOM slices as stacked into the NIfTI file.
...
if ((!opts.isOnlyBIDS) && (nConvert > 1)) {
	int iStart = 1;
	...

to read

...
if ((!opts.isOnlyBIDS) && (nConvert > 1)) {
	for (int i = 0; i < nConvert; i++)
		printMessage("%d\t%s\n", i, nameList->str[indx]);	
	int iStart = 1;
	...
  1. To disable tilt correction change the line
opts->isTiltCorrect = true;

to real

opts->isTiltCorrect = false;

Tilt-correction is discussed here. Tilt is effectively a shear that can can be stored in the NIfTI SForm (a 4x4 matrix). However, a shear can not be stored in the Form (a quaternion). Therefore, tools that support the Form (e.g. SPM) will be fine, while tools that assume a rectangular matrix or give precedence to the QForm will not show these volumes correctly (ANTS, Slicer, VTK-based tools).

  1. Adjusting for variable slices is a bit trickier. MRI volumes typically have consistent slice thicknesses and gaps for all slices to keep SNR and interference equally. In contrast, CT scans are often acquired with more slices near the critical brain stem versus the superior slices of the cortex. The NIfTI format requires all slices are equidistant. Therefore, the function nii_saveNII3Deq interpolates slices to generate an output with even spacing. I would suggest similar adding printMessages to your fork of the project that will allow you to back project results to 2D slices.

Form first principles I would think that treating this data as 3D should provide spatial information not available only looking at the 2D slices. If you are one of the few people using a 3D approach, that should give you an edge for winning the substantial prize. You are generous discussing this on an open forum where your competitors can replicate your trick. Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants