rordenlab / dcm2niix

dcm2nii DICOM to NIfTI converter: compiled versions available from NITRC
https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage
Other
863 stars 228 forks source link

trouble converting 3D glioma annotations from Olea Sphere to nifti #572

Closed neuronflow closed 2 years ago

neuronflow commented 2 years ago

Dear readers,

I am trying to convert annotations created in Olea Sphere ( https://www.olea-medical.com/en/solutions/neurology ) into nifti format. The program creates a single .dcm file per label for the whole 3D volume. So I assume the dicom series is somehow embedded in there. When I try to convert the file via dcm2niix I get the following error message:

Chris Rorden's dcm2niiX version v1.0.20181125  (JP2:OpenJPEG) GCC9.3.0 (64-bit Linux)
Found 1 DICOM file(s)
Unsupported DICOM bit-depth 1 with 1 samples per pixel 

Any advice how to proceed? I am happy to share an example file via email but cannot make it public.

Thanks for your time and assistance!

neurolabusc commented 2 years ago

I have never seen a binary DICOM before. Should be easy to support with a concrete exemplar.

I can have a look if you share the dataset - either make it public or send a GoogleDrive/DropBox link to the email address in my avatar.

neurolabusc commented 2 years ago

I have made a commit to the development branch that should add support for 1-bit DICOMs. Please validate this and close this issue if it resolves your issue.

Assuming you are using UNIX, you can build the development branch with the following commands:

git clone --branch development https://github.com/rordenlab/dcm2niix.git
cd dcm2niix/console
make
neuronflow commented 2 years ago

getting this when starting the build:

g++ -s -O3 -I.  main_console.cpp nii_foreign.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp  -o dcm2niix -DmyDisableOpenJPEG
nii_dicom.cpp: In function ‘TDICOMdata readDICOMx(char*, TDCMprefs*, TDTI4D*)’:
nii_dicom.cpp:6885:23: warning: ‘%c’ directive writing 1 byte into a region of size between 0 and 65 [-Wformat-overflow=]
 6885 |     sprintf(str, "%s%c%c ", str, vr[0], vr[1]);
      |                       ^~
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 4 and 69 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6897:24: warning: ‘ ’ directive writing 1 byte into a region of size between 0 and 65 [-Wformat-overflow=]
 6897 |      sprintf(str, "%s%d ", str, dcmInt(lLength, &buffer[lPos], d.isLittleEndian));
      |                        ^
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 3 and 78 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6895:24: warning: ‘ ’ directive writing 1 byte into a region of size between 0 and 65 [-Wformat-overflow=]
 6895 |      sprintf(str, "%s%d ", str, dcmInt(lLength, &buffer[lPos], d.isLittleEndian));
      |                        ^
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 3 and 78 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6893:24: warning: ‘ ’ directive writing 1 byte into a region of size between 0 and 65 [-Wformat-overflow=]
 6893 |      sprintf(str, "%s%d ", str, dcmInt(lLength, &buffer[lPos], d.isLittleEndian));
      |                        ^
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 3 and 78 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6891:24: warning: ‘ ’ directive writing 1 byte into a region of size between 0 and 65 [-Wformat-overflow=]
 6891 |      sprintf(str, "%s%d ", str, dcmInt(lLength, &buffer[lPos], d.isLittleEndian));
      |                        ^
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 3 and 78 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6889:22: warning: ‘%g’ directive writing between 1 and 13 bytes into a region of size between 1 and 66 [-Wformat-overflow=]
 6889 |      sprintf(str, "%s%g ", str, dcmFloat(lLength, &buffer[lPos], d.isLittleEndian));
      |                      ^~
nii_dicom.cpp:6889:19: note: assuming directive output of 12 bytes
 6889 |      sprintf(str, "%s%g ", str, dcmFloat(lLength, &buffer[lPos], d.isLittleEndian));
      |                   ^~~~~~~
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 3 and 80 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6887:22: warning: ‘%g’ directive writing between 1 and 13 bytes into a region of size between 1 and 66 [-Wformat-overflow=]
 6887 |      sprintf(str, "%s%g ", str, dcmFloatDouble(lLength, &buffer[lPos], d.isLittleEndian));
      |                      ^~
nii_dicom.cpp:6887:19: note: assuming directive output of 12 bytes
 6887 |      sprintf(str, "%s%g ", str, dcmFloatDouble(lLength, &buffer[lPos], d.isLittleEndian));
      |                   ^~~~~~~
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 3 and 80 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom.cpp:6935:22: warning: ‘%d’ directive writing between 1 and 11 bytes into a region of size between 0 and 65 [-Wformat-overflow=]
 6935 |     sprintf(str, "%s<%d bytes> ", str, lLength);
      |                      ^~
nii_dicom.cpp:6935:18: note: using the range [-2147483648, 2147483647] for directive argument
 6935 |     sprintf(str, "%s<%d bytes> ", str, lLength);
      |                  ^~~~~~~~~~~~~~~
In file included from /usr/include/stdio.h:867,
                 from print.h:38,
                 from nii_dicom.cpp:28:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 11 and 86 bytes into a destination of size 66
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom_batch.cpp: In function ‘int pigz_File(char*, TDCMopts, size_t)’:
nii_dicom_batch.cpp:3639:22: warning: ‘%s’ directive writing up to 767 bytes into a region of size 255 [-Wformat-overflow=]
 3639 |   sprintf(newstr, "\"%s -n \"", blockSize);
      |                      ^~         ~~~~~~~~~
In file included from /usr/include/stdio.h:867,
                 from miniz.c:2854,
                 from nii_dicom_batch.cpp:22:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 7 and 774 bytes into a destination of size 256
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nii_dicom_batch.cpp:3635:22: warning: ‘%s’ directive writing up to 767 bytes into a region of size 255 [-Wformat-overflow=]
 3635 |   sprintf(newstr, "\"%s -n -f -%d \"", blockSize, opts.gzLevel);
      |                      ^~                ~~~~~~~~~
nii_dicom_batch.cpp:3635:19: note: directive argument in the range [1, 11]
 3635 |   sprintf(newstr, "\"%s -n -f -%d \"", blockSize, opts.gzLevel);
      |                   ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/stdio.h:867,
                 from miniz.c:2854,
                 from nii_dicom_batch.cpp:22:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:34: note: ‘__builtin___sprintf_chk’ output between 13 and 781 bytes into a destination of size 256
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
neurolabusc commented 2 years ago

I am not concerned with these warnings. If they bug you, you can change the code to use snprintf() instead of sprintf()

neuronflow commented 2 years ago

Thank you, my bad I overlooked the created binary!

Screenshot 2022-01-11 at 19 39 06

With the update, I could convert the segmentations. They appear flipped, but I assume this is due to a malformed Dicom header?

Unfortunately, thanks to your amazing software my knowledge of Dicoms remains superficial ;)

