[med-svn] [dcm2niix] 01/04: New upstream version 1.0.20171017

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Sun Oct 22 13:23:18 UTC 2017


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/master
in repository dcm2niix.

commit 9ba4e2a42013d8aa0446f6f2e69c841e19af6ecc
Author: Ghislain Antony Vaillant <ghisvail at gmail.com>
Date:   Sat Oct 21 22:40:00 2017 +0100

    New upstream version 1.0.20171017
---
 BATCH.md                    |  28 +++++
 COMPILE.md                  |   5 +-
 README.md                   | 152 ++----------------------
 README.md => VERSIONS.md    | 110 +-----------------
 console/nii_dicom.cpp       |  85 ++++++++++----
 console/nii_dicom.h         |  13 ++-
 console/nii_dicom_batch.cpp | 126 ++++++++++++++++----
 console/nii_foreign.cpp     |  35 +++++-
 old_nii_SaveBIDS.cpp        | 274 --------------------------------------------
 9 files changed, 251 insertions(+), 577 deletions(-)

diff --git a/BATCH.md b/BATCH.md
new file mode 100644
index 0000000..e3c6809
--- /dev/null
+++ b/BATCH.md
@@ -0,0 +1,28 @@
+**Optional batch processing version:**
+
+Perform a batch conversion of multiple dicoms using the configurations specified in a yaml file.
+```bash
+dcm2niibatch batch_config.yml
+```
+
+The configuration file should be in yaml format as shown in example `batch_config.yaml`
+
+```yaml
+Options:
+  isGz:             false
+  isFlipY:          false
+  isVerbose:        false
+  isCreateBIDS:     false
+  isOnlySingleFile: false
+Files:
+    -
+      in_dir:           /path/to/first/folder
+      out_dir:          /path/to/output/folder
+      filename:         dcemri
+    -
+      in_dir:           /path/to/second/folder
+      out_dir:          /path/to/output/folder
+      filename:         fa3
+```
+
+You can add as many files as you want to convert as long as this structure stays consistent. Note that a dash must separate each file.
diff --git a/COMPILE.md b/COMPILE.md
index c5c8e06..a1b8946 100644
--- a/COMPILE.md
+++ b/COMPILE.md
@@ -6,7 +6,6 @@ The README.md file describes the typical compilation of the software, using the
 
 The text below generally describes how to build dcm2niix using the [GCC](https://gcc.gnu.org) compiler using the `g++` command. However, the code is portable and you can use different compilers. For [clang/llvm](https://clang.llvm.org) compile using `clang++`.  If you have the [Intel C compiler](https://software.intel.com/en-us/c-compilers), you can substitute the `icc` command. For [Microsoft's C compiler](http://landinghub.visualstudio.com/visual-cpp-build-tools) you would use the `cl` [...]
 
-
 ## Building the command line version without cmake
 
 You can also build the software without C-make. The easiest way to do this is to run the function "make" from the "console" folder. Note that this only creates the default version of dcm2niix, not the optional batch version described above. The make command simply calls the g++ compiler, and if you want you can tune this for your build. In essence, the make function simply calls
@@ -17,6 +16,10 @@ g++ -dead_strip -O3 -I. main_console.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp ni
 
 The following sub-sections list how you can modify this basic recipe for your needs.
 
+## Trouble Shooting
+
+Some [Centos/Redhat](https://github.com/rordenlab/dcm2niix/issues/137) may report "/usr/bin/ld: cannot find -lstdc++". This can be resolved by installing static versions of libstd:  `yum install libstdc++-static`.
+
 ##### ZLIB BUILD
  If we have zlib, we can use it (-lz) and disable [miniz](https://code.google.com/p/miniz/) (-myDisableMiniZ)
 
diff --git a/README.md b/README.md
index 3411e16..97eb97b 100644
--- a/README.md
+++ b/README.md
@@ -11,153 +11,17 @@ This software is open source. The bulk of the code is covered by the BSD license
 
 ## Dependencies
 
-This software should run on macOS, Linux and Windows without requiring any other software. However, if you use dcm2niix to create gz-compressed images it will be faster if you have [pigz](https://github.com/madler/pigz) installed. You can get a version of both dcm2niix and pigz compiled for your operating system by downloading [MRIcroGL](https://www.nitrc.org/projects/mricrogl/).
+This software should run on macOS, Linux and Windows typically without requiring any other software. However, if you use dcm2niix to create gz-compressed images it will be faster if you have [pigz](https://github.com/madler/pigz) installed. You can get a version of both dcm2niix and pigz compiled for your operating system by downloading [MRIcroGL](https://www.nitrc.org/projects/mricrogl/).
 
 ## Versions
 
-23-Sept-2017
- - Swap [phase-encoding direction polarity](https://github.com/rordenlab/dcm2niix/issues/125) for Siemens images where PE is in the Column direction.
- - Sort diffusion volumes by [B-value amplitude](https://www.nitrc.org/forum/forum.php?thread_id=8396&forum_id=4703) (use "-d n"/"-d y" to turn the feature off/on).
- - BIDS tag [TotalReadoutTime](https://github.com/rordenlab/dcm2niix/issues/130) handles partial fourier, Phase Resolution, etc (Michael Harms).
- - Additional [json fields](https://github.com/rordenlab/dcm2niix/issues/127).
-
-18-Aug-2017
- - Better BVec extraction for  [PAR/REC 4.1](https://www.nitrc.org/forum/forum.php?thread_id=8387&forum_id=4703).
- - Support for [Segami Cerescan volumes](https://www.nitrc.org/forum/forum.php?thread_id=8076&forum_id=4703).
-
-24-July-2017
- - Compiles with recent releases of [OpenJPEG](https://github.com/neurolabusc/dcm_qa/issues/5#issuecomment-317443179) for JPEG2000 support.
-
-23-June-2017
- - [Ensure slice timing always encoded for Siemens EPI](https://github.com/neurolabusc/dcm_qa/issues/4#issuecomment-310707906)
- - [Integrates validation](https://github.com/neurolabusc/dcm_qa)
- - JSON fix (InstitutionName -> InstitutionAddress)
-
-21-June-2017
- - Read DICOM header in 1Mb segments rather than loading whole file : reduces ram usage and [faster for systems with slow io](https://github.com/rordenlab/dcm2niix/issues/104).
- - Report [TotalReadoutTime](https://github.com/rordenlab/dcm2niix/issues/98).
- - Fix JPEG2000 support in [Superbuild](https://github.com/rordenlab/dcm2niix/issues/105).
-
-28-May-2017
- - Remove all derived images from [Philips DTI series](http://www.nitrc.org/forum/message.php?msg_id=21025).
- - Provide some [Siemens EPI sequence details](https://github.com/rordenlab/dcm2niix/issues).
-
-28-April-2017
- - Experimental [ECAT support](https://github.com/rordenlab/dcm2niix/issues/95).
- - Updated cmake to make JPEG2000 support easier with improved Travis and AppVeyor support [Ningfei Li](https://github.com/ningfei).
- - Supports Data/Time for images that report Data/Time (0008,002A) but not separate Date and Time (0008,0022 and 0008,0032).
- - [BIDS reports morning times correctly](http://www.nitrc.org/forum/message.php?msg_id=20852).
- - Options -1..-9 to control [gz compression level](https://github.com/rordenlab/dcm2niix/issues/90).
- - Includes some [PET details in the BIDS JSON sidecar](https://github.com/rordenlab/dcm2niix/issues/87).
- - Better detection of image order for Philips 4D DICOM (reported by Jason McMorrow and Stephen Wilson).
- - [Include StudyInstanceUID and SeriesInstanceUID in filename](https://github.com/rordenlab/dcm2niix/issues/94).
-
-7-Feb-2017
- - Can be compiled to use either Philips [Float or Display](http://www.nitrc.org/forum/message.php?msg_id=20213) intensity intercept and slope values.
- - Handle 3D Philips DICOM and [PAR/REC](https://www.nitrc.org/forum/forum.php?thread_id=7707&forum_id=4703) files where images are not stored in a spatially contiguous order.
- - Handle DICOM violations where icon is uncompressed but image data is compressed.
- - Best guess matrix for 2D slices (similar to dcm2nii, SPM and MRIconvert).
- - Linux (case sensitive filenames) now handles par/rec as well as PAR/REC.
- - Images with unknown phase encoding do not generate [BIDS entry](https://github.com/rordenlab/dcm2niix/issues/79).
- - Unified printMessage/printWarning/printError aids embedding in other projects, such as [divest](https://github.com/jonclayden/divest).
-
-1-Nov-2016
- - AppVeyor Support (Ningfei Li & Chris Filo Gorgolewski)
- - Swap 3rd/4th dimensions for GE sequential multi-phase acquisitions (Niels Janssen).
-
-10-Oct-2016
- - Restores/improves building for the Windows operating system using MinGW.
-
-30-Sept-2016
- - Save ImageType (0x0008,0x0008) to BIDS.
- - Separate CT scans with different exposures.
- - Fixed issues where some compilers would generate erratic filenames for zero-padded series (e.g. "-f %3s").
-
-21-Sept-2016
- - Reduce verbosity (reduce number of repeated warnings, less scary warnings for derived rather than raw images).
- - Re-enable custom output directory "-o" option broken by 30-Apr-2016 version.
- - Deal with mis-behaved GE CT images where slice direction across images is not consistent.
- - Add new BIDS fields (field strength, manufacturer, etc).
- - Philips PAR/REC conversion now reports inconsistent requested vs measured TR (due to prospect. motion corr.?).
- - GE: Locations In Acquisition (0054, 0081) is inaccurate if slices are interpolated, use Images In Acquisition (0020,1002) if available.
- - New filename options %d Series description (0008,103E), %z Sequence Name (0018,0024).
- - New filename options %a antenna (coil) number, %e echo number.
- - Initialize unused portions of NIfTI header to zero so multiple runs always produce identical results.
- - Supports 3D lossless JPEG saved as [multiple fragments](http://www.nitrc.org/forum/forum.php?thread_id=5872&forum_id=4703).
-
-5-May-2016
- - Crop 3D T1 acquisitions (e.g. ./dcm2niix -x y ~/DICOM).
-
-30-Apr-2016
- - Convert multiple files/folders with single command line invocation (e.g. ./dcm2niix -b y ~/tst ~/tst2).
-
-22-Apr-2016
- - Detect Siemens Phase maps (phase image names end with "_ph").
- - Use current working directory if file name not specified.
-
-12-Apr-2016
- - Provide override (command line option "-m y") to stack images of the same series even if they differ in study date/time, echo/coil number, or slice orientation. This mechanism allows users to concatenate images that break strict DICOM compliance.
-
-22-Mar-2016
- - Experimental support for [DICOM datasets without DICOM file meta information](http://dicom.nema.org/dicom/2013/output/chtml/part10/chapter_7.html).
-
-12-Dec-2015
- - Support PAR/REC FP values when possible (see PMC3998685).
-
-11-Nov-2015
- - Minor refinements.
-
-12-June-2015
- - Uses less memory (helpful for large datasets).
-
-2-Feb-2015
- - Support for Visual Studio.
- - Remove dependency on zlib (now uses miniz).
-
-1-Jan-2015
- - Images separated based on TE (fieldmaps).
- - Support for JPEG2000 using OpenJPEG or Jasper libraries.
- - Support for JPEG using NanoJPEG library.
- - Support for lossless JPEG using custom library.
-
-24-Nov-2014
- - Support for CT scans with gantry tilt and varying distance between slices.
-
-11-Oct-2014
- - Initial public release.
+[See the VERSIONS.md file for details on releases](./VERSIONS.md).
 
 ## Running
 
 Command line usage is described in the [NITRC wiki](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#General_Usage). The minimal command line call would be `dcm2niix /path/to/dicom/folder`. However, you may want to invoke additional options, for example the call `dcm2niix -z y -f %p_%t_%s -o /path/ouput /path/to/dicom/folder` will save data as gzip compressed, with the filename based on the protocol name (%p) acquisition time (%t) and DICOM series number (%s), with all file [...]
 
-**Optional batch processing version:**
-
-Perform a batch conversion of multiple dicoms using the configurations specified in a yaml file.
-```bash
-dcm2niibatch batch_config.yml
-```
-
-The configuration file should be in yaml format as shown in example `batch_config.yaml`
-
-```yaml
-Options:
-  isGz:             false
-  isFlipY:          false
-  isVerbose:        false
-  isCreateBIDS:     false
-  isOnlySingleFile: false
-Files:
-    -
-      in_dir:           /path/to/first/folder
-      out_dir:          /path/to/output/folder
-      filename:         dcemri
-    -
-      in_dir:           /path/to/second/folder
-      out_dir:          /path/to/output/folder
-      filename:         fa3
-```
-
-You can add as many files as you want to convert as long as this structure stays consistent. Note that a dash must separate each file.
+[See the BATCH.md file for instructions on using the batch processing version](./BATCH.md).
 
 ## Build
 
@@ -189,14 +53,11 @@ make
 
 **optional batch processing version:**
 
-The batch processing binary `dcm2niibatch` is optional. To build `dcm2niibatch` as well change the cmake command to `cmake -DBATCH_VERSION=ON ..`
-
-This requires a compiler that supports c++11.
-
+The batch processing binary `dcm2niibatch` is optional. To build `dcm2niibatch` as well change the cmake command to `cmake -DBATCH_VERSION=ON ..`. This requires a compiler that supports c++11.
 
 ### Building the command line version without cmake
 
-[See the COMPILE.md file for details on manual compilation](./COMPILE.md).
+If you have any problems with the cmake build script described above or want to customize the software see the [COMPILE.md file for details on manual compilation](./COMPILE.md).
 
 ## Links
 
@@ -209,6 +70,7 @@ This requires a compiler that supports c++11.
   - [dcm2niir](https://github.com/muschellij2/dcm2niir) R wrapper for dcm2niix/dcm2nii.
   - [divest](https://github.com/jonclayden/divest) R interface to dcm2niix.
   - [sci-tran dcm2niix](https://github.com/scitran-apps/dcm2niix) docker.
-  - [neuro_docker](https://github.com/Neurita/neuro_docker) includes dcm2niix.
+  - [neuro_docker](https://github.com/Neurita/neuro_docker) includes dcm2niix as part of a provides a single, static Dockerfile.
+  - [neurodocker](https://github.com/kaczmarj/neurodocker) generates [custom](https://github.com/rordenlab/dcm2niix/issues/138) Dockerfiles given specific versions of neuroimaging software.
   - [dcm2niix_afni](https://afni.nimh.nih.gov/pub/dist/doc/program_help/dcm2niix_afni.html) is a version of dcm2niix included with the [AFNI](https://afni.nimh.nih.gov/) distribution.
   - [MRIcroGL](https://github.com/neurolabusc/MRIcroGL) is available for MacOS, Linux and Windows and provides a graphical interface for dcm2niix. You can get compiled copies from the [MRIcroGL NITRC web site](https://www.nitrc.org/projects/mricrogl/).
\ No newline at end of file
diff --git a/README.md b/VERSIONS.md
similarity index 52%
copy from README.md
copy to VERSIONS.md
index 3411e16..43ef2d4 100644
--- a/README.md
+++ b/VERSIONS.md
@@ -1,21 +1,6 @@
-[![Build Status](https://travis-ci.org/rordenlab/dcm2niix.svg?branch=master)](https://travis-ci.org/rordenlab/dcm2niix)
-[![Build status](https://ci.appveyor.com/api/projects/status/7o0xp2fgbhadkgn1?svg=true)](https://ci.appveyor.com/project/neurolabusc/dcm2niix)
-
-## About
-
-dcm2niix is a designed to convert neuroimaging data from the DICOM format to the NIfTI format. This web page hosts the developmental source code - a compiled version for Linux, MacOS, and Windows of the most recent stable release is included with [MRIcroGL](https://www.nitrc.org/projects/mricrogl/). A full manual for this software is available in the form of a [NITRC wiki](http://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage).
-
-## License
-
-This software is open source. The bulk of the code is covered by the BSD license. Some units are either public domain (nifti*.*, miniz.c) or use the MIT license (ujpeg.cpp). See the license.txt file for more details.
-
-## Dependencies
-
-This software should run on macOS, Linux and Windows without requiring any other software. However, if you use dcm2niix to create gz-compressed images it will be faster if you have [pigz](https://github.com/madler/pigz) installed. You can get a version of both dcm2niix and pigz compiled for your operating system by downloading [MRIcroGL](https://www.nitrc.org/projects/mricrogl/).
-
 ## Versions
 
-23-Sept-2017
+17-Oct-2017
  - Swap [phase-encoding direction polarity](https://github.com/rordenlab/dcm2niix/issues/125) for Siemens images where PE is in the Column direction.
  - Sort diffusion volumes by [B-value amplitude](https://www.nitrc.org/forum/forum.php?thread_id=8396&forum_id=4703) (use "-d n"/"-d y" to turn the feature off/on).
  - BIDS tag [TotalReadoutTime](https://github.com/rordenlab/dcm2niix/issues/130) handles partial fourier, Phase Resolution, etc (Michael Harms).
@@ -29,7 +14,7 @@ This software should run on macOS, Linux and Windows without requiring any other
  - Compiles with recent releases of [OpenJPEG](https://github.com/neurolabusc/dcm_qa/issues/5#issuecomment-317443179) for JPEG2000 support.
 
 23-June-2017
- - [Ensure slice timing always encoded for Siemens EPI](https://github.com/neurolabusc/dcm_qa/issues/4#issuecomment-310707906)
+ - [Ensure slice timing always reported for Siemens EPI](https://github.com/neurolabusc/dcm_qa/issues/4#issuecomment-310707906)
  - [Integrates validation](https://github.com/neurolabusc/dcm_qa)
  - JSON fix (InstitutionName -> InstitutionAddress)
 
@@ -46,7 +31,7 @@ This software should run on macOS, Linux and Windows without requiring any other
  - Experimental [ECAT support](https://github.com/rordenlab/dcm2niix/issues/95).
  - Updated cmake to make JPEG2000 support easier with improved Travis and AppVeyor support [Ningfei Li](https://github.com/ningfei).
  - Supports Data/Time for images that report Data/Time (0008,002A) but not separate Date and Time (0008,0022 and 0008,0032).
- - [BIDS reports morning times correctly](http://www.nitrc.org/forum/message.php?msg_id=20852).
+ - [BIDS reports SliceTiming correctly](http://www.nitrc.org/forum/message.php?msg_id=20852).
  - Options -1..-9 to control [gz compression level](https://github.com/rordenlab/dcm2niix/issues/90).
  - Includes some [PET details in the BIDS JSON sidecar](https://github.com/rordenlab/dcm2niix/issues/87).
  - Better detection of image order for Philips 4D DICOM (reported by Jason McMorrow and Stephen Wilson).
@@ -124,91 +109,4 @@ This software should run on macOS, Linux and Windows without requiring any other
  - Support for CT scans with gantry tilt and varying distance between slices.
 
 11-Oct-2014
- - Initial public release.
-
-## Running
-
-Command line usage is described in the [NITRC wiki](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#General_Usage). The minimal command line call would be `dcm2niix /path/to/dicom/folder`. However, you may want to invoke additional options, for example the call `dcm2niix -z y -f %p_%t_%s -o /path/ouput /path/to/dicom/folder` will save data as gzip compressed, with the filename based on the protocol name (%p) acquisition time (%t) and DICOM series number (%s), with all file [...]
-
-**Optional batch processing version:**
-
-Perform a batch conversion of multiple dicoms using the configurations specified in a yaml file.
-```bash
-dcm2niibatch batch_config.yml
-```
-
-The configuration file should be in yaml format as shown in example `batch_config.yaml`
-
-```yaml
-Options:
-  isGz:             false
-  isFlipY:          false
-  isVerbose:        false
-  isCreateBIDS:     false
-  isOnlySingleFile: false
-Files:
-    -
-      in_dir:           /path/to/first/folder
-      out_dir:          /path/to/output/folder
-      filename:         dcemri
-    -
-      in_dir:           /path/to/second/folder
-      out_dir:          /path/to/output/folder
-      filename:         fa3
-```
-
-You can add as many files as you want to convert as long as this structure stays consistent. Note that a dash must separate each file.
-
-## Build
-
-### Build command line version with cmake (Linux, MacOS, Windows)
-
-`cmake` and `pkg-config` (optional) can be installed as follows:
-
-Ubuntu: `sudo apt-get install cmake pkg-config`
-
-MacOS: `brew install cmake pkg-config`
-
-**To build:**
-```bash
-mkdir build && cd build
-cmake ..
-make
-```
-`dcm2niix` will be created in the `bin` subfolder. To install on the system run `make install`.
-
-**optional building with OpenJPEG:**
-
-Support for JPEG2000 using OpenJPEG is optional. To build with OpenJPEG change the cmake command to `cmake -DUSE_OPENJPEG=ON ..`:
-
-```bash
-mkdir build && cd build
-cmake -DUSE_OPENJPEG=ON ..
-make
-```
-
-**optional batch processing version:**
-
-The batch processing binary `dcm2niibatch` is optional. To build `dcm2niibatch` as well change the cmake command to `cmake -DBATCH_VERSION=ON ..`
-
-This requires a compiler that supports c++11.
-
-
-### Building the command line version without cmake
-
-[See the COMPILE.md file for details on manual compilation](./COMPILE.md).
-
-## Links
-
-  - [Dcm2Bids](https://github.com/cbedetti/Dcm2Bids) uses dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
-  - [bidskit](https://github.com/jmtyszka/bidskit) uses dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
-  - [DAC2BIDS](https://github.com/dangom/dac2bids) uses dcm2niibatch to create [BIDS](http://bids.neuroimaging.io/) datasets.
-  - [heudiconv](https://github.com/nipy/heudiconv) can use dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
-  - [nipype](https://github.com/nipy/nipype) can use dcm2niix to convert images.
-  - [pydcm2niix is a Python module for working with dcm2niix](https://github.com/jstutters/pydcm2niix).
-  - [dcm2niir](https://github.com/muschellij2/dcm2niir) R wrapper for dcm2niix/dcm2nii.
-  - [divest](https://github.com/jonclayden/divest) R interface to dcm2niix.
-  - [sci-tran dcm2niix](https://github.com/scitran-apps/dcm2niix) docker.
-  - [neuro_docker](https://github.com/Neurita/neuro_docker) includes dcm2niix.
-  - [dcm2niix_afni](https://afni.nimh.nih.gov/pub/dist/doc/program_help/dcm2niix_afni.html) is a version of dcm2niix included with the [AFNI](https://afni.nimh.nih.gov/) distribution.
-  - [MRIcroGL](https://github.com/neurolabusc/MRIcroGL) is available for MacOS, Linux and Windows and provides a graphical interface for dcm2niix. You can get compiled copies from the [MRIcroGL NITRC web site](https://www.nitrc.org/projects/mricrogl/).
\ No newline at end of file
+ - Initial public release.
\ No newline at end of file
diff --git a/console/nii_dicom.cpp b/console/nii_dicom.cpp
index af3fbc2..a4f7451 100644
--- a/console/nii_dicom.cpp
+++ b/console/nii_dicom.cpp
@@ -624,17 +624,22 @@ int headerDcm2Nii2(struct TDICOMdata d, struct TDICOMdata d2, struct nifti_1_hea
         h->dim_info = (3 << 4) + (1 << 2) + 2;
     if (d.phaseEncodingRC =='C')
         h->dim_info = (3 << 4) + (2 << 2) + 1;
+    if (d.CSA.multiBandFactor > 1) {
+        char dtxt[1024] = {""};
+        sprintf(dtxt, ";mb=%d", d.CSA.multiBandFactor);
+        strcat(txt,dtxt);
+    }
     snprintf(h->descrip,80, "%s",txt);
     if (strlen(d.imageComments) > 0)
         snprintf(h->aux_file,24,"%s",d.imageComments);
     return headerDcm2NiiSForm(d,d2, h, isVerbose);
 } //headerDcm2Nii2()
 
-int dcmStrLen (int len) {
-    if (len < kDICOMStr)
+int dcmStrLen (int len, int kMaxLen) {
+    if (len < kMaxLen)
         return len+1;
     else
-        return kDICOMStr;
+        return kMaxLen;
 } //dcmStrLen()
 
 struct TDICOMdata clear_dicom_data() {
@@ -670,6 +675,7 @@ struct TDICOMdata clear_dicom_data() {
     strcpy(d.scanningSequence, "");
     strcpy(d.sequenceVariant, "");
     strcpy(d.manufacturersModelName, "");
+    strcpy(d.institutionalDepartmentName, "");
     strcpy(d.procedureStepDescription, "");
     strcpy(d.institutionName, "");
     strcpy(d.referringPhysicianName, "");
@@ -678,6 +684,7 @@ struct TDICOMdata clear_dicom_data() {
     strcpy(d.softwareVersions, "");
     strcpy(d.stationName, "");
     strcpy(d.scanOptions, "");
+    //strcpy(d.mrAcquisitionType, "");
     strcpy(d.seriesInstanceUID, "");
     strcpy(d.studyID, "");
     strcpy(d.studyInstanceUID, "");
@@ -699,13 +706,17 @@ struct TDICOMdata clear_dicom_data() {
     d.flipAngle = 0.0;
     d.bandwidthPerPixelPhaseEncode = 0.0;
     d.fieldStrength = 0.0;
+    d.SAR = 0.0;
+    d.pixelBandwidth = 0.0;
+    d.zSpacing = 0.0;
+    d.zThick = 0.0;
     d.numberOfDynamicScans = 0;
     d.echoNum = 1;
     d.echoTrainLength = 0;
     d.phaseFieldofView = 0.0;
     d.dwellTime = 0;
     d.phaseEncodingSteps = 0;
-    d.coilNum = 1;
+    d.coilNum = 0;
     d.accelFactPE = 0.0;
     d.patientPositionNumPhilips = 0;
     d.imageBytes = 0;
@@ -724,6 +735,7 @@ struct TDICOMdata clear_dicom_data() {
     d.imageNum = 1;
     d.imageStart = 0;
     d.is3DAcq = false; //e.g. MP-RAGE, SPACE, TFE
+    d.is2DAcq = false; //
     d.isSlicesSpatiallySequentialPhilips = true; //Philips can save slices in random order, e.g. 4,5,6,1,2,3
     d.isDerived = false; //0008,0008 = DERIVED,CSAPARALLEL,POSDISP
     d.isSegamiOasis = false; //these images do not store spatial coordinates
@@ -741,6 +753,10 @@ struct TDICOMdata clear_dicom_data() {
     d.isLittleEndian = true; //DICOM initially always little endian
     d.converted2NII = 0;
     d.phaseEncodingRC = '?';
+    d.patientSex = '?';
+    d.patientWeight = 0.0;
+    strcpy(d.patientBirthDate, "");
+    strcpy(d.patientAge, "");
     d.CSA.bandwidthPerPixelPhaseEncode = 0.0;
     d.CSA.mosaicSlices = 0;
     d.CSA.sliceNormV[1] = 1.0;
@@ -782,7 +798,7 @@ void dcmStrDigitsOnly(char* lStr) {
             lStr[i] = ' ';
 }
 
-void dcmStr(int lLength, unsigned char lBuffer[], char* lOut) {
+void dcmStr(int lLength, unsigned char lBuffer[], char* lOut, bool isStrLarge = false) {
     //char test[] = " 1     2    3    ";
     //lLength = (int)strlen(test);
 
@@ -835,8 +851,10 @@ void dcmStr(int lLength, unsigned char lBuffer[], char* lOut) {
     if (cString[len-1] == '_') len--;
     //while ((len > 0) && (cString[len]=='_')) len--; //remove trailing '_'
     cString[len] = 0; //null-terminate, strlcpy does this anyway
-    len = dcmStrLen(len);
-    if (len == kDICOMStr) { //we need space for null-termination
+    int maxLen = kDICOMStr;
+    if (isStrLarge) maxLen = kDICOMStrLarge;
+    len = dcmStrLen(len, maxLen);
+    if (len == maxLen) { //we need space for null-termination
 		if (cString[len-2] == '_') len = len -2;
 	}
     memcpy(lOut,cString,len-1);
@@ -1954,7 +1972,7 @@ unsigned char * nii_loadImgCore(char* imgname, struct nifti_1_header hdr, int bi
 	if (bitsAllocated == 12)
 	 conv12bit16bit(bImg, hdr);
     return bImg;
-} //nii_loadImg()
+} //nii_loadImgCore()
 
 unsigned char * nii_planar2rgb(unsigned char* bImg, struct nifti_1_header *hdr, int isPlanar) {
 	//DICOM data saved in triples RGBRGBRGB, NIfTI RGB saved in planes RRR..RGGG..GBBBB..B
@@ -2571,15 +2589,13 @@ unsigned char * nii_loadImgXL(char* imgname, struct nifti_1_header *hdr, struct
         if ((dcm.compressionScheme == kCompressYes) && (compressFlag != kCompressNone) )
             img = nii_loadImgCoreJasper(imgname, *hdr, dcm, compressFlag);
         else
-        #else
-        UNUSED(compressFlag); //avoid compiler -Wunused-parameter warning: compressFlag required when  myEnableJasper or not myDisableOpenJPEG
-        #endif
+       #endif
     #endif
-    if (dcm.compressionScheme == kCompressYes) {
+     if (dcm.compressionScheme == kCompressYes) {
         printMessage("Software not set up to decompress DICOM\n");
         return NULL;
     } else
-        img = nii_loadImgCore(imgname, *hdr, dcm.bitsAllocated);
+    	img = nii_loadImgCore(imgname, *hdr, dcm.bitsAllocated);
     if (img == NULL) return img;
     if ((dcm.compressionScheme == kCompressNone) && (dcm.isLittleEndian != littleEndianPlatform()) && (hdr->bitpix > 8))
         img = nii_byteswap(img, hdr);
@@ -2715,11 +2731,16 @@ struct TDICOMdata readDICOMv(char * fname, int isVerbose, int compressFlag, stru
 #define  kReferringPhysicianName 0x0008+(0x0090 << 16 )
 #define  kStationName 0x0008+(0x1010 << 16 )
 #define  kSeriesDescription 0x0008+(0x103E << 16 ) // '0008' '103E' 'LO' 'SeriesDescription'
+#define  kInstitutionalDepartmentName  0x0008+(0x1040 << 16 )
 #define  kManufacturersModelName 0x0008+(0x1090 << 16 )
 #define  kDerivationDescription 0x0008+(0x2111 << 16 )
 #define  kComplexImageComponent (uint32_t) 0x0008+(0x9208 << 16 )//'0008' '9208' 'CS' 'ComplexImageComponent'
 #define  kPatientName 0x0010+(0x0010 << 16 )
 #define  kPatientID 0x0010+(0x0020 << 16 )
+#define  kPatientBirthDate 0x0010+(0x0030 << 16 )
+#define  kPatientSex 0x0010+(0x0040 << 16 )
+#define  kPatientAge 0x0010+(0x1010 << 16 )
+#define  kPatientWeight 0x0010+(0x1030 << 16 )
 #define  kAnatomicalOrientationType 0x0010+(0x2210 << 16 )
 #define  kBodyPartExamined 0x0018+(0x0015 << 16)
 #define  kScanningSequence 0x0018+(0x0020 << 16)
@@ -2737,6 +2758,7 @@ struct TDICOMdata readDICOMv(char * fname, int isVerbose, int compressFlag, stru
 #define  kPhaseEncodingSteps  0x0018+(0x0089 << 16 ) //'IS'
 #define  kEchoTrainLength  0x0018+(0x0091 << 16 ) //IS
 #define  kPhaseFieldofView  0x0018+(0x0094 << 16 ) //'DS'
+#define  kPixelBandwidth  0x0018+(0x0095 << 16 ) //'DS' 'PixelBandwidth'
 #define  kDeviceSerialNumber  0x0018+(0x1000 << 16 ) //LO
 #define  kSoftwareVersions  0x0018+(0x1020 << 16 ) //LO
 #define  kProtocolName  0x0018+(0x1030<< 16 )
@@ -2748,6 +2770,7 @@ struct TDICOMdata readDICOMv(char * fname, int isVerbose, int compressFlag, stru
 #define  kAcquisitionMatrix  0x0018+(0x1310  << 16 ) //US
 #define  kFlipAngle  0x0018+(0x1314  << 16 )
 #define  kInPlanePhaseEncodingDirection  0x0018+(0x1312<< 16 ) //CS
+#define  kSAR  0x0018+(0x1316 << 16 ) //'DS' 'SAR'
 #define  kPatientOrient  0x0018+(0x5100<< 16 )    //0018,5100. patient orientation - 'HFS'
 //#define  kDiffusionBFactorSiemens  0x0019+(0x100C<< 16 ) //   0019;000C;SIEMENS MR HEADER  ;B_value
 #define  kDwellTime  0x0019+(0x1018<< 16 ) //IS in NSec, see https://github.com/rordenlab/dcm2niix/issues/127
@@ -2824,7 +2847,7 @@ uint32_t kNest = 0xFFFE +(0xE000 << 16 ); //#define kNest 0xFFFE +(0xE000 << 16
 uint32_t kUnnest = 0xFFFE +(0xE00D << 16 ); //#define  kUnnest  0xFFFE +(0xE00D << 16 ) //ItemDelimitationItem [length defined] http://www.dabsoft.ch/dicom/5/7.5/
 uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD << 16 )//SequenceDelimitationItem [length undefined]
     int nest = 0;
-    double zSpacing = -1.0l; //includes slice thickness plus gap
+    //double zSpacing = -1.0l; //includes slice thickness plus gap
     int locationsInAcquisitionGE = 0;
     int locationsInAcquisitionPhilips = 0;
     int imagesInAcquisition = 0;
@@ -3094,12 +3117,27 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
             case kPatientID :
                 dcmStr (lLength, &buffer[lPos], d.patientID);
                 break;
+            case kPatientBirthDate :
+              	dcmStr (lLength, &buffer[lPos], d.patientBirthDate);
+              	break;
+            case kPatientSex :
+            	d.patientSex = toupper(buffer[lPos]); //first character is either 'R'ow or 'C'ol
+                break;
+            case kPatientAge :
+                dcmStr (lLength, &buffer[lPos], d.patientAge);
+                break;
+        	case kPatientWeight :
+                d.patientWeight = dcmStrFloat(lLength, &buffer[lPos]);
+                break;
             case kStationName :
                 dcmStr (lLength, &buffer[lPos], d.stationName);
                 break;
             case kSeriesDescription: {
                 dcmStr (lLength, &buffer[lPos], d.seriesDescription);
                 break; }
+            case kInstitutionalDepartmentName:
+            	dcmStr (lLength, &buffer[lPos], d.institutionalDepartmentName);
+            	break;
             case kManufacturersModelName :
             	dcmStr (lLength, &buffer[lPos], d.manufacturersModelName);
             	break;
@@ -3190,6 +3228,9 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
             case kInPlanePhaseEncodingDirection:
                 d.phaseEncodingRC = toupper(buffer[lPos]); //first character is either 'R'ow or 'C'ol
                 break;
+            case kSAR:
+            	d.SAR = dcmStrFloat(lLength, &buffer[lPos]);
+            	break;
             case kStudyID:
             	dcmStr (lLength, &buffer[lPos], d.studyID);
             	break;
@@ -3229,7 +3270,7 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
                 dcmMultiFloat(lLength, (char*)&buffer[lPos], 2, d.xyzMM);
                 break;
             case kImageComments:
-                dcmStr (lLength, &buffer[lPos], d.imageComments);
+                dcmStr (lLength, &buffer[lPos], d.imageComments, true);
                 break;
             case kLocationsInAcquisitionGE:
                 locationsInAcquisitionGE = dcmInt(lLength,&buffer[lPos],d.isLittleEndian);
@@ -3262,7 +3303,7 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
                 d.fieldStrength =  dcmStrFloat(lLength, &buffer[lPos]);
                 break;
             case kZSpacing :
-                zSpacing = dcmStrFloat(lLength, &buffer[lPos]);
+                d.zSpacing = dcmStrFloat(lLength, &buffer[lPos]);
                 break;
             case kPhaseEncodingSteps :
                 d.phaseEncodingSteps =  dcmStrInt(lLength, &buffer[lPos]);
@@ -3273,6 +3314,9 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
             case kPhaseFieldofView :
             	d.phaseFieldofView = dcmStrFloat(lLength, &buffer[lPos]);
                 break;
+            case kPixelBandwidth :
+            	d.pixelBandwidth = dcmStrFloat(lLength, &buffer[lPos]);
+            	break;
         	case kAcquisitionMatrix :
 				if (lLength == 8) {
                 	uint16_t acquisitionMatrix[4];
@@ -3318,6 +3362,7 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
                 break;
             case kZThick :
                 d.xyzMM[3] = dcmStrFloat(lLength, &buffer[lPos]);
+                d.zThick = d.xyzMM[3];
                 break;
             case kCoilSiemens : {
                 if (d.manufacturer == kMANUFACTURER_SIEMENS) {
@@ -3356,9 +3401,9 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
                 d.numberOfDynamicScans =  dcmStrInt(lLength, &buffer[lPos]);
                 break;
             case	kMRAcquisitionType: //detect 3D acquisition: we can reorient these without worrying about slice time correct or BVEC/BVAL orientation
-            	#ifndef myDisableReorient3dToOrtho
+            	if (lLength > 1) d.is2DAcq = (buffer[lPos]=='2') && (toupper(buffer[lPos+1]) == 'D');
                 if (lLength > 1) d.is3DAcq = (buffer[lPos]=='3') && (toupper(buffer[lPos+1]) == 'D');
-                #endif
+                //dcmStr (lLength, &buffer[lPos], d.mrAcquisitionType);
                 break;
             case kBodyPartExamined : {
                 dcmStr (lLength, &buffer[lPos], d.bodyPartExamined);
@@ -3635,8 +3680,8 @@ uint32_t kUnnest2 = 0xFFFE +(0xE0DD << 16 ); //#define  kUnnest2 0xFFFE +(0xE0DD
         d.locationsInAcquisition = imagesInAcquisition; //e.g. if 72 slices acquired but interpolated as 144
     if ((d.manufacturer == kMANUFACTURER_GE) && (d.locationsInAcquisition == 0))
         d.locationsInAcquisition = locationsInAcquisitionGE;
-    if (zSpacing > 0)
-    	d.xyzMM[3] = zSpacing; //use zSpacing if provided: depending on vendor, kZThick may or may not include a slice gap
+    if (d.zSpacing > 0)
+    	d.xyzMM[3] = d.zSpacing; //use zSpacing if provided: depending on vendor, kZThick may or may not include a slice gap
     //printMessage("patientPositions = %d XYZT = %d slicePerVol = %d numberOfDynamicScans %d\n",patientPositionNum,d.xyzDim[3], d.locationsInAcquisition, d.numberOfDynamicScans);
     if ((d.manufacturer == kMANUFACTURER_PHILIPS) && (patientPositionNum > d.xyzDim[3]))
         printMessage("Please check slice thicknesses: Philips R3.2.2 bug can disrupt estimation (%d positions reported for %d slices)\n",patientPositionNum, d.xyzDim[3]); //Philips reported different positions for each slice!
diff --git a/console/nii_dicom.h b/console/nii_dicom.h
index f1f9e5c..9b32399 100644
--- a/console/nii_dicom.h
+++ b/console/nii_dicom.h
@@ -38,11 +38,12 @@ extern "C" {
 	#define kCCsuf " CompilerNA" //unknown compiler!
 #endif
 
-#define kDCMvers "v1.0.20170923" kDCMsuf kCCsuf
+#define kDCMvers "v1.0.20171017" kDCMsuf kCCsuf
 
 static const int kMaxEPI3D = 1024; //maximum number of EPI images in Siemens Mosaic
 static const int kMaxDTI4D = 4096; //maximum number of DTI directions for 4D (Philips) images, also maximum number of 3D slices for Philips 3D and 4D images
 #define kDICOMStr 64
+#define kDICOMStrLarge 256
 #define kMANUFACTURER_UNKNOWN  0
 #define kMANUFACTURER_SIEMENS  1
 #define kMANUFACTURER_GE  2
@@ -112,15 +113,17 @@ static const int kCompressRLE = 4; //run length encoding
         long seriesNum;
         int xyzDim[5];
         int modality, dwellTime, effectiveEchoSpacingGE, phaseEncodingLines, phaseEncodingSteps, echoTrainLength, patientPositionNumPhilips, coilNum, echoNum, sliceOrient,numberOfDynamicScans, manufacturer, converted2NII, acquNum, imageNum, imageStart, imageBytes, bitsStored, bitsAllocated, samplesPerPixel,patientPositionSequentialRepeats,locationsInAcquisition, compressionScheme;
-        float phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4];
+        float patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4];
         float orient[7], patientPosition[4], patientPositionLast[4], xyzMM[4], stackOffcentre[4];
         float radionuclidePositronFraction, radionuclideTotalDose, radionuclideHalfLife, doseCalibrationFactor; //PET ISOTOPE MODULE ATTRIBUTES (C.8-57)
 		float ecat_isotope_halflife, ecat_dosage;
         double dateTime, acquisitionTime, acquisitionDate, bandwidthPerPixelPhaseEncode;
-        bool isSegamiOasis, isDerived, isXRay, isMultiEcho, isSlicesSpatiallySequentialPhilips, isValid, is3DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase,isHasMagnitude,isHasMixed, isFloat, isResampled;
-        char phaseEncodingRC;
-        char scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionAddress[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patientName[kDICOMStr],seriesDescription[kDICOM [...]
+        //char mrAcquisitionType[kDICOMStr]
+        char scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionAddress[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], institutionalDepartmentName[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patient [...]
+        char imageComments[kDICOMStrLarge];
         struct TCSAdata CSA;
+        bool isSegamiOasis, isDerived, isXRay, isMultiEcho, isSlicesSpatiallySequentialPhilips, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase,isHasMagnitude,isHasMixed, isFloat, isResampled;
+        char phaseEncodingRC, patientSex;
     };
 
     size_t nii_ImgBytes(struct nifti_1_header hdr);
diff --git a/console/nii_dicom_batch.cpp b/console/nii_dicom_batch.cpp
index 55bfe23..e7ab697 100644
--- a/console/nii_dicom_batch.cpp
+++ b/console/nii_dicom_batch.cpp
@@ -93,8 +93,9 @@ void dropFilenameFromPath(char *path) { //
     if (strlen(path) == 0) { //file name did not specify path, assume relative path and return current working directory
     	//strcat (path,"."); //relative path - use cwd <- not sure if this works on Windows!
     	char cwd[1024];
-   		getcwd(cwd, sizeof(cwd));
-   		strcat (path,cwd);
+   		char* ok = getcwd(cwd, sizeof(cwd));
+   		if (ok !=NULL)
+   			strcat (path,cwd);
     }
 }
 
@@ -337,9 +338,9 @@ void nii_SaveText(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
     strcat (txtname,".txt");
     //printMessage("Saving text %s\n",txtname);
     FILE *fp = fopen(txtname, "w");
-    fprintf(fp, "%s\tField Strength:\t%g\tProtocolName:\t%s\tScanningSequence00180020:\t%s\tTE:\t%g\tTR:\t%g\tSeriesNum:\t%ld\tAcquNum:\t%d\tImageNum:\t%d\tImageComments:\t%s\tDateTime:\t%f\tName:\t%s\tConvVers:\t%s\tDoB:\t%s\tGender:\t%s\tAge:\t%s\tDimXYZT:\t%d\t%d\t%d\t%d\tCoil:\t%d\tEchoNum:\t%d\tOrient(6)\t%g\t%g\t%g\t%g\t%g\t%g\tbitsAllocated\t%d\tInputName\t%s\n",
+    fprintf(fp, "%s\tField Strength:\t%g\tProtocolName:\t%s\tScanningSequence00180020:\t%s\tTE:\t%g\tTR:\t%g\tSeriesNum:\t%ld\tAcquNum:\t%d\tImageNum:\t%d\tImageComments:\t%s\tDateTime:\t%f\tName:\t%s\tConvVers:\t%s\tDoB:\t%s\tGender:\t%c\tAge:\t%s\tDimXYZT:\t%d\t%d\t%d\t%d\tCoil:\t%d\tEchoNum:\t%d\tOrient(6)\t%g\t%g\t%g\t%g\t%g\t%g\tbitsAllocated\t%d\tInputName\t%s\n",
       pathoutname, d.fieldStrength, d.protocolName, d.scanningSequence, d.TE, d.TR, d.seriesNum, d.acquNum, d.imageNum, d.imageComments,
-      d.dateTime, d.patientName, kDCMvers, d.birthDate, d.gender, d.age, h->dim[1], h->dim[2], h->dim[3], h->dim[4],
+      d.dateTime, d.patientName, kDCMvers, d.patientBirthDate, d.patientSex, d.patientAge, h->dim[1], h->dim[2], h->dim[3], h->dim[4],
             d.coilNum,d.echoNum, d.orient[1], d.orient[2], d.orient[3], d.orient[4], d.orient[5], d.orient[6],
             d.bitsAllocated, dcmname);
     fclose(fp);
@@ -490,19 +491,25 @@ int phoenixOffsetCSASeriesHeader(unsigned char *buff, int lLength) {
     return 0;
 } // phoenixOffsetCSASeriesHeader()
 
-void siemensCsaAscii(const char * filename,  int csaOffset, int csaLength, float* phaseOversampling, float* phaseResolution, int* baseResolution, int* interp, int* partialFourier, int* echoSpacing, int* parallelReductionFactorInPlane, char* coilID, char* consistencyInfo, char* coilElements, char* pulseSequenceDetails, char* fmriExternalInfo) {
+void siemensCsaAscii(const char * filename,  int csaOffset, int csaLength, float* delayTimeInTR, float* phaseOversampling, float* phaseResolution, float* txRefAmp, float* shimSetting, int* baseResolution, int* interp, int* partialFourier, int* echoSpacing, int* parallelReductionFactorInPlane, char* coilID, char* consistencyInfo, char* coilElements, char* pulseSequenceDetails, char* fmriExternalInfo, char * protocolName) {
  //reads ASCII portion of CSASeriesHeaderInfo and returns lEchoTrainDuration or lEchoSpacing value
  // returns 0 if no value found
+ 	*delayTimeInTR = 0.0;
  	*phaseOversampling = 0.0;
  	*phaseResolution = 0.0;
+ 	*txRefAmp = 0.0;
  	*baseResolution = 0;
  	*interp = 0;
  	*partialFourier = 0;
  	*echoSpacing = 0;
+ 	for (int i = 0; i < 8; i++)
+ 		shimSetting[i] = 0.0;
  	strcpy(coilID, "");
  	strcpy(consistencyInfo, "");
  	strcpy(coilElements, "");
  	strcpy(pulseSequenceDetails, "");
+ 	strcpy(fmriExternalInfo, "");
+ 	strcpy(protocolName, "");
  	if ((csaOffset < 0) || (csaLength < 8)) return;
 	FILE * pFile = fopen ( filename, "rb" );
 	if(pFile==NULL) return;
@@ -557,10 +564,41 @@ void siemensCsaAscii(const char * filename,  int csaOffset, int csaLength, float
 		readKeyStr(keyStrSeq,  keyPos, csaLengthTrim, pulseSequenceDetails);
 		char keyStrExt[] = "FmriExternalInfo";
 		readKeyStr(keyStrExt,  keyPos, csaLengthTrim, fmriExternalInfo);
-		char keyStrPhase[] = "sKSpace.dPhaseResolution";
-		*phaseResolution = readKeyFloat(keyStrPhase, keyPos, csaLengthTrim);
+		char keyStrPn[] = "tProtocolName";
+		readKeyStr(keyStrPn,  keyPos, csaLengthTrim, protocolName);
+		char keyStrDelay[] = "lDelayTimeInTR";
+		*delayTimeInTR = readKeyFloat(keyStrDelay, keyPos, csaLengthTrim);
 		char keyStrOver[] = "sKSpace.dPhaseOversamplingForDialog";
 		*phaseOversampling = readKeyFloat(keyStrOver, keyPos, csaLengthTrim);
+		char keyStrPhase[] = "sKSpace.dPhaseResolution";
+		*phaseResolution = readKeyFloat(keyStrPhase, keyPos, csaLengthTrim);
+		char keyStrAmp[] = "sTXSPEC.asNucleusInfo[0].flReferenceAmplitude";
+		*txRefAmp = readKeyFloat(keyStrAmp, keyPos, csaLengthTrim);
+		//lower order shims: newer sequences
+		char keyStrSh0[] = "sGRADSPEC.asGPAData[0].lOffsetX";
+		shimSetting[0] = readKeyFloat(keyStrSh0, keyPos, csaLengthTrim);
+		char keyStrSh1[] = "sGRADSPEC.asGPAData[0].lOffsetY";
+		shimSetting[1] = readKeyFloat(keyStrSh1, keyPos, csaLengthTrim);
+		char keyStrSh2[] = "sGRADSPEC.asGPAData[0].lOffsetZ";
+		shimSetting[2] = readKeyFloat(keyStrSh2, keyPos, csaLengthTrim);
+		//lower order shims: older sequences
+		char keyStrSh0s[] = "sGRADSPEC.lOffsetX";
+		if (shimSetting[0] == 0.0) shimSetting[0] = readKeyFloat(keyStrSh0s, keyPos, csaLengthTrim);
+		char keyStrSh1s[] = "sGRADSPEC.lOffsetY";
+		if (shimSetting[1] == 0.0) shimSetting[1] = readKeyFloat(keyStrSh1s, keyPos, csaLengthTrim);
+		char keyStrSh2s[] = "sGRADSPEC.lOffsetZ";
+		if (shimSetting[2] == 0.0) shimSetting[2] = readKeyFloat(keyStrSh2s, keyPos, csaLengthTrim);
+		//higher order shims: older sequences
+		char keyStrSh3[] = "sGRADSPEC.alShimCurrent[0]";
+		shimSetting[3] = readKeyFloat(keyStrSh3, keyPos, csaLengthTrim);
+		char keyStrSh4[] = "sGRADSPEC.alShimCurrent[1]";
+		shimSetting[4] = readKeyFloat(keyStrSh4, keyPos, csaLengthTrim);
+		char keyStrSh5[] = "sGRADSPEC.alShimCurrent[2]";
+		shimSetting[5] = readKeyFloat(keyStrSh5, keyPos, csaLengthTrim);
+		char keyStrSh6[] = "sGRADSPEC.alShimCurrent[3]";
+		shimSetting[6] = readKeyFloat(keyStrSh6, keyPos, csaLengthTrim);
+		char keyStrSh7[] = "sGRADSPEC.alShimCurrent[4]";
+		shimSetting[7] = readKeyFloat(keyStrSh7, keyPos, csaLengthTrim);
 	}
 	fclose (pFile);
 	free (buffer);
@@ -641,6 +679,7 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 	};
 	json_Str(fp, "\t\"ManufacturersModelName\": \"%s\",\n", d.manufacturersModelName);
 	json_Str(fp, "\t\"InstitutionName\": \"%s\",\n", d.institutionName);
+	json_Str(fp, "\t\"InstitutionalDepartmentName\": \"%s\",\n", d.institutionalDepartmentName);
 	json_Str(fp, "\t\"InstitutionAddress\": \"%s\",\n", d.institutionAddress);
 	json_Str(fp, "\t\"DeviceSerialNumber\": \"%s\",\n", d.deviceSerialNumber );
 	json_Str(fp, "\t\"StationName\": \"%s\",\n", d.stationName );
@@ -650,12 +689,20 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 		json_Str(fp, "\t\"ReferringPhysicianName\": \"%s\",\n", d.referringPhysicianName);
 		json_Str(fp, "\t\"StudyID\": \"%s\",\n", d.studyID);
 		//Next lines directly reveal patient identity
-		// json_Str(fp, "\t\"PatientName\": \"%s\",\n", d.patientName);
-		// json_Str(fp, "\t\"PatientID\": \"%s\",\n", d.patientID);
+		json_Str(fp, "\t\"PatientName\": \"%s\",\n", d.patientName);
+		json_Str(fp, "\t\"PatientID\": \"%s\",\n", d.patientID);
+		if (d.patientSex != '?') fprintf(fp, "\t\"PatientSex\": \"%c\",\n",  d.patientSex);
+		json_Float(fp, "\t\"PatientWeight\": %g,\n", d.patientWeight);
+		//d.patientBirthDate //convert from DICOM  YYYYMMDD to JSON
+		//d.patientAge //4-digit Age String: nnnD, nnnW, nnnM, nnnY;
 	}
 	json_Str(fp, "\t\"BodyPartExamined\": \"%s\",\n", d.bodyPartExamined);
+	json_Str(fp, "\t\"PatientPosition\": \"%s\",\n", d.patientOrient);  // 0018,5100 = PatientPosition in DICOM
 	json_Str(fp, "\t\"ProcedureStepDescription\": \"%s\",\n", d.procedureStepDescription);
 	json_Str(fp, "\t\"SoftwareVersions\": \"%s\",\n", d.softwareVersions);
+	//json_Str(fp, "\t\"MRAcquisitionType\": \"%s\",\n", d.mrAcquisitionType);
+	if (d.is2DAcq)  fprintf(fp, "\t\"MRAcquisitionType\": \"2D\",\n");
+	if (d.is3DAcq)  fprintf(fp, "\t\"MRAcquisitionType\": \"3D\",\n");
 	json_Str(fp, "\t\"SeriesDescription\": \"%s\",\n", d.seriesDescription);
 	json_Str(fp, "\t\"ProtocolName\": \"%s\",\n", d.protocolName);
 	json_Str(fp, "\t\"ScanningSequence\": \"%s\",\n", d.scanningSequence);
@@ -678,6 +725,7 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 	}
 	if (d.isDerived) //DICOM is derived image or non-spatial file (sounds, etc)
 		fprintf(fp, "\t\"RawImage\": false,\n");
+	if (d.seriesNum > 0) fprintf(fp, "\t\"SeriesNumber\": %ld,\n", d.seriesNum);
 	//Chris Gorgolewski: BIDS standard specifies ISO8601 date-time format (Example: 2016-07-06T12:49:15.679688)
 	//Lines below directly save DICOM values
 	if (d.acquisitionTime > 0.0 && d.acquisitionDate > 0.0){
@@ -726,6 +774,12 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 	//CT parameters
 	if ((d.TE > 0.0) && (d.isXRay)) fprintf(fp, "\t\"XRayExposure\": %g,\n", d.TE );
     //MRI parameters
+    if (!d.isXRay) { //with CT scans, slice thickness often varies
+    	//beware, not used correctly by all vendors https://public.kitware.com/pipermail/insight-users/2005-September/014711.html
+    	json_Float(fp, "\t\"SliceThickness\": %g,\n", d.zThick );
+    	json_Float(fp, "\t\"SpacingBetweenSlices\": %g,\n", d.zSpacing);
+    }
+	json_Float(fp, "\t\"SAR\": %g,\n", d.SAR );
 	if (d.echoNum > 1) fprintf(fp, "\t\"EchoNumber\": %d,\n", d.echoNum);
 	if ((d.TE > 0.0) && (!d.isXRay)) fprintf(fp, "\t\"EchoTime\": %g,\n", d.TE / 1000.0 );
     json_Float(fp, "\t\"RepetitionTime\": %g,\n", d.TR / 1000.0 );
@@ -737,9 +791,9 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 	#ifdef myReadAsciiCsa
 	if ((d.manufacturer == kMANUFACTURER_SIEMENS) && (d.CSA.SeriesHeader_offset > 0) && (d.CSA.SeriesHeader_length > 0)) {
 		int baseResolution, interpInt, partialFourier, echoSpacing, parallelReductionFactorInPlane;
-		float phaseResolution;
-		char fmriExternalInfo[kDICOMStr], coilID[kDICOMStr], consistencyInfo[kDICOMStr], coilElements[kDICOMStr], pulseSequenceDetails[kDICOMStr];
-		siemensCsaAscii(filename,  d.CSA.SeriesHeader_offset, d.CSA.SeriesHeader_length, &phaseOversampling, &phaseResolution, &baseResolution, &interpInt, &partialFourier, &echoSpacing, &parallelReductionFactorInPlane, coilID, consistencyInfo, coilElements, pulseSequenceDetails, fmriExternalInfo);
+		float delayTimeInTR, phaseResolution, txRefAmp, shimSetting[8];
+		char protocolName[kDICOMStr], fmriExternalInfo[kDICOMStr], coilID[kDICOMStr], consistencyInfo[kDICOMStr], coilElements[kDICOMStr], pulseSequenceDetails[kDICOMStr];
+		siemensCsaAscii(filename,  d.CSA.SeriesHeader_offset, d.CSA.SeriesHeader_length, &delayTimeInTR, &phaseOversampling, &phaseResolution, &txRefAmp, shimSetting, &baseResolution, &interpInt, &partialFourier, &echoSpacing, &parallelReductionFactorInPlane, coilID, consistencyInfo, coilElements, pulseSequenceDetails, fmriExternalInfo, protocolName);
 		if (partialFourier > 0) {
 			//https://github.com/ismrmrd/siemens_to_ismrmrd/blob/master/parameter_maps/IsmrmrdParameterMap_Siemens_EPI_FLASHREF.xsl
 			if (partialFourier == 1) pf = 0.5; // 4/8
@@ -753,6 +807,20 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 			fprintf(fp, "\t\"Interpolation2D\": %d,\n", interp);
 		}
 		if (baseResolution > 0) fprintf(fp, "\t\"BaseResolution\": %d,\n", baseResolution );
+		if (shimSetting[0] != 0.0) {
+			fprintf(fp, "\t\"ShimSetting\": [\n");
+			for (int i = 0; i < 8; i++) {
+				if (i != 0)
+					fprintf(fp, ",\n");
+				fprintf(fp, "\t\t%g", shimSetting[i]);
+			}
+			fprintf(fp, "\t],\n");
+		}
+		//DelayTimeInTR
+		// https://groups.google.com/forum/#!topic/bids-discussion/nmg1BOVH1SU
+		// https://groups.google.com/forum/#!topic/bids-discussion/seD7AtJfaFE
+		json_Float(fp, "\t\"DelayTime\": %g,\n", delayTimeInTR/ 1000000.0); //DelayTimeInTR usec -> sec
+		json_Float(fp, "\t\"TxRefAmp\": %g,\n", txRefAmp);
 		json_Float(fp, "\t\"PhaseResolution\": %g,\n", phaseResolution);
 		json_Float(fp, "\t\"PhaseOversampling\": %g,\n", phaseOversampling); //usec -> sec
 		json_Float(fp, "\t\"VendorReportedEchoSpacing\": %g,\n", echoSpacing / 1000000.0); //usec -> sec
@@ -763,6 +831,8 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 		json_Str(fp, "\t\"ReceiveCoilActiveElements\": \"%s\",\n", coilElements);
 		json_Str(fp, "\t\"PulseSequenceDetails\": \"%s\",\n", pulseSequenceDetails);
 		json_Str(fp, "\t\"FmriExternalInfo\": \"%s\",\n", fmriExternalInfo);
+		if (strlen(d.protocolName) < 1)  //insert protocol name if it exists in CSA but not DICOM header: https://github.com/nipy/heudiconv/issues/80
+			json_Str(fp, "\t\"ProtocolName\": \"%s\",\n", protocolName);
 		json_Str(fp, "\t\"ConsistencyInfo\": \"%s\",\n", consistencyInfo);
 		if (parallelReductionFactorInPlane > 0) {//AccelFactorPE -> phase encoding
 			if (d.accelFactPE < 1.0) { //value not found in DICOM header, but WAS found in CSA ascii
@@ -797,7 +867,6 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 			reconMatrixPE = h->dim[1];
     }
 	if (reconMatrixPE > 0) fprintf(fp, "\t\"ReconMatrixPE\": %d,\n", reconMatrixPE );
-
     double bandwidthPerPixelPhaseEncode = d.bandwidthPerPixelPhaseEncode;
     if (bandwidthPerPixelPhaseEncode == 0.0)
     	bandwidthPerPixelPhaseEncode = 	d.CSA.bandwidthPerPixelPhaseEncode;
@@ -839,6 +908,7 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
     if ((reconMatrixPE > 0) && (effectiveEchoSpacing > 0.0))
 	  fprintf(fp, "\t\"TotalReadoutTime\": %g,\n", effectiveEchoSpacing * (reconMatrixPE - 1.0));
 
+    json_Float(fp, "\t\"PixelBandwidth\": %g,\n", d.pixelBandwidth );
 	if ((d.manufacturer == kMANUFACTURER_SIEMENS) && (d.dwellTime > 0))
 		fprintf(fp, "\t\"DwellTime\": %g,\n", d.dwellTime * 1E-9);
 	// Phase encoding polarity
@@ -874,6 +944,16 @@ void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts,
 		}
 		fprintf(fp, "\t],\n");
 	}
+	//DICOM orientation and phase encoding: useful for 3D undistortion. Original DICOM values: DICOM not NIfTI space, ignores if 3D image re-oriented
+	fprintf(fp, "\t\"ImageOrientationPatientDICOM\": [\n");
+	for (int i = 1; i < 7; i++) {
+		if (i != 1)
+			fprintf(fp, ",\n");
+		fprintf(fp, "\t\t%g", d.orient[i]);
+	}
+	fprintf(fp, "\t],\n");
+	if (d.phaseEncodingRC == 'C') fprintf(fp, "\t\"InPlanePhaseEncodingDirectionDICOM\": \"COL\",\n" );
+	if (d.phaseEncodingRC == 'R') fprintf(fp, "\t\"InPlanePhaseEncodingDirectionDICOM\": \"ROW\",\n" );
 	// Finish up with info on the conversion tool
 	fprintf(fp, "\t\"ConversionSoftware\": \"dcm2niix\",\n");
 	fprintf(fp, "\t\"ConversionSoftwareVersion\": \"%s\"\n", kDCMvers );
@@ -1744,7 +1824,9 @@ int nii_saveNII(char * niiFilename, struct nifti_1_header hdr, unsigned char* im
     		} else
     			printMessage("compression failed %s\n",command);
     	#else //if win else linux
-        system(command);
+        int ret = system(command);
+        if (ret == -1)
+        	printWarning("Failed to execute: %s\n",command);
         #endif //else linux
         printMessage("compress: %s\n",command);
     }
@@ -2182,6 +2264,7 @@ void checkSliceTiming(struct TDICOMdata * d, struct TDICOMdata * d1) {
 		if (d->CSA.sliceTiming[i] > maxT) maxT = d->CSA.sliceTiming[i];
 	}
 	if ((minT != maxT) && (maxT <= d->TR)) return; //looks fine
+	if ((minT == maxT) && (d->is3DAcq)) return; //fine: 3D EPI
 	if ((minT == maxT) && (d->CSA.multiBandFactor == d->CSA.mosaicSlices)) return; //fine: all slices single excitation
 	if ((strlen(d->seriesDescription) > 0) && (strstr(d->seriesDescription, "SBRef") != NULL))  return; //fine: single-band calibration data, the slice timing WILL exceed the TR
 	//check if 2nd image has valud slice timing
@@ -2355,6 +2438,7 @@ int saveDcm2Nii(int nConvert, struct TDCMsort dcmSort[],struct TDICOMdata dcmLis
         free(imgM);
         return EXIT_FAILURE;
     }
+    checkSliceTiming(&dcmList[indx0], &dcmList[indx1]);
     int sliceDir = 0;
     if (hdr0.dim[3] > 1)sliceDir = headerDcm2Nii2(dcmList[dcmSort[0].indx],dcmList[dcmSort[nConvert-1].indx] , &hdr0, true);
 	//UNCOMMENT NEXT TWO LINES TO RE-ORDER MOSAIC WHERE CSA's protocolSliceNumber does not start with 1
@@ -2367,7 +2451,7 @@ int saveDcm2Nii(int nConvert, struct TDCMsort dcmSort[],struct TDICOMdata dcmLis
         imgM = nii_flipZ(imgM, &hdr0);
         sliceDir = abs(sliceDir); //change this, we have flipped the image so GE DTI bvecs no longer need to be flipped!
     }
-    checkSliceTiming(&dcmList[indx0], &dcmList[indx1]);
+    //move before headerDcm2Nii2 checkSliceTiming(&dcmList[indx0], &dcmList[indx1]);
     //nii_SaveBIDS(pathoutname, dcmList[dcmSort[0].indx], opts, dti4D, &hdr0, nameList->str[dcmSort[0].indx]);
     nii_SaveBIDS(pathoutname, dcmList[dcmSort[0].indx], opts, &hdr0, nameList->str[dcmSort[0].indx]);
     if (opts.isOnlyBIDS) {
@@ -2521,17 +2605,17 @@ bool isSameSet (struct TDICOMdata d1, struct TDICOMdata d2, struct TDCMopts* opt
         warnings->bitDepthVaries = true;
         return false;
     }
-    if (opts->isForceStackSameSeries) {
-    	if ((d1.TE != d2.TE) || (d1.echoNum != d2.echoNum))
-    		*isMultiEcho = true;
-    	return true; //we will stack these images, even if they differ in the following attributes
-    }
     if (!isSameFloatDouble(d1.dateTime, d2.dateTime)) { //beware, some vendors incorrectly store Image Time (0008,0033) as Study Time (0008,0030).
     	if (!warnings->dateTimeVaries)
     		printMessage("slices not stacked: Study Data/Time (0008,0020 / 0008,0030) varies %12.12f ~= %12.12f\n", d1.dateTime, d2.dateTime);
     	warnings->dateTimeVaries = true;
     	return false;
     }
+    if (opts->isForceStackSameSeries) {
+    	if ((d1.TE != d2.TE) || (d1.echoNum != d2.echoNum))
+    		*isMultiEcho = true;
+    	return true; //we will stack these images, even if they differ in the following attributes
+    }
     if ((d1.TE != d2.TE) || (d1.echoNum != d2.echoNum)) {
         if ((!warnings->echoVaries) && (d1.isXRay)) //for CT/XRay we check DICOM tag 0018,1152 (XRayExposure)
         	printMessage("slices not stacked: X-Ray Exposure varies (exposure %g, %g; number %d, %d). Use 'merge 2D slices' option to force stacking\n", d1.TE, d2.TE,d1.echoNum, d2.echoNum );
@@ -3151,4 +3235,4 @@ void saveIniFile (struct TDCMopts opts) {
     fclose(fp);
 } //saveIniFile()
 
-#endif
\ No newline at end of file
+#endif
diff --git a/console/nii_foreign.cpp b/console/nii_foreign.cpp
index b1666d6..5219fc4 100644
--- a/console/nii_foreign.cpp
+++ b/console/nii_foreign.cpp
@@ -175,14 +175,24 @@ PACK( typedef struct {
     //read list matrix
     ecat_list_hdr lhdr;
     fseek(f, 512, SEEK_SET);
-    fread(&lhdr, sizeof(lhdr), 1, f);
+    size_t nRead = fread(&lhdr, sizeof(lhdr), 1, f);
+    if (nRead != 1) {
+        printMessage("Error reading ECAT file\n");
+        fclose(f);
+        return NULL;
+    }
     if (swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]);
     //offset to first image
     int img_StartBytes = lhdr.r[0][1] * 512;
     //load image header for first image
     fseek(f, img_StartBytes - 512, SEEK_SET); //image header is block immediately before image
     ecat_img_hdr ihdr;
-    fread(&ihdr, sizeof(ihdr), 1, f);
+    nRead = fread(&ihdr, sizeof(ihdr), 1, f);
+    if (nRead != 1) {
+        printMessage("Error reading ECAT file\n");
+        fclose(f);
+        return NULL;
+    }
     if (swapEndian) {
     	nifti_swap_2bytes(5, &ihdr.data_type);
         nifti_swap_4bytes(5, &ihdr.x_offset);
@@ -218,7 +228,12 @@ PACK( typedef struct {
     while ((lhdr.hdr[0]+lhdr.hdr[3]) == 31) { //while valid list
     	if (num_vol > 0) { //read the next list
     		fseek(f, 512 * (lhdr.hdr[1] -1), SEEK_SET);
-    		fread(&lhdr, 512, 1, f);
+    		nRead =fread(&lhdr, 512, 1, f);
+    		if (nRead != 1) {
+        		printMessage("Error reading ECAT file\n");
+        		fclose(f);
+        		return NULL;
+    		}
     		if (swapEndian) nifti_swap_4bytes(128, &lhdr.hdr[0]);
     	}
 		if ((lhdr.hdr[0]+lhdr.hdr[3]) != 31) break; //if valid list
@@ -226,7 +241,12 @@ PACK( typedef struct {
 		for (int k = 0; k < lhdr.hdr[3]; k++) {
     		//check images' ecat_img_hdr matches first
     		fseek(f, (lhdr.r[k][1]-1) * 512, SEEK_SET); //image header is block immediately before image
-    		fread(&ihdrN, sizeof(ihdrN), 1, f);
+    		nRead = fread(&ihdrN, sizeof(ihdrN), 1, f);
+    		if (nRead != 1) {
+        		printMessage("Error reading ECAT file\n");
+        		fclose(f);
+        		return NULL;
+    		}
     		if (swapEndian) {
 				nifti_swap_2bytes(5, &ihdrN.data_type);
 				nifti_swap_4bytes(5, &ihdrN.x_offset);
@@ -286,7 +306,12 @@ PACK( typedef struct {
 		float * img32 = (float*) img;
 		for (int v = 0; v < num_vol; v++) {
 			fseek(f, imgOffsets[v] * 512, SEEK_SET);
-			fread( &imgIn[0], 1, bytesPerVolumeIn, f);
+			nRead = fread( &imgIn[0], 1, bytesPerVolumeIn, f);
+    		if (nRead != 1) {
+        		printMessage("Error reading ECAT file\n");
+        		fclose(f);
+        		return NULL;
+    		}
 			if (swapEndian)
 				nifti_swap_2bytes(num_vox, imgIn);
 			int volOffset = v * num_vox;
diff --git a/old_nii_SaveBIDS.cpp b/old_nii_SaveBIDS.cpp
deleted file mode 100644
index a055e18..0000000
--- a/old_nii_SaveBIDS.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts, struct nifti_1_header *h, const char * filename) {
-//https://docs.google.com/document/d/1HFUkAEE-pB-angVcYe6pf_-fVf4sCpOHKesUvfb8Grc/edit#
-// Generate Brain Imaging Data Structure (BIDS) info
-// sidecar JSON file (with the same  filename as the .nii.gz file, but with .json extension).
-// we will use %g for floats since exponents are allowed
-// we will not set the locale, so decimal separator is always a period, as required
-//  https://www.ietf.org/rfc/rfc4627.txt
-	if (!opts.isCreateBIDS) return;
-	char txtname[2048] = {""};
-	strcpy (txtname,pathoutname);
-	strcat (txtname,".json");
-	FILE *fp = fopen(txtname, "w");
-	fprintf(fp, "{\n");
-	switch (d.modality) {
-		case kMODALITY_CR:
-			fprintf(fp, "\t\"Modality\": \"CR\",\n" );
-			break;
-		case kMODALITY_CT:
-			fprintf(fp, "\t\"Modality\": \"CT\",\n" );
-			break;
-		case kMODALITY_MR:
-			fprintf(fp, "\t\"Modality\": \"MR\",\n" );
-			break;
-		case kMODALITY_PT:
-			fprintf(fp, "\t\"Modality\": \"PT\",\n" );
-			break;
-		case kMODALITY_US:
-			fprintf(fp, "\t\"Modality\": \"US\",\n" );
-			break;
-	};
-	switch (d.manufacturer) {
-		case kMANUFACTURER_SIEMENS:
-			fprintf(fp, "\t\"Manufacturer\": \"Siemens\",\n" );
-			break;
-		case kMANUFACTURER_GE:
-			fprintf(fp, "\t\"Manufacturer\": \"GE\",\n" );
-			break;
-		case kMANUFACTURER_PHILIPS:
-			fprintf(fp, "\t\"Manufacturer\": \"Philips\",\n" );
-			break;
-		case kMANUFACTURER_TOSHIBA:
-			fprintf(fp, "\t\"Manufacturer\": \"Toshiba\",\n" );
-			break;
-	};
-	fprintf(fp, "\t\"ManufacturersModelName\": \"%s\",\n", d.manufacturersModelName );
-	if (!opts.isAnonymizeBIDS) {
-		if (strlen(d.seriesInstanceUID) > 0)
-			fprintf(fp, "\t\"SeriesInstanceUID\": \"%s\",\n", d.seriesInstanceUID );
-		if (strlen(d.studyInstanceUID) > 0)
-			fprintf(fp, "\t\"StudyInstanceUID\": \"%s\",\n", d.studyInstanceUID );
-		if (strlen(d.referringPhysicianName) > 0)
-			fprintf(fp, "\t\"ReferringPhysicianName\": \"%s\",\n", d.referringPhysicianName );
-		if (strlen(d.studyID) > 0)
-			fprintf(fp, "\t\"StudyID\": \"%s\",\n", d.studyID );
-		//Next lines directly reveal patient identity
-		//if (strlen(d.patientName) > 0)
-		//	fprintf(fp, "\t\"PatientName\": \"%s\",\n", d.patientName );
-		//if (strlen(d.patientID) > 0)
-		//	fprintf(fp, "\t\"PatientID\": \"%s\",\n", d.patientID );
-	}
-	#ifdef myReadAsciiCsa
-	if ((d.manufacturer == kMANUFACTURER_SIEMENS) && (d.CSA.SeriesHeader_offset > 0) && (d.CSA.SeriesHeader_length > 0)) {
-		//&& (strlen(d.scanningSequence) > 1) && (d.scanningSequence[0] == 'E') && (d.scanningSequence[1] == 'P')) { //for EPI scans only
-		int partialFourier, echoSpacing, echoTrainDuration, epiFactor, parallelReductionFactorInPlane;
-		char fmriExternalInfo[kDICOMStr], coilID[kDICOMStr], consistencyInfo[kDICOMStr], coilElements[kDICOMStr], pulseSequenceDetails[kDICOMStr];
-		epiFactor = siemensCsaAscii(filename,  d.CSA.SeriesHeader_offset, d.CSA.SeriesHeader_length, &partialFourier, &echoSpacing, &echoTrainDuration, &parallelReductionFactorInPlane, coilID, consistencyInfo, coilElements, pulseSequenceDetails, fmriExternalInfo);
-		//printMessage("ES %d ETD %d EPI %d\n", echoSpacing, echoTrainDuration, epiFactor);
-		if (partialFourier > 0) {
-			//https://github.com/ismrmrd/siemens_to_ismrmrd/blob/master/parameter_maps/IsmrmrdParameterMap_Siemens_EPI_FLASHREF.xsl
-			float pf = 1.0f;
-			if (partialFourier == 1) pf = 0.5;
-			if (partialFourier == 2) pf = 0.75;
-			if (partialFourier == 4) pf = 0.875;
-			fprintf(fp, "\t\"PartialFourier\": %g,\n", pf);
-		}
-		if (echoSpacing > 0)
-			 fprintf(fp, "\t\"EchoSpacing\": %g,\n", echoSpacing / 1000000.0); //usec -> sec
-		if (echoTrainDuration > 0)
-			 fprintf(fp, "\t\"EchoTrainDuration\": %g,\n", echoTrainDuration / 1000000.0); //usec -> sec
-		if (epiFactor > 0)
-			 fprintf(fp, "\t\"EPIFactor\": %d,\n", epiFactor);
-		if (strlen(coilID) > 0)
-			fprintf(fp, "\t\"ReceiveCoilName\": \"%s\",\n", coilID);
-		if (strlen(coilElements) > 0)
-			fprintf(fp, "\t\"ReceiveCoilActiveElements\": \"%s\",\n", coilElements);
-		if (strlen(pulseSequenceDetails) > 0)
-			fprintf(fp, "\t\"PulseSequenceDetails\": \"%s\",\n", pulseSequenceDetails);
-		if (strlen(fmriExternalInfo) > 0)
-			fprintf(fp, "\t\"FmriExternalInfo\": \"%s\",\n", fmriExternalInfo);
-		if (strlen(consistencyInfo) > 0)
-			fprintf(fp, "\t\"ConsistencyInfo\": \"%s\",\n", consistencyInfo);
-		if (parallelReductionFactorInPlane > 0) {//AccelFactorPE -> phase encoding
-			if (d.accelFactPE < 1.0) d.accelFactPE = parallelReductionFactorInPlane; //value found in ASCII but not in DICOM (0051,1011)
-			if (parallelReductionFactorInPlane != round(d.accelFactPE))
-				printWarning("ParallelReductionFactorInPlane reported in DICOM [0051,1011] (%g) does not match CSA series value %g\n", round(d.accelFactPE), parallelReductionFactorInPlane);
-		}
-	}
-	#endif
-	if (d.CSA.multiBandFactor > 1) //AccelFactorSlice
-		fprintf(fp, "\t\"MultibandAccelerationFactor\": %d,\n", d.CSA.multiBandFactor);
-	if (strlen(d.imageComments) > 0)
-		fprintf(fp, "\t\"ImageComments\": \"%s\",\n", d.imageComments);
-	if (strlen(opts.imageComments) > 0)
-		fprintf(fp, "\t\"ConversionComments\": \"%s\",\n", opts.imageComments);
-	if (d.echoTrainLength > 1) //>1 as for Siemens EPI this is 1, Siemens uses EPI factor http://mriquestions.com/echo-planar-imaging.html
-		fprintf(fp, "\t\"EchoTrainLength\": %d,\n", d.echoTrainLength);
-	if (d.echoNum > 1)
-		fprintf(fp, "\t\"EchoNumber\": %d,\n", d.echoNum);
-	if (d.isDerived) //DICOM is derived image or non-spatial file (sounds, etc)
-		fprintf(fp, "\t\"RawImage\": false,\n");
-	if (d.acquNum > 0)
-		fprintf(fp, "\t\"AcquisitionNumber\": %d,\n", d.acquNum);
-	if (strlen(d.institutionName) > 0)
-		fprintf(fp, "\t\"InstitutionName\": \"%s\",\n", d.institutionName );
-	if (strlen(d.institutionAddress) > 0)
-		fprintf(fp, "\t\"InstitutionAddress\": \"%s\",\n", d.institutionAddress );
-	if (strlen(d.deviceSerialNumber) > 0)
-		fprintf(fp, "\t\"DeviceSerialNumber\": \"%s\",\n", d.deviceSerialNumber );
-	if (strlen(d.stationName) > 0)
-		fprintf(fp, "\t\"StationName\": \"%s\",\n", d.stationName );
-	if (strlen(d.scanOptions) > 0)
-		fprintf(fp, "\t\"ScanOptions\": \"%s\",\n", d.scanOptions );
-	if (strlen(d.softwareVersions) > 0)
-		fprintf(fp, "\t\"SoftwareVersions\": \"%s\",\n", d.softwareVersions );
-	if (strlen(d.procedureStepDescription) > 0)
-		fprintf(fp, "\t\"ProcedureStepDescription\": \"%s\",\n", d.procedureStepDescription );
-	if (strlen(d.scanningSequence) > 0)
-		fprintf(fp, "\t\"ScanningSequence\": \"%s\",\n", d.scanningSequence );
-	if (strlen(d.sequenceVariant) > 0)
-		fprintf(fp, "\t\"SequenceVariant\": \"%s\",\n", d.sequenceVariant );
-	if (strlen(d.seriesDescription) > 0)
-		fprintf(fp, "\t\"SeriesDescription\": \"%s\",\n", d.seriesDescription );
-	if (strlen(d.bodyPartExamined) > 0)
-		fprintf(fp, "\t\"BodyPartExamined\": \"%s\",\n", d.bodyPartExamined );
-	if (strlen(d.protocolName) > 0)
-		fprintf(fp, "\t\"ProtocolName\": \"%s\",\n", d.protocolName );
-	if (strlen(d.sequenceName) > 0)
-		fprintf(fp, "\t\"SequenceName\": \"%s\",\n", d.sequenceName );
-	if (strlen(d.imageType) > 0) {
-		fprintf(fp, "\t\"ImageType\": [\"");
-		bool isSep = false;
-		for (int i = 0; i < strlen(d.imageType); i++) {
-			if (d.imageType[i] != '_') {
-				if (isSep)
-		  			fprintf(fp, "\", \"");
-				isSep = false;
-				fprintf(fp, "%c", d.imageType[i]);
-			} else
-				isSep = true;
-		}
-		fprintf(fp, "\"],\n");
-	}
-	//Chris Gorgolewski: BIDS standard specifies ISO8601 date-time format (Example: 2016-07-06T12:49:15.679688)
-	//Lines below directly save DICOM values
-	if (d.acquisitionTime > 0.0 && d.acquisitionDate > 0.0){
-		long acquisitionDate = d.acquisitionDate;
-		double acquisitionTime = d.acquisitionTime;
-		char acqDateTimeBuf[64];
-		//snprintf(acqDateTimeBuf, sizeof acqDateTimeBuf, "%+08ld%+08f", acquisitionDate, acquisitionTime);
-		snprintf(acqDateTimeBuf, sizeof acqDateTimeBuf, "%+08ld%+013.5f", acquisitionDate, acquisitionTime); //CR 20170404 add zero pad so 1:23am appears as +012300.00000 not +12300.00000
-		//printMessage("acquisitionDateTime %s\n",acqDateTimeBuf);
-		int ayear,amonth,aday,ahour,amin;
-		double asec;
-		int count = 0;
-		sscanf(acqDateTimeBuf, "%5d%2d%2d%3d%2d%lf%n", &ayear, &amonth, &aday, &ahour, &amin, &asec, &count);  //CR 20170404 %lf not %f for double precision
-		//printf("-%02d-%02dT%02d:%02d:%02.6f\",\n", amonth, aday, ahour, amin, asec);
-		if (count) { // ISO 8601 specifies a sign must exist for distant years.
-			//report time of the day only format, https://www.cs.tut.fi/~jkorpela/iso8601.html
-			fprintf(fp, "\t\"AcquisitionTime\": \"%02d:%02d:%02.6f\",\n",ahour, amin, asec);
-			//report date and time together
-			if (!opts.isAnonymizeBIDS) {
-				fprintf(fp, "\t\"AcquisitionDateTime\": ");
-				fprintf(fp, (ayear >= 0 && ayear <= 9999) ? "\"%4d" : "\"%+4d", ayear);
-				fprintf(fp, "-%02d-%02dT%02d:%02d:%02.6f\",\n", amonth, aday, ahour, amin, asec);
-
-			}
-		} //if (count)
-	} //if acquisitionTime and acquisitionDate recorded
-	// if (d.acquisitionTime > 0.0) fprintf(fp, "\t\"AcquisitionTime\": %f,\n", d.acquisitionTime );
-	// if (d.acquisitionDate > 0.0) fprintf(fp, "\t\"AcquisitionDate\": %8.0f,\n", d.acquisitionDate );
-	//if conditionals: the following values are required for DICOM MRI, but not available for CT
-	if ((d.intenScalePhilips != 0) || (d.manufacturer == kMANUFACTURER_PHILIPS)) { //for details, see PhilipsPrecise()
-		fprintf(fp, "\t\"PhilipsRescaleSlope\": %g,\n", d.intenScale );
-		fprintf(fp, "\t\"PhilipsRescaleIntercept\": %g,\n", d.intenIntercept );
-		fprintf(fp, "\t\"PhilipsScaleSlope\": %g,\n", d.intenScalePhilips );
-		fprintf(fp, "\t\"UsePhilipsFloatNotDisplayScaling\": %d,\n", opts.isPhilipsFloatNotDisplayScaling);
-	}
-	//PET ISOTOPE MODULE ATTRIBUTES
-	if (d.radionuclidePositronFraction > 0.0) fprintf(fp, "\t\"RadionuclidePositronFraction\": %g,\n", d.radionuclidePositronFraction );
-	if (d.radionuclideTotalDose > 0.0) fprintf(fp, "\t\"RadionuclideTotalDose\": %g,\n", d.radionuclideTotalDose );
-	if (d.radionuclideHalfLife > 0.0) fprintf(fp, "\t\"RadionuclideHalfLife\": %g,\n", d.radionuclideHalfLife );
-	if (d.doseCalibrationFactor > 0.0) fprintf(fp, "\t\"DoseCalibrationFactor\": %g,\n", d.doseCalibrationFactor );
-	//MRI parameters
-	if (d.fieldStrength > 0.0) fprintf(fp, "\t\"MagneticFieldStrength\": %g,\n", d.fieldStrength );
-	if (d.flipAngle > 0.0) fprintf(fp, "\t\"FlipAngle\": %g,\n", d.flipAngle );
-	if ((d.TE > 0.0) && (!d.isXRay)) fprintf(fp, "\t\"EchoTime\": %g,\n", d.TE / 1000.0 );
-    if ((d.TE > 0.0) && (d.isXRay)) fprintf(fp, "\t\"XRayExposure\": %g,\n", d.TE );
-    if (d.TR > 0.0) fprintf(fp, "\t\"RepetitionTime\": %g,\n", d.TR / 1000.0 );
-    if (d.TI > 0.0) fprintf(fp, "\t\"InversionTime\": %g,\n", d.TI / 1000.0 );
-    if (d.ecat_isotope_halflife > 0.0) fprintf(fp, "\t\"IsotopeHalfLife\": %g,\n", d.ecat_isotope_halflife);
-    if (d.ecat_dosage > 0.0) fprintf(fp, "\t\"Dosage\": %g,\n", d.ecat_dosage);
-    double bandwidthPerPixelPhaseEncode = d.bandwidthPerPixelPhaseEncode;
-    int phaseEncodingLines = d.phaseEncodingLines;
-    if ((phaseEncodingLines == 0) &&  (h->dim[2] > 0) && (h->dim[1] > 0)) {
-		if  (h->dim[2] == h->dim[2]) //phase encoding does not matter
-			phaseEncodingLines = h->dim[2];
-		else if (d.phaseEncodingRC =='R')
-			phaseEncodingLines = h->dim[2];
-		else if (d.phaseEncodingRC =='C')
-			phaseEncodingLines = h->dim[1];
-    }
-    if (bandwidthPerPixelPhaseEncode == 0.0)
-    	bandwidthPerPixelPhaseEncode = 	d.CSA.bandwidthPerPixelPhaseEncode;
-    if (phaseEncodingLines > 0.0) fprintf(fp, "\t\"PhaseEncodingLines\": %d,\n", phaseEncodingLines );
-    if (bandwidthPerPixelPhaseEncode > 0.0)
-    	fprintf(fp, "\t\"BandwidthPerPixelPhaseEncode\": %g,\n", bandwidthPerPixelPhaseEncode );
-    double effectiveEchoSpacing = 0.0;
-    if ((phaseEncodingLines > 0) && (bandwidthPerPixelPhaseEncode > 0.0))
-    	effectiveEchoSpacing = 1.0 / (bandwidthPerPixelPhaseEncode * phaseEncodingLines) ;
-    if (d.effectiveEchoSpacingGE > 0.0)
-    	effectiveEchoSpacing = d.effectiveEchoSpacingGE / 1000000.0;
-    if (effectiveEchoSpacing > 0.0)
-    		fprintf(fp, "\t\"EffectiveEchoSpacing\": %g,\n", effectiveEchoSpacing);
-    //FSL definition is start of first line until start of last line, so n-1 unless accelerated in-plane acquisition
-    // to check: partial Fourier, iPAT, etc.
-	int fencePost = 1;
-    if (d.accelFactPE > 1.0)
-    	fencePost = (int)round(d.accelFactPE); //e.g. if 64 lines with iPAT=2, we want time from start of first until start of 62nd effective line
-    if ((d.phaseEncodingSteps > 1) && (effectiveEchoSpacing > 0.0))
-		fprintf(fp, "\t\"TotalReadoutTime\": %g,\n", effectiveEchoSpacing * ((float)d.phaseEncodingSteps - fencePost));
-    if (d.accelFactPE > 1.0) {
-    		fprintf(fp, "\t\"ParallelReductionFactorInPlane\": %g,\n", d.accelFactPE);
-    		if (effectiveEchoSpacing > 0.0)
-    			fprintf(fp, "\t\"TrueEchoSpacing\": %g,\n", effectiveEchoSpacing * d.accelFactPE);
-	}
-	if ((d.manufacturer == kMANUFACTURER_SIEMENS) && (d.dwellTime > 0))
-		fprintf(fp, "\t\"DwellTime\": %g,\n", d.dwellTime * 1E-9);
-	if (d.CSA.sliceTiming[0] >= 0.0) {
-   		fprintf(fp, "\t\"SliceTiming\": [\n");
-   		for (int i = 0; i < kMaxEPI3D; i++) {
-   			if (d.CSA.sliceTiming[i] < 0.0) break;
-			if (i != 0)
-				fprintf(fp, ",\n");
-			fprintf(fp, "\t\t%g", d.CSA.sliceTiming[i] / 1000.0 );
-		}
-		fprintf(fp, "\t],\n");
-	}
-	if (((d.phaseEncodingRC == 'R') || (d.phaseEncodingRC == 'C')) &&  (!d.is3DAcq) && ((d.CSA.phaseEncodingDirectionPositive == 1) || (d.CSA.phaseEncodingDirectionPositive == 0))) {
-		if (d.phaseEncodingRC == 'C') //Values should be "R"ow, "C"olumn or "?"Unknown
-			fprintf(fp, "\t\"PhaseEncodingDirection\": \"j");
-		else if (d.phaseEncodingRC == 'R')
-				fprintf(fp, "\t\"PhaseEncodingDirection\": \"i");
-		else
-			fprintf(fp, "\t\"PhaseEncodingDirection\": \"?");
-		//phaseEncodingDirectionPositive has one of three values: UNKNOWN (-1), NEGATIVE (0), POSITIVE (1)
-		//However, DICOM and NIfTI are reversed in the j (ROW) direction
-		//Equivalent to dicm2nii's "if flp(iPhase), phPos = ~phPos; end"
-		//for samples see https://github.com/rordenlab/dcm2niix/issues/125
-		if (d.CSA.phaseEncodingDirectionPositive == -1)
-			fprintf(fp, "?"); //unknown
-		else if ((d.CSA.phaseEncodingDirectionPositive == 0) && (d.phaseEncodingRC != 'C'))
-			fprintf(fp, "-");
-		else if ((d.phaseEncodingRC == 'C') && (d.CSA.phaseEncodingDirectionPositive == 1) && (opts.isFlipY))
-			fprintf(fp, "-");
-		else if ((d.phaseEncodingRC == 'C') && (d.CSA.phaseEncodingDirectionPositive == 0) && (!opts.isFlipY))
-			fprintf(fp, "-");
-		fprintf(fp, "\",\n");
-	} //only save PhaseEncodingDirection if BOTH direction and POLARITY are known
-	fprintf(fp, "\t\"ConversionSoftware\": \"dcm2niix\",\n");
-	fprintf(fp, "\t\"ConversionSoftwareVersion\": \"%s\"\n", kDCMvers );
-	//fprintf(fp, "\t\"DicomConversion\": [\"dcm2niix\", \"%s\"]\n", kDCMvers );
-    fprintf(fp, "}\n");
-    fclose(fp);
-}// nii_SaveBIDS()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/dcm2niix.git



More information about the debian-med-commit mailing list