[ismrmrd] 17/281: Now supporting ISMRMRD Image format too

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:00:50 UTC 2015


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

ghisvail-guest pushed a commit to annotated tag ismrmrd0.5
in repository ismrmrd.

commit dec2ac59e67946c963f2991b939188fffc31871c
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date:   Wed Aug 29 15:00:09 2012 -0400

    Now supporting ISMRMRD Image format too
---
 CMakeLists.txt   |   4 +-
 README.html      | 258 ++++++++++++++++++++++++++++++++++++++++++-------------
 doc/README.rst   | 134 +++++++++++++++++++++++++----
 ismrmrd.h        | 248 ++++++++++++++++++++++++++++++----------------------
 ismrmrd_hdf5.cpp |  20 +++++
 ismrmrd_hdf5.h   |  37 ++++++++
 6 files changed, 521 insertions(+), 180 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0e7a4b3..2196ec7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,14 +7,12 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
 find_package(XSD REQUIRED)
 find_package(XercesC REQUIRED)
 find_package(Boost REQUIRED)
-find_package(HDF5 1.8 COMPONENTS C CXX HL REQUIRED)
+find_package(HDF5 1.8 COMPONENTS C CXX REQUIRED)
 
 #Process the XSD files
 SET(XSDS schema/ismrmrd.xsd)
 SET(XSD_ARGS cxx-tree --generate-serialization --export-symbol EXPORTISMRMRD --hxx-prologue-file ${CMAKE_SOURCE_DIR}/ismrmrd_export.h)
-
 WRAP_XSD(XSDS_SOURCES XSD_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/schema ${XSDS} OPTIONS ${XSD_ARGS})