neurolabusc commented 2 years ago
  1. A compiler warning is different from an error. You only provided warnings. I assume that your did create an executable. You might also want to report what the command gcc -v reports, as I do not see these warnings. While I do prefer code that does not generate warnings, I need to be cautious as I we need to support a wide number of compilers, and it is easy to have unintended consequences.
  2. The spatial transform should be explicitly determined by ImageOrientationPatient (0020,0037) and ImagePositionPatient (0020,0032). If you want provide me with one of the DICOMs for the anatomical data, I can provide more information. I suspect this either reflects an error on the part of Olea, or a NIfTI viewer that ignores the NIfTI spatial transformation matrix (the s-form). I would check the image alignment using MRIcroGL, which supports NIfTI spatial transforms. I did validate that Slicer and dcm2niix generate the same NIfTI result from your binary images.
neuronflow commented 2 years ago
  1. I agree. Sorry I overlooked the creation of the binary as I was working on a remote server with a GUI and apparently the GUI did not refresh upon creation of the binary. Thank you for providing such a quick fix! I don't mind the warnings at all. In case you do here is output of gcc -v:

    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
    OFFLOAD_TARGET_NAMES=nvptx-none:hsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique -object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) 
  2. I opened the NIfTI in MRIcroGL and it indeed anatomic image and annotation overlap with the tumor displayed on the left. Apparently, my default viewer ITK-SNAP lacks supports for this, see above screenshot (annotation left, anatomic tumor right). I converted both the anatomic image and the annotation using dcm2niix.

Unfortunately, I am not allowed to share the anatomical files. If you want to have them I could try skull-stripping them first.

neurolabusc commented 2 years ago

Sounds like the issue is solved.