-
 INCLUDE_DIRECTORIES(${XSD_INCLUDES} ${XERCESC_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${HDF5_INCLUDES})
 add_library(ismrmrd SHARED ismrmrd_hdf5.cpp ${XSDS_SOURCES})
 target_link_libraries(ismrmrd ${HDF5_LIBRARIES} ${XERCESC_LIBRARIES})
diff --git a/README.html b/README.html
index b2914af..c6bbf7b 100644
--- a/README.html
+++ b/README.html
@@ -317,18 +317,49 @@ ul.auto-toc {
 <div class="document" id="ismrm-raw-data-format-ismrmrd">
 <h1 class="title">ISMRM Raw Data Format (ISMRMRD)</h1>
 
+<div class="contents topic" id="contents">
+<p class="topic-title first">Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#preamble" id="id1">Preamble</a></li>
+<li><a class="reference internal" href="#obtaining-and-installing" id="id2">Obtaining and Installing</a><ul>
+<li><a class="reference internal" href="#dependencies" id="id3">Dependencies</a></li>
+<li><a class="reference internal" href="#linux-installation" id="id4">Linux installation</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#change-log" id="id5">Change log</a></li>
+<li><a class="reference internal" href="#overview" id="id6">Overview</a><ul>
+<li><a class="reference internal" href="#flexible-data-header" id="id7">Flexible Data Header</a></li>
+<li><a class="reference internal" href="#fixed-data-structures" id="id8">Fixed Data structures</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#file-storage" id="id9">File Storage</a></li>
+<li><a class="reference internal" href="#c-support-library" id="id10">C++ Support Library</a></li>
+<li><a class="reference internal" href="#matlab-example-code-and-datasets" id="id11">Matlab Example Code and Datasets</a></li>
+<li><a class="reference internal" href="#appendix" id="id12">Appendix</a><ul>
+<li><a class="reference internal" href="#xml-schema-definition" id="id13">XML Schema Definition</a></li>
+<li><a class="reference internal" href="#frequently-asked-questions" id="id14">Frequently Asked Questions</a></li>
+</ul>
+</li>
+</ul>
+</div>
 <div class="section" id="preamble">
-<h1>Preamble</h1>
+<h1><a class="toc-backref" href="#id1">Preamble</a></h1>
 <p>A prerequisite for sharing magnetic resonance (imaging) reconstruction algorithms and code is a common raw data format. This document describes such a common raw data format and attempts to capture the data fields that are require to describe enough details about the magnetic resonance experiment to reconstruct images from the data.</p>
 <p>This standard was developed by a subcommittee of the ISMRM Sedona 2013 workshop. Comments and requests for additions/modifications can be sent to:</p>
 <ul class="simple">
-<li>Michael S. Hansen (michael.hansen AT nih DOT gov)</li>
+<li>Michael S. Hansen (michael DOT hansen AT nih DOT gov)</li>
 <li>Wally Block (wblock AT cae DOT wisc DOT edu)</li>
 <li>Mark Griswold (mag46 AT case DOT edu)</li>
 <li>Brian Hargreaves (bah AT stanford DOT edu)</li>
-<li>Peter Boernert (peter.boernert AT philips DOT com)</li>
+<li>Peter Boernert (peter DOT boernert AT philips DOT com)</li>
+<li>Sebastian Kozerke (kozerke AT biomed DOT ee DOT ethz DOT ch)</li>
+<li>Craig Meyer (cmeyer AT virginia DOT edu)</li>
+<li>Doug Noll (dnoll AT umich DOT edu)</li>
 <li>Jim Pipe (Jim.Pipe AT DignityHealth DOT org)</li>
 </ul>
+</div>
+<div class="section" id="obtaining-and-installing">
+<h1><a class="toc-backref" href="#id2">Obtaining and Installing</a></h1>
 <p>The source code, examples, and example datasets can be found on the ISMRM Raw Data Sourceforge <a class="reference external" href="http://sourceforge.net/projects/ismrmrd">website</a>.</p>
 <p>To download the source code, clone the git archive:</p>
 <pre class="literal-block">
@@ -338,20 +369,57 @@ git clone git://git.code.sf.net/p/ismrmrd/code ismrmrd-code
 <pre class="literal-block">
 wget https://sourceforge.net/projects/ismrmrd/files/src/ismrmrd_latest.zip
 </pre>
+<p>API Documentation can be found at <a class="reference external" href="http://ismrmrd.sourceforge.net/api">http://ismrmrd.sourceforge.net/api</a>.</p>
+<div class="section" id="dependencies">
+<h2><a class="toc-backref" href="#id3">Dependencies</a></h2>
+<p>The ISMRM Raw Data format is described by an XML <a class="reference internal" href="#schema">schema</a> and some C-style structs with fixed memory layout and as such does not have dependencies. However, it uses HDF5 files for storage and a C++ library for reading and writing the ISMRMRD files is included in this distribution. Furthermore, since the XML header is defined with an XML <a class="reference internal" href="#schema">schema</a>, we encourage using XML data binding when writi [...]
+<ul class="simple">
+<li>HDF5 (version 1.8 or higher) libraries. Available from <a class="reference external" href="http://www.hdfgroup.org/downloads/index.html">http://www.hdfgroup.org/downloads/index.html</a>.</li>
+<li>Boost (<a class="reference external" href="http://www.boost.org/">http://www.boost.org/</a>)</li>
+<li>CodeSynthesis XSD (<a class="reference external" href="http://www.codesynthesis.com/products/xsd/">http://www.codesynthesis.com/products/xsd/</a>)</li>
+<li>Xerces-C XML parser library (<a class="reference external" href="http://xerces.apache.org/xerces-c/">http://xerces.apache.org/xerces-c/</a>)</li>
+<li>Cmake build tool (<a class="reference external" href="http://www.cmake.org/">http://www.cmake.org/</a>)</li>
+<li>Doxygen if you would like to generate API documentation (<a class="reference external" href="http://www.doxygen.org">http://www.doxygen.org</a>)</li>
+<li>Git if you would like to use the source code archive (<a class="reference external" href="http://git-scm.com/">http://git-scm.com/</a>)</li>
+</ul>
+<div class="note">
+<p class="first admonition-title">Note</p>
+<p class="last">It is only necessary to install the dependencies if you wish to develop compiled C/C++ software, which uses the ISMRMRD format. The format can be read in Matlab without installing any additional software.</p>
+</div>
+</div>
+<div class="section" id="linux-installation">
+<h2><a class="toc-backref" href="#id4">Linux installation</a></h2>
+<p>The dependencies mentioned above should be included in most linux distributions. On Ubuntu you can install all required dependencies with:</p>
+<pre class="literal-block">
+sudo apt-get install libhdf5-serial-dev h5utils cmake cmake-curses-gui libboost-dev libxerces-c-dev xsdcxx doxygen git
+</pre>
+<p>After installation of dependencies, the library can be installed with:</p>
+<pre class="literal-block">
+git clone git://git.code.sf.net/p/ismrmrd/code ismrmrd-code
+cd ismrmrd-code/
+mkdir build
+cd build
+cmake ../
+make
+sudo make install
+</pre>
+<p>Last command will install the library in <tt class="docutils literal">/usr/local/ismrmrd</tt>.</p>
+</div>
 </div>
 <div class="section" id="change-log">
-<h1>Change log</h1>
+<h1><a class="toc-backref" href="#id5">Change log</a></h1>
 <p>August 2012 - First draft.</p>
 </div>
 <div class="section" id="overview">
-<h1>Overview</h1>
-<p>The raw data format combines a mix of flexible data structures (XML header) and fixed structures (equivalent to C-structs). A raw data set consist of 2 sections:</p>
+<h1><a class="toc-backref" href="#id6">Overview</a></h1>
+<p>The raw data format combines a mix of flexible data structures (XML header) and fixed structures (equivalent to C-structs). A raw data set consist mainly of 2 sections:</p>
 <ol class="arabic simple">
 <li>A flexible XML format document that can contain an arbitrary number of fields and accommodate everything from simple values (b-values, etc.) to entire vendor protocols, etc. This purpose of this XML document is to provide parameters that may be meaningful for some experiments but not for others. This XML format is defined by an XML Schema Definition file (ismrmrd.xsd).</li>
 <li>Raw data section. This section contains all the acquired data in the experiment. Each data item is preceded by a C-struct with encoding numbers, etc. Following this data header is a channel header and data for each acquired channel. The raw data headers are defined in a C/C++ header file (ismrmrd.h)</li>
 </ol>
+<p>In addition to these sections, the ISMRMRD format also specifies an image header for storing reconstructed images and the accompanying C++ library provides a convenient way of writing such images into HDF5 files along with generic arrays for storing less well defined data structures, e.g. coil sensitivity maps or other calibration data.</p>
 <div class="section" id="flexible-data-header">
-<h2>Flexible Data Header</h2>
+<h2><a class="toc-backref" href="#id7">Flexible Data Header</a></h2>
 <p>The flexible data structure is defined by the xml schema definition in <tt class="docutils literal">schema/ismrmrd.xsd</tt> (<a class="reference internal" href="#schema">schema</a> is included in appendix below).</p>
 <p>An example of an XML file for a Cartesian 3D acquisition could look like:</p>
 <pre class="literal-block">
@@ -449,50 +517,50 @@ wget https://sourceforge.net/projects/ismrmrd/files/src/ismrmrd_latest.zip
 </pre>
 </div>
 <div class="section" id="fixed-data-structures">
-<h2>Fixed Data structures</h2>
-<p>Each acquisition is preceded by the following fixed layout structure:</p>
+<h2><a class="toc-backref" href="#id8">Fixed Data structures</a></h2>
+<p>Each raw data acquisition is preceded by the following fixed layout structure:</p>
 <pre class="literal-block">
- struct AcquisitionHeader
- {
-   uint16_t           version;                        //First unsigned int indicates the version
-   uint64_t           flags;                          //bit field with flags
-   uint32_t           measurement_uid;                //Unique ID for the measurement
-   uint32_t           scan_counter;                   //Current acquisition number in the measurement
-   uint32_t           acquisition_time_stamp;         //Acquisition clock
-   uint32_t           physiology_time_stamp[3];       //Physiology time stamps, e.g. ecg, breating, etc. 
-   uint16_t           number_of_samples;              //Number of samples acquired
-   uint16_t           available_channels;             //Available coils
-   uint16_t           active_channels;                //Active coils on current acquisiton
-   uint64_t           channel_mask[16];               //Mask to indicate which channels are active. Support for 1024 channels
-   uint16_t           discard_pre;                    //Samples to be discarded at the beginning of acquisition
-   uint16_t           discard_post;                   //Samples to be discarded at the end of acquisition
-   uint16_t           center_sample;                  //Sample at the center of k-space
-   uint16_t           encoding_space_ref;             //Reference to an encoding space, typically only one per acquisition
-   uint16_t           trajectory_dimensions;          //Indicates the dimensionality of the trajectory vector (0 means no trajectory)
-   float              sample_time_us;                 //Time between samples in micro seconds, sampling BW
-   float              position[3];                    //Three-dimensional spatial offsets from isocenter
-   float              quaternion[4];                  //Angulation of acquisition
-   float              patient_table_position[3];      //Patient table off-center
-   EncodingCounters   idx;                            //Encoding loop counters, see above
-   int32_t            user_int[8];                    //Free user parameters
-   float              user_float[8];                  //Free user parameters
- }; 
+struct AcquisitionHeader
+{
+        uint16_t           version;                        /**< First unsigned int indicates the version */
+        uint64_t           flags;                          /**< bit field with flags */
+        uint32_t           measurement_uid;                /**< Unique ID for the measurement */
+        uint32_t           scan_counter;                   /**< Current acquisition number in the measurement */
+        uint32_t           acquisition_time_stamp;         /**< Acquisition clock */
+        uint32_t           physiology_time_stamp[3];       /**< Physiology time stamps, e.g. ecg, breating, etc. */
+        uint16_t           number_of_samples;              /**< Number of samples acquired */
+        uint16_t           available_channels;             /**< Available coils */
+        uint16_t           active_channels;                /**< Active coils on current acquisiton */
+        uint64_t           channel_mask[16];               /**< Mask to indicate which channels are active. Support for 1024 channels */
+        uint16_t           discard_pre;                    /**< Samples to be discarded at the beginning of acquisition */
+        uint16_t           discard_post;                   /**< Samples to be discarded at the end of acquisition */
+        uint16_t           center_sample;                  /**< Sample at the center of k-space */
+        uint16_t           encoding_space_ref;             /**< Reference to an encoding space, typically only one per acquisition */
+        uint16_t           trajectory_dimensions;          /**< Indicates the dimensionality of the trajectory vector (0 means no trajectory) */
+        float              sample_time_us;                 /**< Time between samples in micro seconds, sampling BW */
+        float              position[3];                    /**< Three-dimensional spatial offsets from isocenter */
+        float              quaternion[4];                  /**< Angulation of acquisition */
+        float              patient_table_position[3];      /**< Patient table off-center */
+        EncodingCounters   idx;                            /**< Encoding loop counters, see above */
+        int32_t            user_int[8];                    /**< Free user parameters */
+        float              user_float[8];                  /**< Free user parameters */
+};
 
 </pre>
 <p>Where EncodingCounters are defined as:</p>
 <pre class="literal-block">
-  struct EncodingCounters {
-    uint16_t kspace_encode_step_1; //e.g. phase encoding line number
-    uint16_t kspace_encode_step_2; //e.g. partition encodning number
-    uint16_t average;              //e.g. signal average number
-    uint16_t slice;                //e.g. imaging slice number
-    uint16_t contrast;             //e.g. echo number in multi-echo
-    uint16_t phase;                //e.g. cardiac phase number
-    uint16_t repetition;           //e.g. dynamic number for dynamic scanning
-    uint16_t set;                  //e.g. flow encodning set
-    uint16_t segment;              //e.g. segment number for segmented acquisition
-    uint16_t user[8];              //Free user parameters
-  };
+struct EncodingCounters {
+        uint16_t kspace_encode_step_1; /**< e.g. phase encoding line number */
+        uint16_t kspace_encode_step_2; /**< e.g. partition encodning number */
+        uint16_t average;              /**< e.g. signal average number */
+        uint16_t slice;                /**< e.g. imaging slice number */
+        uint16_t contrast;             /**< e.g. echo number in multi-echo */
+        uint16_t phase;                /**< e.g. cardiac phase number */
+        uint16_t repetition;           /**< e.g. dynamic number for dynamic scanning */
+        uint16_t set;                  /**< e.g. flow encodning set */
+        uint16_t segment;              /**< e.g. segment number for segmented acquisition */
+        uint16_t user[8];              /**< Free user parameters */
+};
 
 </pre>
 <p>The interpretation of some of these fields may vary from sequence to sequence, i.e. for a Cartesian sequence, <tt class="docutils literal">kspace_encode_step_1</tt> would be the phase encoding step, for a spiral sequence where phase encoding direction does not make sense, it would be the spiral interleave number. The <tt class="docutils literal">encoding_space_ref</tt> enables the user to tie an acquisition to a specific encoding space (see above) in case there are multiple, e.g. in s [...]
@@ -517,10 +585,49 @@ float* data_;            //Actual data, elements = head_.number_of_samples*head_
 };
 </pre>
 <p>This suggested memory layout is only a suggestion. The HDF5 interface (see below) can be used to read the data into many different data structures. In fact, the user can choose to read only part of the header or not read the data, etc.</p>
+<p>As mentioned above, the ISMRMRD format also suggests a way to store reconstructed images (or maybe image data used for calibration). An <tt class="docutils literal">ImageHeader</tt> structure is defined in <tt class="docutils literal">ismrmrd.h</tt>:</p>
+<pre class="literal-block">
+struct ImageHeader
+{
+        uint16_t                version;                        /**< First unsigned int indicates the version */
+        uint64_t                flags;                          /**< bit field with flags */
+        uint32_t                measurement_uid;                /**< Unique ID for the measurement  */
+        uint16_t                matrix_size[3];                 /**< Pixels in the 3 spatial dimensions */
+        float                   field_of_view[3];               /**< Size (in mm) of the 3 spatial dimensions */
+        uint16_t                channels;                       /**< Number of receive channels */
+        float                   position[3];                    /**< Three-dimensional spatial offsets from isocenter */
+        float                   quaternion[4];                  /**< Angulation of acquisition */
+        float                   patient_table_position[3];      /**< Patient table off-center */
+        uint16_t                average;                        /**< e.g. signal average number */
+        uint16_t                slice;                          /**< e.g. imaging slice number */
+        uint16_t                contrast;                       /**< e.g. echo number in multi-echo */
+        uint16_t                phase;                          /**< e.g. cardiac phase number */
+        uint16_t                repetition;                     /**< e.g. dynamic number for dynamic scanning */
+        uint16_t                set;                            /**< e.g. flow encodning set */
+        uint32_t                acquisition_time_stamp;         /**< Acquisition clock */
+        uint32_t                physiology_time_stamp[3];       /**< Physiology time stamps, e.g. ecg, breating, etc. */
+        uint16_t                image_data_type;                /**< e.g. unsigned short, float, complex float, etc. */
+        uint16_t                image_type;                     /**< e.g. magnitude, phase, complex, real, imag, etc. */
+        uint16_t                image_index;                                    /**< e.g. image number in series of images  */
+        uint16_t                        image_series_index;             /**< e.g. series number */
+        int32_t                 user_int[8];                    /**< Free user parameters */
+        float                   user_float[8];                  /**< Free user parameters */
+};
+
+</pre>
+<p>In a similar fashion to the raw data acquisition data, the intention is to store a header followed by the image data. Since image data can be in several different format (e.g. float, complex, etc.), the memory layout is less well defined but can be described as:</p>
+<pre class="literal-block">
+template <typename T> class Image {
+
+ImageHeader head_;     //ImageHeader as defined above
+T* data_;              //Data, array of size (matrix_size[0]*matrix_size[1]*matrix_size[2]*channels),
+                       //first spatial dimension is fastest changing array index, channels outer most (slowest changing).
+};
+</pre>
 </div>
 </div>
 <div class="section" id="file-storage">
-<h1>File Storage</h1>
+<h1><a class="toc-backref" href="#id9">File Storage</a></h1>
 <p>The ISMRM Raw Data format is stored in HDF5 format. Details on this format can be found at the <a class="reference external" href="http://www.hdfgroup.org/HDF5/">HDF5</a> website. Briefly it is a hierarchical data format (much like a file system), which can contain multiple variable organized in groups (like folders in a file system). The variables can contain arrays of data values, custom defined structs, or simple text fields. It is the convention (but not a requirement) that the IS [...]
 <pre class="literal-block">
 >> data = h5read('simple_gre.h5', '/dataset/data');
@@ -562,21 +669,56 @@ data: {1x1281 cell}
  >>
 </pre>
 <p>The HDF5 file format can be access from C, C++, and java using the libraries provided on the HDF5 website. The ISMRMRD distribution also comes with some C++ wrappers that can be used for easy access (read and write) from C++ programs. See below.</p>
+<p>In addition to storing acquisition data and images as defined by the headers above, the HDF5 format also enables storage of generic multi-dimensional arrays. The ISMRMRD format does not explicitly define how such data should be stored, but leaves it open for the user to add variables and data as dictated by a given application.</p>
 </div>
 <div class="section" id="c-support-library">
-<h1>C++ Support Library</h1>
+<h1><a class="toc-backref" href="#id10">C++ Support Library</a></h1>
 <p>To enable easy prototyping of C++ software using the ISMRMRD data format, a simple C++ wrapper class is provided (defined in <tt class="docutils literal">ismrmrd_hdf5.h</tt>):</p>
 <pre class="literal-block">
 class EXPORTISMRMRD IsmrmrdDataset
 {
  public:
-         IsmrmrdDataset(const char* filename, const char* groupname, bool create_file_if_needed = true);
-         int appendAcquisition(Acquisition* a);
-         int writeHeader(std::string& xml);
 
-         boost::shared_ptr<std::string> readHeader();
-         boost::shared_ptr<Acquisition> readAcquisition(unsigned long index = 0);
-         unsigned long getNumberOfAcquisitions();
+     IsmrmrdDataset(const char* filename, const char* groupname, bool create_file_if_needed = true)
+     : filename_(filename)
+     , groupname_(groupname)
+     , file_open_(false)
+     , dataset_open_(false)
+     , create_file_if_needed_(create_file_if_needed)
+     {
+             std::ifstream ifile(filename_.c_str());
+             file_exists_ = ifile;
+
+             if (openHDF5File() < 0) {
+                     std::cerr << "IsmrmrdDataset: Error opening HDF file." << std::endl;
+             }
+
+             if (!linkExists(groupname_.c_str())) {
+                     if (createGroupForDataset(groupname_.c_str()) < 0) {
+                             std::cerr << "IsmrmrdDataset: Error create HDF5 group." << std::endl;
+                     }
+             }
+
+             xml_header_path_ = groupname_ + std::string("/xml");
+             data_path_ = groupname_ + std::string("/data");
+     }
+
+     int appendAcquisition(Acquisition* a);
+     boost::shared_ptr<Acquisition> readAcquisition(unsigned long index = 0);
+     unsigned long getNumberOfAcquisitions();
+
+     int writeHeader(std::string& xml);
+     boost::shared_ptr<std::string> readHeader();
+
+     template <typename T> int appendImage(Image<T>& m, const char* varname);
+     template <typename T> boost::shared_ptr< Image<T> > readImage(const char* varname, unsigned long index = 0);
+
+     int appendImageHeader(ImageHeader& h, const char* varname);
+     boost::shared_ptr< ImageHeader > readImageHeader(const char* varname, unsigned long index = 0);
+
+     template <typename T> int appendArray(NDArrayContainer<T>& a, const char* varname);
+     template <typename T> int appendArray(std::vector<unsigned int>& dimensions, T* data, const char* varname);
+     template <typename T> boost::shared_ptr< NDArrayContainer<T> > readArray(const char* varname, unsigned long index = 0);
  };
 </pre>
 <p>Using this wrapper, C++ applications can be programmed as:</p>
@@ -612,7 +754,7 @@ std::cout << "Number of encoding spaces: " << cfg->enco
 <p>Again, this is not a requirement for using the ISMRMRD format, the XML can be parsed with numerous other xml parsing libraries. The schema file <tt class="docutils literal">schema/ismrmrd.xsd</tt> gives the user the option of validating the XML header before parsing, which is recommended to reduce the chance of hard to detect errors in your code due to missing or malformed parameters.</p>
 </div>
 <div class="section" id="matlab-example-code-and-datasets">
-<h1>Matlab Example Code and Datasets</h1>
+<h1><a class="toc-backref" href="#id11">Matlab Example Code and Datasets</a></h1>
 <p>The <tt class="docutils literal">examples</tt> folder contains some matlab code to illustrate simple interaction with the ISMRMRD data format. The examples use test data sets, wich can be downloaded from the Sourceforge <a class="reference external" href="http://sourceforge.net/projects/ismrmrd">website</a>. Go to the <tt class="docutils literal">examples/data</tt> folder and type the following to download the data:</p>
 <pre class="literal-block">
 wget https://sourceforge.net/projects/ismrmrd/files/data/3D_partial_fourier.h5
@@ -657,9 +799,9 @@ Reconstructing image 10....done
 </pre>
 </div>
 <div class="section" id="appendix">
-<h1>Appendix</h1>
+<h1><a class="toc-backref" href="#id12">Appendix</a></h1>
 <div class="section" id="xml-schema-definition">
-<h2>XML Schema Definition</h2>
+<h2><a class="toc-backref" href="#id13">XML Schema Definition</a></h2>
 <pre class="literal-block" id="schema">
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <xs:schema xmlns="http://www.ismrm.org/ISMRMRD" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.ismrm.org/ISMRMRD">
@@ -809,7 +951,7 @@ Reconstructing image 10....done
 </pre>
 </div>
 <div class="section" id="frequently-asked-questions">
-<h2>Frequently Asked Questions</h2>
+<h2><a class="toc-backref" href="#id14">Frequently Asked Questions</a></h2>
 <ul>
 <li><p class="first">I am trying to compile on Mac OSX Lion and I am getting strange errors.</p>
 <blockquote>
diff --git a/doc/README.rst b/doc/README.rst
index c672b60..796ebc6 100644
--- a/doc/README.rst
+++ b/doc/README.rst
@@ -1,6 +1,8 @@
 ISMRM Raw Data Format (ISMRMRD)
 *******************************
 
+.. contents::
+
 Preamble
 ---------
 
@@ -8,13 +10,20 @@ A prerequisite for sharing magnetic resonance (imaging) reconstruction algorithm
 
 This standard was developed by a subcommittee of the ISMRM Sedona 2013 workshop. Comments and requests for additions/modifications can be sent to:
 
-* Michael S. Hansen (michael.hansen AT nih DOT gov)
+* Michael S. Hansen (michael DOT hansen AT nih DOT gov)
 * Wally Block (wblock AT cae DOT wisc DOT edu)
 * Mark Griswold (mag46 AT case DOT edu)
 * Brian Hargreaves (bah AT stanford DOT edu)
-* Peter Boernert (peter.boernert AT philips DOT com)
+* Peter Boernert (peter DOT boernert AT philips DOT com)
+* Sebastian Kozerke (kozerke AT biomed DOT ee DOT ethz DOT ch)
+* Craig Meyer (cmeyer AT virginia DOT edu)
+* Doug Noll (dnoll AT umich DOT edu)
 * Jim Pipe (Jim.Pipe AT DignityHealth DOT org)
 
+
+Obtaining and Installing
+-------------------------
+
 The source code, examples, and example datasets can be found on the ISMRM Raw Data Sourceforge website_.
 
 .. _website: http://sourceforge.net/projects/ismrmrd
@@ -27,6 +36,45 @@ Alternatively download the zip file with the source code::
 
   wget https://sourceforge.net/projects/ismrmrd/files/src/ismrmrd_latest.zip
 
+API Documentation can be found at http://ismrmrd.sourceforge.net/api.
+
+
+Dependencies
+.............
+
+The ISMRM Raw Data format is described by an XML schema_ and some C-style structs with fixed memory layout and as such does not have dependencies. However, it uses HDF5 files for storage and a C++ library for reading and writing the ISMRMRD files is included in this distribution. Furthermore, since the XML header is defined with an XML schema_, we encourage using XML data binding when writing software using the format. In the ISMRMRD distribution we use the CodeSynthesis XSD (http://www. [...]
+
+
+* HDF5 (version 1.8 or higher) libraries. Available from http://www.hdfgroup.org/downloads/index.html. 
+* Boost (http://www.boost.org/)
+* CodeSynthesis XSD (http://www.codesynthesis.com/products/xsd/)
+* Xerces-C XML parser library (http://xerces.apache.org/xerces-c/)
+* Cmake build tool (http://www.cmake.org/)
+* Doxygen if you would like to generate API documentation (http://www.doxygen.org)
+* Git if you would like to use the source code archive (http://git-scm.com/)
+
+.. note:: It is only necessary to install the dependencies if you wish to develop compiled C/C++ software, which uses the ISMRMRD format. The format can be read in Matlab without installing any additional software. 
+
+
+Linux installation
+...................
+
+The dependencies mentioned above should be included in most linux distributions. On Ubuntu you can install all required dependencies with::
+
+  sudo apt-get install libhdf5-serial-dev h5utils cmake cmake-curses-gui libboost-dev libxerces-c-dev xsdcxx doxygen git
+
+After installation of dependencies, the library can be installed with::
+
+  git clone git://git.code.sf.net/p/ismrmrd/code ismrmrd-code
+  cd ismrmrd-code/
+  mkdir build
+  cd build
+  cmake ../
+  make
+  sudo make install
+
+Last command will install the library in ``/usr/local/ismrmrd``.
+
 
 Change log
 ----------
@@ -37,11 +85,13 @@ August 2012 - First draft.
 Overview
 ---------
 
-The raw data format combines a mix of flexible data structures (XML header) and fixed structures (equivalent to C-structs). A raw data set consist of 2 sections:
+The raw data format combines a mix of flexible data structures (XML header) and fixed structures (equivalent to C-structs). A raw data set consist mainly of 2 sections:
 
 1. A flexible XML format document that can contain an arbitrary number of fields and accommodate everything from simple values (b-values, etc.) to entire vendor protocols, etc. This purpose of this XML document is to provide parameters that may be meaningful for some experiments but not for others. This XML format is defined by an XML Schema Definition file (ismrmrd.xsd). 
 2. Raw data section. This section contains all the acquired data in the experiment. Each data item is preceded by a C-struct with encoding numbers, etc. Following this data header is a channel header and data for each acquired channel. The raw data headers are defined in a C/C++ header file (ismrmrd.h)
 
+In addition to these sections, the ISMRMRD format also specifies an image header for storing reconstructed images and the accompanying C++ library provides a convenient way of writing such images into HDF5 files along with generic arrays for storing less well defined data structures, e.g. coil sensitivity maps or other calibration data. 
+
 Flexible Data Header
 .....................
 
@@ -86,19 +136,19 @@ In addition to the defined field in the xml header, it is possible to add an arb
 Fixed Data structures
 ......................
 
-Each acquisition is preceded by the following fixed layout structure:
+Each raw data acquisition is preceded by the following fixed layout structure:
 
 .. include:: ../ismrmrd.h
    :literal:
-   :start-line: 118
-   :end-line: 143
+   :start-line: 123
+   :end-line: 148
 
 Where EncodingCounters are defined as:
 
 .. include:: ../ismrmrd.h
    :literal:
-   :start-line: 102
-   :end-line: 114
+   :start-line: 107
+   :end-line: 119
 
 The interpretation of some of these fields may vary from sequence to sequence, i.e. for a Cartesian sequence, ``kspace_encode_step_1`` would be the phase encoding step, for a spiral sequence where phase encoding direction does not make sense, it would be the spiral interleave number. The ``encoding_space_ref`` enables the user to tie an acquisition to a specific encoding space (see above) in case there are multiple, e.g. in situations where a calibration scan may be integrated in the acq [...]
 
@@ -125,7 +175,25 @@ The header contains a ``trajectory_dimensions`` field. If the value of this fiel
 
    };
 
-This suggested memory layout is only a suggestion. The HDF5 interface (see below) can be used to read the data into many different data structures. In fact, the user can choose to read only part of the header or not read the data, etc. 
+This suggested memory layout is only a suggestion. The HDF5 interface (see below) can be used to read the data into many different data structures. In fact, the user can choose to read only part of the header or not read the data, etc.
+
+As mentioned above, the ISMRMRD format also suggests a way to store reconstructed images (or maybe image data used for calibration). An ``ImageHeader`` structure is defined in ``ismrmrd.h``:
+
+.. include:: ../ismrmrd.h
+   :literal:
+   :start-line: 279
+   :end-line: 305
+
+In a similar fashion to the raw data acquisition data, the intention is to store a header followed by the image data. Since image data can be in several different format (e.g. float, complex, etc.), the memory layout is less well defined but can be described as::
+
+  template <typename T> class Image {
+
+  ImageHeader head_;     //ImageHeader as defined above
+  T* data_;              //Data, array of size (matrix_size[0]*matrix_size[1]*matrix_size[2]*channels),
+                         //first spatial dimension is fastest changing array index, channels outer most (slowest changing).
+  };
+ 
+
 
 File Storage
 -------------
@@ -174,6 +242,8 @@ The ISMRM Raw Data format is stored in HDF5 format. Details on this format can b
 
 The HDF5 file format can be access from C, C++, and java using the libraries provided on the HDF5 website. The ISMRMRD distribution also comes with some C++ wrappers that can be used for easy access (read and write) from C++ programs. See below.
 
+In addition to storing acquisition data and images as defined by the headers above, the HDF5 format also enables storage of generic multi-dimensional arrays. The ISMRMRD format does not explicitly define how such data should be stored, but leaves it open for the user to add variables and data as dictated by a given application. 
+
 .. _HDF5: http://www.hdfgroup.org/HDF5/
 
 C++ Support Library
@@ -186,13 +256,47 @@ To enable easy prototyping of C++ software using the ISMRMRD data format, a simp
    class EXPORTISMRMRD IsmrmrdDataset
    {
     public:
-	    IsmrmrdDataset(const char* filename, const char* groupname, bool create_file_if_needed = true);
-	    int appendAcquisition(Acquisition* a);
-	    int writeHeader(std::string& xml);
 
-	    boost::shared_ptr<std::string> readHeader();
-	    boost::shared_ptr<Acquisition> readAcquisition(unsigned long index = 0);
-	    unsigned long getNumberOfAcquisitions();
+	IsmrmrdDataset(const char* filename, const char* groupname, bool create_file_if_needed = true)
+	: filename_(filename)
+	, groupname_(groupname)
+	, file_open_(false)
+	, dataset_open_(false)
+	, create_file_if_needed_(create_file_if_needed)
+	{
+		std::ifstream ifile(filename_.c_str());
+		file_exists_ = ifile;
+
+		if (openHDF5File() < 0) {
+			std::cerr << "IsmrmrdDataset: Error opening HDF file." << std::endl;
+		}
+
+		if (!linkExists(groupname_.c_str())) {
+			if (createGroupForDataset(groupname_.c_str()) < 0) {
+				std::cerr << "IsmrmrdDataset: Error create HDF5 group." << std::endl;
+			}
+		}
+
+		xml_header_path_ = groupname_ + std::string("/xml");
+		data_path_ = groupname_ + std::string("/data");
+ 	}
+
+	int appendAcquisition(Acquisition* a);
+	boost::shared_ptr<Acquisition> readAcquisition(unsigned long index = 0);
+	unsigned long getNumberOfAcquisitions();
+
+	int writeHeader(std::string& xml);
+	boost::shared_ptr<std::string> readHeader();
+
+	template <typename T> int appendImage(Image<T>& m, const char* varname);
+	template <typename T> boost::shared_ptr< Image<T> > readImage(const char* varname, unsigned long index = 0);
+
+	int appendImageHeader(ImageHeader& h, const char* varname);
+	boost::shared_ptr< ImageHeader > readImageHeader(const char* varname, unsigned long index = 0);
+
+	template <typename T> int appendArray(NDArrayContainer<T>& a, const char* varname);
+	template <typename T> int appendArray(std::vector<unsigned int>& dimensions, T* data, const char* varname);
+	template <typename T> boost::shared_ptr< NDArrayContainer<T> > readArray(const char* varname, unsigned long index = 0);
     };
 
 
diff --git a/ismrmrd.h b/ismrmrd.h
index a65b047..6cbb288 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -62,42 +62,42 @@ public:
 };
 #endif //__cplusplus
 
-/* ACQUISITION FLAGS */
-enum {
+/** ACQUISITION FLAGS */
+enum AcquisitionFlags {
 	/* Looping indicators */
-	FIRST_IN_ENCODE_STEP1                	= 1,
-	LAST_IN_ENCODE_STEP1    				= 2,
-	FIRST_IN_ENCODE_STEP2   				= 3,
-	LAST_IN_ENCODE_STEP2    				= 4,
-	FIRST_IN_AVERAGE        				= 5,
-	LAST_IN_AVERAGE         				= 6,
-	FIRST_IN_SLICE          				= 7,
-	LAST_IN_SLICE           				= 8,
-	FIRST_IN_CONTRAST       				= 9,
-	LAST_IN_CONTRAST        				= 10,
-	FIRST_IN_PHASE          				= 11,
-	LAST_IN_PHASE           				= 12,
-	FIRST_IN_REPETITION     				= 13,
-	LAST_IN_REPETITION      				= 14,
-	FIRST_IN_SET            				= 15,
-	LAST_IN_SET             				= 16,
-	FIRST_IN_SEGMENT        				= 17,
-	LAST_IN_SEGMENT         				= 18,
-
-	IS_NOISE_MEASUREMENT                	= 19,
-	IS_PARALLEL_CALIBRATION             	= 20,
-	IS_PARALLEL_CALIBRATION_AND_IMAGING 	= 21,
-	IS_REVERSE              				= 22,
-	IS_NAVIGATION_DATA      				= 23,
-
-	USER1                   				= 57,
-	USER2                   				= 58,
-	USER3                   				= 59,
-	USER4                   				= 60,
-	USER5                   				= 61,
-	USER6                   				= 62,
-	USER7                   				= 63,
-	USER8                   				= 64
+	ACQ_FIRST_IN_ENCODE_STEP1                	= 1,
+	ACQ_LAST_IN_ENCODE_STEP1    				= 2,
+	ACQ_FIRST_IN_ENCODE_STEP2   				= 3,
+	ACQ_LAST_IN_ENCODE_STEP2    				= 4,
+	ACQ_FIRST_IN_AVERAGE        				= 5,
+	ACQ_LAST_IN_AVERAGE         				= 6,
+	ACQ_FIRST_IN_SLICE          				= 7,
+	ACQ_LAST_IN_SLICE           				= 8,
+	ACQ_FIRST_IN_CONTRAST       				= 9,
+	ACQ_LAST_IN_CONTRAST        				= 10,
+	ACQ_FIRST_IN_PHASE          				= 11,
+	ACQ_LAST_IN_PHASE           				= 12,
+	ACQ_FIRST_IN_REPETITION     				= 13,
+	ACQ_LAST_IN_REPETITION      				= 14,
+	ACQ_FIRST_IN_SET            				= 15,
+	ACQ_LAST_IN_SET             				= 16,
+	ACQ_FIRST_IN_SEGMENT        				= 17,
+	ACQ_LAST_IN_SEGMENT         				= 18,
+
+	ACQ_IS_NOISE_MEASUREMENT                	= 19,
+	ACQ_IS_PARALLEL_CALIBRATION             	= 20,
+	ACQ_IS_PARALLEL_CALIBRATION_AND_IMAGING 	= 21,
+	ACQ_IS_REVERSE              				= 22,
+	ACQ_IS_NAVIGATION_DATA      				= 23,
+
+	ACQ_USER1                   				= 57,
+	ACQ_USER2                   				= 58,
+	ACQ_USER3                   				= 59,
+	ACQ_USER4                   				= 60,
+	ACQ_USER5                   				= 61,
+	ACQ_USER6                   				= 62,
+	ACQ_USER7                   				= 63,
+	ACQ_USER8                   				= 64
 };
 
 
@@ -106,16 +106,16 @@ enum {
 
  */
 struct EncodingCounters {
-	uint16_t kspace_encode_step_1; //e.g. phase encoding line number
-	uint16_t kspace_encode_step_2; //e.g. partition encodning number
-	uint16_t average;              //e.g. signal average number
-	uint16_t slice;                //e.g. imaging slice number
-	uint16_t contrast;             //e.g. echo number in multi-echo
-	uint16_t phase;                //e.g. cardiac phase number
-	uint16_t repetition;           //e.g. dynamic number for dynamic scanning
-	uint16_t set;                  //e.g. flow encodning set
-	uint16_t segment;              //e.g. segment number for segmented acquisition
-	uint16_t user[8];              //Free user parameters
+	uint16_t kspace_encode_step_1; /**< e.g. phase encoding line number */
+	uint16_t kspace_encode_step_2; /**< e.g. partition encodning number */
+	uint16_t average;              /**< e.g. signal average number */
+	uint16_t slice;                /**< e.g. imaging slice number */
+	uint16_t contrast;             /**< e.g. echo number in multi-echo */
+	uint16_t phase;                /**< e.g. cardiac phase number */
+	uint16_t repetition;           /**< e.g. dynamic number for dynamic scanning */
+	uint16_t set;                  /**< e.g. flow encodning set */
+	uint16_t segment;              /**< e.g. segment number for segmented acquisition */
+	uint16_t user[8];              /**< Free user parameters */
 };
 
 /**
@@ -123,28 +123,28 @@ struct EncodingCounters {
  */
 struct AcquisitionHeader
 {
-	uint16_t           version;                        //First unsigned int indicates the version
-	uint64_t           flags;                          //bit field with flags
-	uint32_t           measurement_uid;                //Unique ID for the measurement
-	uint32_t           scan_counter;                   //Current acquisition number in the measurement
-	uint32_t           acquisition_time_stamp;         //Acquisition clock
-	uint32_t           physiology_time_stamp[3];       //Physiology time stamps, e.g. ecg, breating, etc.
-	uint16_t           number_of_samples;              //Number of samples acquired
-	uint16_t           available_channels;             //Available coils
-	uint16_t           active_channels;                //Active coils on current acquisiton
-	uint64_t           channel_mask[16];               //Mask to indicate which channels are active. Support for 1024 channels
-	uint16_t           discard_pre;                    //Samples to be discarded at the beginning of acquisition
-	uint16_t           discard_post;                   //Samples to be discarded at the end of acquisition
-	uint16_t           center_sample;                  //Sample at the center of k-space
-	uint16_t           encoding_space_ref;             //Reference to an encoding space, typically only one per acquisition
-	uint16_t           trajectory_dimensions;          //Indicates the dimensionality of the trajectory vector (0 means no trajectory)
-	float              sample_time_us;                 //Time between samples in micro seconds, sampling BW
-	float              position[3];                    //Three-dimensional spatial offsets from isocenter
-	float              quaternion[4];                  //Angulation of acquisition
-	float              patient_table_position[3];      //Patient table off-center
-	EncodingCounters   idx;                            //Encoding loop counters, see above
-	int32_t            user_int[8];                    //Free user parameters
-	float              user_float[8];                  //Free user parameters
+	uint16_t           version;                        /**< First unsigned int indicates the version */
+	uint64_t           flags;                          /**< bit field with flags */
+	uint32_t           measurement_uid;                /**< Unique ID for the measurement */
+	uint32_t           scan_counter;                   /**< Current acquisition number in the measurement */
+	uint32_t           acquisition_time_stamp;         /**< Acquisition clock */
+	uint32_t           physiology_time_stamp[3];       /**< Physiology time stamps, e.g. ecg, breating, etc. */
+	uint16_t           number_of_samples;              /**< Number of samples acquired */
+	uint16_t           available_channels;             /**< Available coils */
+	uint16_t           active_channels;                /**< Active coils on current acquisiton */
+	uint64_t           channel_mask[16];               /**< Mask to indicate which channels are active. Support for 1024 channels */
+	uint16_t           discard_pre;                    /**< Samples to be discarded at the beginning of acquisition */
+	uint16_t           discard_post;                   /**< Samples to be discarded at the end of acquisition */
+	uint16_t           center_sample;                  /**< Sample at the center of k-space */
+	uint16_t           encoding_space_ref;             /**< Reference to an encoding space, typically only one per acquisition */
+	uint16_t           trajectory_dimensions;          /**< Indicates the dimensionality of the trajectory vector (0 means no trajectory) */
+	float              sample_time_us;                 /**< Time between samples in micro seconds, sampling BW */
+	float              position[3];                    /**< Three-dimensional spatial offsets from isocenter */
+	float              quaternion[4];                  /**< Angulation of acquisition */
+	float              patient_table_position[3];      /**< Patient table off-center */
+	EncodingCounters   idx;                            /**< Encoding loop counters, see above */
+	int32_t            user_int[8];                    /**< Free user parameters */
+	float              user_float[8];                  /**< Free user parameters */
 };
 
 #ifdef __cplusplus
@@ -224,15 +224,15 @@ public:
 		return *this;
 	}
 
-	AcquisitionHeader head_; //Header, see above
+	AcquisitionHeader head_; /**< Header, see above */
 
-	float* traj_;            //Trajectory, elements = head_.trajectory_dimensions*head_.number_of_samples
-							 //   [kx,ky,kx,ky.....]        (for head_.trajectory_dimensions = 2)
-							 //   [kx,ky,kz,kx,ky,kz,.....] (for head_.trajectory_dimensions = 3)
+	float* traj_;            /**< Trajectory, elements = head_.trajectory_dimensions*head_.number_of_samples
+							       [kx,ky,kx,ky.....]        (for head_.trajectory_dimensions = 2)
+							       [kx,ky,kz,kx,ky,kz,.....] (for head_.trajectory_dimensions = 3)           */
 
-	float* data_;            //Actual data, elements = head_.number_of_samples*head_.active_channels*2
-	                         //   [re,im,re,im,.....,re,im,re,im,.....,re,im,re,im,.....]
-	                         //    ---channel 1-------channel 2---------channel 3-----
+	float* data_;            /**< Actual data, elements = head_.number_of_samples*head_.active_channels*2
+	                               [re,im,re,im,.....,re,im,re,im,.....,re,im,re,im,.....]
+	                                 ---channel 1-------channel 2---------channel 3-----                     */
 
 protected:
 	void deleteData() {
@@ -242,35 +242,72 @@ protected:
 };
 #endif //__cplusplus
 
-/* Definition of ISMRM Raw Data Image structures */
+enum ImageDataType
+{
+	DATA_FLOAT = 1,
+	DATA_DOUBLE,
+	DATA_COMPLEX_FLOAT,
+	DATA_COMPLEX_DOUBLE,
+	DATA_UNSIGNED_SHORT
+};
+
+enum ImageType
+{
+	TYPE_MAGNITUDE = 1,
+	TYPE_PHASE,
+	TYPE_REAL,
+	TYPE_IMAG,
+	TYPE_COMPLEX
+};
+
+/** IMAGE FLAGS */
+enum ImageFlags {
+	IMAGE_IS_NAVIGATION_DATA      				= 23,
+
+	IMAGE_USER1                   				= 57,
+	IMAGE_USER2                   				= 58,
+	IMAGE_USER3                   				= 59,
+	IMAGE_USER4                   				= 60,
+	IMAGE_USER5                   				= 61,
+	IMAGE_USER6                   				= 62,
+	IMAGE_USER7                   				= 63,
+	IMAGE_USER8                   				= 64
+};
+
+/**
+ *  Definition of ISMRM Raw Data Image structure
+ */
 struct ImageHeader
 {
-	uint16_t           version;                        //First unsigned int indicates the version
-	uint64_t           flags;                          //bit field with flags
-	uint32_t           measurement_uid;                //Unique ID for the measurement
-	uint16_t           matrix_size[3];                 //Pixels in the 3 spatial dimensions
-	float              field_of_view[3];               //Size (in mm) of the 3 spatial dimensions
-	uint16_t           channels;                       //Number of receive channels
-	float              position[3];                    //Three-dimensional spatial offsets from isocenter
-	float              quaternion[4];                  //Angulation of acquisition
-	float              patient_table_position[3];      //Patient table off-center
-	uint16_t           average;                        //e.g. signal average number
-	uint16_t           slice;                          //e.g. imaging slice number
-	uint16_t           contrast;                       //e.g. echo number in multi-echo
-	uint16_t           phase;                          //e.g. cardiac phase number
-	uint16_t           repetition;                     //e.g. dynamic number for dynamic scanning
-	uint16_t           set;                            //e.g. flow encodning set
-	uint32_t           acquisition_time_stamp;         //Acquisition clock
-	uint32_t           physiology_time_stamp[3];       //Physiology time stamps, e.g. ecg, breating, etc.
-	uint16_t           image_data_type;                //e.g. unsigned short, float, complex float, etc.
-	uint16_t           image_type;                     //e.g. magnitude, phase, complex, real, imag, etc.
-	uint16_t           image_index;
-	uint16_t	       image_series_index;
-	int32_t            user_int[8];                    //Free user parameters
-	float              user_float[8];                  //Free user parameters
+	uint16_t           	version;                        /**< First unsigned int indicates the version */
+	uint64_t           	flags;                          /**< bit field with flags */
+	uint32_t           	measurement_uid;                /**< Unique ID for the measurement  */
+	uint16_t           	matrix_size[3];                 /**< Pixels in the 3 spatial dimensions */
+	float              	field_of_view[3];               /**< Size (in mm) of the 3 spatial dimensions */
+	uint16_t           	channels;                       /**< Number of receive channels */
+	float              	position[3];                    /**< Three-dimensional spatial offsets from isocenter */
+	float              	quaternion[4];                  /**< Angulation of acquisition */
+	float              	patient_table_position[3];      /**< Patient table off-center */
+	uint16_t           	average;                        /**< e.g. signal average number */
+	uint16_t           	slice;                          /**< e.g. imaging slice number */
+	uint16_t           	contrast;                       /**< e.g. echo number in multi-echo */
+	uint16_t           	phase;                          /**< e.g. cardiac phase number */
+	uint16_t           	repetition;                     /**< e.g. dynamic number for dynamic scanning */
+	uint16_t           	set;                            /**< e.g. flow encodning set */
+	uint32_t           	acquisition_time_stamp;         /**< Acquisition clock */
+	uint32_t           	physiology_time_stamp[3];       /**< Physiology time stamps, e.g. ecg, breating, etc. */
+	uint16_t           	image_data_type;                /**< e.g. unsigned short, float, complex float, etc. */
+	uint16_t           	image_type;                     /**< e.g. magnitude, phase, complex, real, imag, etc. */
+	uint16_t           	image_index;					/**< e.g. image number in series of images  */
+	uint16_t			image_series_index;             /**< e.g. series number */
+	int32_t            	user_int[8];                    /**< Free user parameters */
+	float              	user_float[8];                  /**< Free user parameters */
 };
 
 #ifdef __cplusplus
+/**
+ *   Container for an image (header and data)
+ */
 template <typename T> class Image {
 
 public:
@@ -333,9 +370,9 @@ public:
 				head_.channels;
 	}
 
-	ImageHeader head_;     //ImageHeader as defined above
-	T* data_;              //Data, array of size (matrix_size[0]*matrix_size[1]*matrix_size[2]*channels),
-	                       //first spatial dimension is fastest changing array index, channels outer most (slowest changing).
+	ImageHeader head_;     /**< ImageHeader as defined above */
+	T* data_;              /**< Data, array of size (matrix_size[0]*matrix_size[1]*matrix_size[2]*channels),
+	                            first spatial dimension is fastest changing array index, channels outer most (slowest changing). */
 
 protected:
 	void deleteData() {
@@ -347,20 +384,23 @@ protected:
 
 };
 
+/**
+ *  Container for generic array. This structure is used through the HDF5 file interaction.
+ */
 template <typename T> class NDArrayContainer
 {
 public:
 	NDArrayContainer() {}
 
-	NDArrayContainer(std::vector<unsigned int>& dimensions, T* d) {
+	NDArrayContainer(const std::vector<unsigned int>& dimensions, T* d) {
 		dimensions_ = dimensions;
 		data_.assign(d, d+elements());
 	}
 
 	virtual ~NDArrayContainer() {}
 
-	std::vector<unsigned int> dimensions_;
-	std::vector<T> data_;
+	std::vector<unsigned int> dimensions_; /**< Array with dimensions of the array. First dimension is fastest moving in the array */
+	std::vector<T> data_;                  /**< The data itself. A vector is used here for easy memory management                  */
 
 	size_t elements() {
 		if (dimensions_.size() == 0) {
diff --git a/ismrmrd_hdf5.cpp b/ismrmrd_hdf5.cpp
index 7294a25..117aa9a 100644
--- a/ismrmrd_hdf5.cpp
+++ b/ismrmrd_hdf5.cpp
@@ -555,5 +555,25 @@ template boost::shared_ptr< Image<unsigned short> > IsmrmrdDataset::readImage(co
 template boost::shared_ptr< Image< std::complex<float> > > IsmrmrdDataset::readImage(const char* varname, unsigned long index);
 template boost::shared_ptr< Image< std::complex<double> > > IsmrmrdDataset::readImage(const char* varname, unsigned long index);
 
+
+HDF5Lock* HDF5Lock::instance()
+{
+		if (!instance_) instance_ = new HDF5Lock();
+		return instance_;
+}
+
+void HDF5Lock::acquire()
+{
+	mutex_.lock();
+}
+
+void HDF5Lock::release()
+{
+	mutex_.unlock();
+}
+
+EXPORTISMRMRD HDF5Lock* HDF5Lock::instance_ = NULL;
+
+
 } //End of ISMRMRD namespace
 
diff --git a/ismrmrd_hdf5.h b/ismrmrd_hdf5.h
index 4e9edcf..84f522c 100644
--- a/ismrmrd_hdf5.h
+++ b/ismrmrd_hdf5.h
@@ -7,6 +7,7 @@
 
 #include <fstream>
 #include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
 
 
 #include <H5Cpp.h>
@@ -198,6 +199,42 @@ protected:
 	boost::shared_ptr<DataSet> dataset_;
 };
 
+/**
+ *  Convenience class to provide thread-safe access to HDF5 in cases
+ *  where that is not compiled into the HDF5 library.
+ */
+class EXPORTISMRMRD  HDF5Lock
+{
+
+public:
+	static HDF5Lock* instance();
+
+	void acquire();
+	void release();
+
+protected:
+	HDF5Lock()
+	: mutex_() { }
+
+	virtual ~HDF5Lock() { }
+
+	static HDF5Lock* instance_;
+
+	boost::mutex mutex_;
+};
+
+class HDF5Exclusive
+{
+public:
+	HDF5Exclusive() {
+		HDF5Lock::instance()->acquire();
+	}
+
+	~HDF5Exclusive() {
+		HDF5Lock::instance()->release();
+	}
+
+};
 
 
 } //end of ISMRMRD namespace

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ismrmrd.git



More information about the debian-science-commits mailing list