[ismrmrd] 01/02: Imported Upstream version 0.5.0

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Apr 3 13:45:37 UTC 2014


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

ghisvail-guest pushed a commit to branch master
in repository ismrmrd.

commit 94bf2caf07390d65acd880897dddfa5bd1ae9685
Author: Ghislain Vaillant <ghisvail at gmail.com>
Date:   Thu Apr 3 14:45:21 2014 +0100

    Imported Upstream version 0.5.0
---
 CMakeLists.txt                                     |    8 +-
 bindings/CMakeLists.txt                            |   17 +-
 bindings/java/CMakeLists.txt                       |   39 +-
 bindings/java/XMLString.java                       |   32 +-
 bindings/java/cfg.jxb                              |   10 +
 bindings/java/ismrmrd_java.i                       |   31 +
 bindings/java/{make_jar.sh => make_jar.sh.in}      |    5 +-
 bindings/python/CMakeLists.txt                     |   30 +-
 bindings/python/ismrmrd_python.i                   |  839 +++--------
 cmake/FindJava.cmake                               |  212 +++
 cmake/FindNumPy.cmake                              |  101 ++
 cmake/FindXSD.cmake                                |   72 +-
 examples/java/ismrmrd_test.java                    |   55 +-
 examples/matlab/{ => old}/ismrmrd_header2struct.m  |    0
 examples/matlab/old/simple_cartesian_recon.m       |  127 ++
 examples/matlab/{ => old}/simple_gridder.m         |    0
 examples/matlab/{ => old}/simple_spiral_recon.m    |    0
 examples/matlab/{ => old}/testsynth.m              |    0
 {matlab => examples/matlab/old}/xml2struct.m       |    0
 examples/matlab/simple_cartesian_recon.m           |   82 --
 examples/matlab/test_create_dataset.m              |  170 +++
 examples/matlab/test_recon_dataset.m               |  158 +++
 ismrmrd.h                                          | 1466 ++++++++++----------
 ismrmrd_hdf5_datatypes.h                           |    4 +
 matlab/+ismrmrd/+util/AcquisitionHeaderFromBytes.m |   47 +
 matlab/+ismrmrd/+util/AcquisitionHeaderToBytes.m   |   47 +
 matlab/+ismrmrd/+util/ImageHeaderFromBytes.m       |   32 +
 matlab/+ismrmrd/+util/ImageHeaderToBytes.m         |   32 +
 matlab/+ismrmrd/{old => +util}/hdf5_datatypes.m    |  187 +--
 matlab/+ismrmrd/+util/includejar.m                 |   15 +
 matlab/+ismrmrd/{old => +util}/isInt.m             |    0
 matlab/+ismrmrd/Acquisition.m                      |  122 ++
 matlab/+ismrmrd/AcquisitionFlags.m                 |   38 -
 matlab/+ismrmrd/AcquisitionHeader.m                |  627 ++++++---
 matlab/+ismrmrd/EncodingCounters.m                 |   94 --
 matlab/+ismrmrd/FlagBit.m                          |   32 -
 matlab/+ismrmrd/{old => }/Image.m                  |   18 +-
 matlab/+ismrmrd/ImageDataType.m                    |    9 -
 matlab/+ismrmrd/ImageFlags.m                       |   14 -
 matlab/+ismrmrd/ImageHeader.m                      |  554 +++++---
 matlab/+ismrmrd/ImageType.m                        |    9 -
 matlab/+ismrmrd/{old/file.m => IsmrmrdDataset.m}   |  200 +--
 matlab/+ismrmrd/XMLHeader.m                        |   33 -
 matlab/+ismrmrd/old/Acquisition.m                  |   49 -
 matlab/CMakeLists.txt                              |   72 +
 matlab/XMLString.java                              |   42 +
 matlab/cfg.jxb                                     |   10 +
 schema/ismrmrd.xsd                                 |  199 ++-
 48 files changed, 3421 insertions(+), 2519 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e5e7ec0..9d0de14 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,9 +36,6 @@ target_link_libraries(dummy ${XERCESC_LIBRARIES})
 # Add library ismrmrd
 add_library(ismrmrd SHARED ismrmrd_hdf5.cpp)
 
-# Process the MATLAB files
-file(GLOB MatlabMFiles ${CMAKE_SOURCE_DIR}/matlab/+ismrmrd/*.m)
-
 #The findHDF5.cmake does not work very well on Windows, let's help it out
 IF(WIN32)
 	SET(HDF5_LIB_DIR ${HDF5_INCLUDE_DIR}/../lib)
@@ -57,12 +54,13 @@ ENDIF(WIN32)
 
 INSTALL(FILES ismrmrd.h ismrmrd_hdf5.h ismrmrd_hdf5_datatypes.h ismrmrd_export.h DESTINATION include)
 INSTALL(FILES schema/ismrmrd.xsd ${XSDS_SOURCES} DESTINATION schema)
-INSTALL(FILES cmake/FindIsmrmrd.cmake cmake/FindFFTW3.cmake cmake/FindXSD.cmake cmake/FindXercesC.cmake DESTINATION cmake)
+INSTALL(FILES cmake/FindIsmrmrd.cmake cmake/FindFFTW3.cmake cmake/FindXSD.cmake
+        cmake/FindXercesC.cmake cmake/FindNumPy.cmake DESTINATION cmake)
 INSTALL(TARGETS ismrmrd DESTINATION lib)
-INSTALL(FILES ${MatlabMFiles} DESTINATION matlab/+ismrmrd)
 
 add_subdirectory(examples/c++)
 add_subdirectory(utilities)
 add_subdirectory(tests)
 add_subdirectory(doc)
+add_subdirectory(matlab)
 add_subdirectory(bindings)
diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt
index 2b7cda6..4be6529 100644
--- a/bindings/CMakeLists.txt
+++ b/bindings/CMakeLists.txt
@@ -6,15 +6,26 @@ if(SWIG_FOUND)
 
     find_package(PythonLibs)
     if(PYTHONLIBS_FOUND)
-        add_subdirectory(python)
+        find_package(NumPy)
+        if(NUMPY_FOUND)
+            if (NUMPY_VERSION VERSION_LESS "1.7")
+                message("NumPy version < 1.7. Not building Python bindings")
+            else (${NUMPY_VERSION} VERSION_LESS "1.7")
+                add_subdirectory(python)
+            endif (NUMPY_VERSION VERSION_LESS "1.7")
+        else(NUMPY_FOUND)
+            message("NumPy not found. Not building Python bindings")
+        endif(NUMPY_FOUND)
     else(PYTHONLIBS_FOUND)
         message("PythonLibs not found. Not building Python bindings")
     endif(PYTHONLIBS_FOUND)
 
-    if(DEFINED JAVA_INCLUDE_DIR)
+    find_package(JNI)
+    if(JNI_FOUND)
+        message(STATUS "JAVA Include Path: ${JAVA_INCLUDE_PATH}")
         add_subdirectory(java)
     else()
-        message("JAVA_INCLUDE_DIR not defined. Not building Java bindings")
+        message("JNI not found. Not building Java bindings")
     endif()
 
 endif(SWIG_FOUND)
diff --git a/bindings/java/CMakeLists.txt b/bindings/java/CMakeLists.txt
index 86c2f23..5eb54b9 100644
--- a/bindings/java/CMakeLists.txt
+++ b/bindings/java/CMakeLists.txt
@@ -1,33 +1,44 @@
 include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
 include_directories(${HDF5_INCLUDE_DIR} ${HDF5_INCLUDE_DIR}/cpp ${Boost_INCLUDE_DIR})
-include_directories(${JAVA_INCLUDE_DIR})
+include_directories(${JAVA_INCLUDE_PATH})
 if (UNIX)
-    include_directories(${JAVA_INCLUDE_DIR}/linux)
+    include_directories(${JAVA_INCLUDE_PATH}/linux)
 endif (UNIX)
 
 set(CMAKE_SWIG_FLAGS -package org.ismrm.ismrmrd)
 set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/org/ismrm/ismrmrd)
 
-set(SWIG_SOURCES ismrmrd_java.i ../../ismrmrd_hdf5.cpp)
+set(SWIG_SOURCES ismrmrd_java.i ${CMAKE_SOURCE_DIR}/ismrmrd_hdf5.cpp)
 set_source_files_properties(${SWIG_SOURCES} PROPERTIES CPLUSPLUS ON)
 swig_add_module(jismrmrd java ${SWIG_SOURCES})
 swig_link_libraries(jismrmrd ${HDF5_LIBRARIES} ${Boost_LIBRARIES})
 
-## TODO: this will NOT work on Windows
-set_source_files_properties(ismrmrd.jar PROPERTIES GENERATED true)
+#### ISMRMRD XML Header Java library ####
+configure_file(make_jar.sh.in make_jar.sh @ONLY)
+
+set(JAVADOC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc")
+set(JAVA_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/ismrmrd.jar" ${JAVADOC_OUTPUT})
+
+## TODO: not use a shell script... it breaks 'make'
 add_custom_command(
-    TARGET jismrmrd
-    POST_BUILD
+    OUTPUT ${JAVA_OUTPUTS}
+    DEPENDS jismrmrd "${CMAKE_CURRENT_BINARY_DIR}/make_jar.sh"
+    VERBATIM
+    COMMENT "Compiling java files, building jar, generating API docs"
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-    COMMENT "Compiling java files and creating jar" VERBATIM
-    COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/JNILibLoader.java	
+    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/JNILibLoader.java
                ${CMAKE_CURRENT_BINARY_DIR}/org/ismrm/ismrmrd/
     COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/org/ismrm/ismrmrd/xmlhdr
-    COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/XMLString.java	
+    COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/XMLString.java
                ${CMAKE_CURRENT_BINARY_DIR}/org/ismrm/ismrmrd/xmlhdr/
-    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/make_jar.sh
-    VERBATIM
+    COMMAND sh make_jar.sh
+    COMMAND javadoc -quiet -d ${JAVADOC_OUTPUT} -subpackages org.ismrm.ismrmrd.xmlhdr
 )
+add_custom_target(ismrmrdjar ALL DEPENDS ${JAVA_OUTPUTS})
+
+install(TARGETS jismrmrd DESTINATION java)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ismrmrd.jar DESTINATION java)
 
-install(TARGETS jismrmrd DESTINATION lib)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ismrmrd.jar DESTINATION lib)
+# Note: the API documentation is only for the XML header, and is installed
+# in ${INSTALL_PREFIX}/matlab/doc
+install(DIRECTORY ${JAVADOC_OUTPUT} DESTINATION matlab)
diff --git a/bindings/java/XMLString.java b/bindings/java/XMLString.java
index d215e1d..8038712 100644
--- a/bindings/java/XMLString.java
+++ b/bindings/java/XMLString.java
@@ -1,6 +1,8 @@
 package org.ismrm.ismrmrd.xmlhdr;
 
 import javax.xml.bind.*;
+import javax.xml.namespace.QName;
+import javax.xml.transform.stream.*;
 import java.io.StringReader;
 import java.io.StringWriter;
 
@@ -8,21 +10,33 @@ import java.io.StringWriter;
 public class XMLString {
     public static IsmrmrdHeader StringToIsmrmrdHeader(String xmlstring) throws javax.xml.bind.JAXBException
     {
-        JAXBContext jc = JAXBContext.newInstance(IsmrmrdHeader.class);
-        Unmarshaller u  = jc.createUnmarshaller();
+        JAXBContext jaxbContext = JAXBContext.newInstance(IsmrmrdHeader.class);
+
+        Unmarshaller unmarshaller  = jaxbContext.createUnmarshaller();
+
         StringReader reader = new StringReader(xmlstring);
-        IsmrmrdHeader hdr = (IsmrmrdHeader) u.unmarshal(reader);
-        return hdr;
+
+        JAXBElement<IsmrmrdHeader> root = unmarshaller.unmarshal(new StreamSource(reader), IsmrmrdHeader.class);
+
+        return root.getValue();
     }
 
     public static String IsmrmrdHeaderToString(IsmrmrdHeader header) throws javax.xml.bind.JAXBException
     {
-        JAXBContext jc = JAXBContext.newInstance(IsmrmrdHeader.class);
-        Marshaller m = jc.createMarshaller();
-        m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.ismrm.org/ISMRMRD ismrmrd.xsd");
-        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+        JAXBContext jaxbContext = JAXBContext.newInstance(IsmrmrdHeader.class);
+
+        Marshaller marshaller = jaxbContext.createMarshaller();
+
+        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.ismrm.org/ISMRMRD ismrmrd.xsd");
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
         StringWriter writer = new StringWriter();
-        m.marshal(header, writer);
+
+        QName qname = new QName("http://www.ismrm.org/ISMRMRD", "ismrmrdHeader");
+        JAXBElement<IsmrmrdHeader> root = new JAXBElement(qname, IsmrmrdHeader.class, header);
+
+        marshaller.marshal(root, writer);
+
         return writer.toString();
     }
 }
diff --git a/bindings/java/cfg.jxb b/bindings/java/cfg.jxb
new file mode 100644
index 0000000..c7d574f
--- /dev/null
+++ b/bindings/java/cfg.jxb
@@ -0,0 +1,10 @@
+<jxb:bindings version="1.0" 
+  xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
+  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
+  jxb:extensionBindingPrefixes="xjc">
+    <jxb:bindings>
+        <jxb:globalBindings localScoping="toplevel">
+        </jxb:globalBindings>
+    </jxb:bindings>
+</jxb:bindings>
diff --git a/bindings/java/ismrmrd_java.i b/bindings/java/ismrmrd_java.i
index 6d9cd7b..a2f0019 100644
--- a/bindings/java/ismrmrd_java.i
+++ b/bindings/java/ismrmrd_java.i
@@ -58,6 +58,9 @@ typedef std::complex<double> cxdouble;
 %apply int16_t[]  {int16_t *};
 %apply uint32_t[] {uint32_t *};
 
+%ignore *::operator=;
+%ignore *::operator[];
+
 //
 // Define some extra methods for serializing and deserializing the header structures
 //
@@ -145,9 +148,37 @@ typedef std::complex<double> cxdouble;
         env->ReleaseFloatArrayElements(arr, ptr, JNI_COMMIT);
     }
 
+    jfloatArray getTraj() {
+        JNIEnv *env = JNU_GetEnv();
+        uint32_t nelem = $self->getTrajectoryDimensions()*$self->getNumberOfSamples();
+        jfloatArray arr = env->NewFloatArray(nelem);
+        if (arr != NULL) {
+            float *ptr = env->GetFloatArrayElements(arr, NULL);
+            jint i;
+            for (i = 0; i < nelem; i++) {
+                ptr[i] = $self->getTraj()[i];
+            }
+            env->ReleaseFloatArrayElements(arr, ptr, JNI_COMMIT);
+        }
+        return arr;
+    }
+
+    void setTraj(jfloatArray arr) {
+        // Get the environment
+        JNIEnv *env = JNU_GetEnv();
+        // Get the size of the input array and a pointer to it
+	jsize len  = env->GetArrayLength(arr);
+        float *ptr = env->GetFloatArrayElements(arr, NULL);
+	std::valarray<float> tmp(ptr,len);
+        // TODO: make sure that the user has set the proper size.
+	$self->setTraj(tmp);
+        env->ReleaseFloatArrayElements(arr, ptr, JNI_COMMIT);
+    }
 }
 %ignore ISMRMRD::Acquisition::getData;
 %ignore ISMRMRD::Acquisition::setData;
+%ignore ISMRMRD::Acquisition::getTraj;
+%ignore ISMRMRD::Acquisition::setTraj;
 
 //
 // The Image and NDContainerArray classes are overloaded
diff --git a/bindings/java/make_jar.sh b/bindings/java/make_jar.sh.in
old mode 100755
new mode 100644
similarity index 64%
rename from bindings/java/make_jar.sh
rename to bindings/java/make_jar.sh.in
index 0ecb4e6..fa3b1a7
--- a/bindings/java/make_jar.sh
+++ b/bindings/java/make_jar.sh.in
@@ -3,11 +3,8 @@ javac org/ismrm/ismrmrd/*.java
 
 ## The XML Header classes
 # Make a class out of the schema
-xjc -p org.ismrm.ismrmrd.xmlhdr ../../../schema/ismrmrd.xsd
+xjc -p org.ismrm.ismrmrd.xmlhdr -b @CMAKE_SOURCE_DIR@/bindings/java/cfg.jxb @CMAKE_SOURCE_DIR@/schema/ismrmrd.xsd
 javac org/ismrm/ismrmrd/xmlhdr/*.java
 
 # Build a big jar
 jar -cvf ismrmrd.jar org/ismrm/ismrmrd/*.class org/ismrm/ismrmrd/xmlhdr/*.class
-
-# Build the java docs
-javadoc -quiet -d ismrmrd.javadoc -subpackages org.ismrm.ismrmrd
diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt
index 30199ea..8a86456 100644
--- a/bindings/python/CMakeLists.txt
+++ b/bindings/python/CMakeLists.txt
@@ -1,14 +1,18 @@
 include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${PYTHON_INCLUDE_PATH} ${PYTHON_NUMPY_INCLUDE_DIR})
+include_directories(${PYTHON_INCLUDE_PATH} ${NUMPY_INCLUDE_DIRS})
 include_directories(${HDF5_INCLUDE_DIR} ${HDF5_INCLUDE_DIR}/cpp ${Boost_INCLUDE_DIR})
 
+if ( WIN32 )
+    add_definitions(-Dismrmrd_EXPORTS)
+endif ( WIN32 )
+
 set_source_files_properties(ismrmrd_python.i PROPERTIES CPLUSPLUS ON)
 
-swig_add_module(ismrmrd python ismrmrd_python.i ../../ismrmrd_hdf5.cpp)
+swig_add_module(ismrmrd python ismrmrd_python.i ${CMAKE_SOURCE_DIR}/ismrmrd_hdf5.cpp)
 swig_link_libraries(ismrmrd ${HDF5_LIBRARIES} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
 
-install(TARGETS ${SWIG_MODULE_ismrmrd_REAL_NAME} DESTINATION lib)
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ismrmrd.py DESTINATION lib)
+install(TARGETS ${SWIG_MODULE_ismrmrd_REAL_NAME} DESTINATION python)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ismrmrd.py DESTINATION python)
 
 find_program(PYXBGEN pyxbgen
     HINTS ${PYTHON_HOME} ${PYTHON_LIBRARY}/..
@@ -16,13 +20,21 @@ find_program(PYXBGEN pyxbgen
 
 if(PYXBGEN)
     set(SCHEMA "${CMAKE_SOURCE_DIR}/schema/ismrmrd.xsd")
-    set(XSD_PY "${CMAKE_CURRENT_BINARY_DIR}/ismrmrd_xsd.py")
+    set(XSD_PY_FILE "${CMAKE_CURRENT_BINARY_DIR}/ismrmrd_xsd.py")
+    set(XSD_PY_DIR "${CMAKE_CURRENT_BINARY_DIR}/raw")
+
     add_custom_command(
-        OUTPUT ${XSD_PY}
-        COMMAND ${PYXBGEN} -u "${SCHEMA}" -m ismrmrd_xsd
+        OUTPUT ${XSD_PY_FILE} ${XSD_PY_DIR}
+        COMMAND ${PYXBGEN} -r -u "${SCHEMA}" -m ismrmrd_xsd
+        COMMAND ${CMAKE_COMMAND} -E echo "import" "pyxb.utils.domutils" >> ${XSD_PY_FILE}
+        COMMAND ${CMAKE_COMMAND} -E echo "'pyxb.utils.domutils.BindingDOMSupport.SetDefaultNamespace(Namespace)'" >> ${XSD_PY_FILE}
         DEPENDS ${SCHEMA})
-    add_custom_target(pyismrmrd_xsd ALL DEPENDS ${XSD_PY})
-    install(FILES ${XSD_PY} DESTINATION lib)
+
+    add_custom_target(pyismrmrd_xsd ALL DEPENDS ${XSD_PY_FILE})
+
+    install(FILES ${XSD_PY_FILE} DESTINATION python)
+    install(DIRECTORY ${XSD_PY_DIR} DESTINATION python)
+
 else(PYXBGEN)
     message("Can't find pyxbgen executable. Not building ismrmrd_xsd.py")
 endif(PYXBGEN)
diff --git a/bindings/python/ismrmrd_python.i b/bindings/python/ismrmrd_python.i
index b1fb679..e577e81 100644
--- a/bindings/python/ismrmrd_python.i
+++ b/bindings/python/ismrmrd_python.i
@@ -1,745 +1,296 @@
 %module ismrmrd
 
 %{
+
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+
 #include "ismrmrd_hdf5.h"
 #include "numpy/arrayobject.h"
 
 #define SWIG_FILE_WITH_INIT
 
-/* exception helpers */
-static int swig_c_err_num = 0;
-static char swig_c_err_msg[256];
-
-const char *err_occurred()
-{
-    if (swig_c_err_num) {
-        swig_c_err_num = 0;
-        return (const char*)swig_c_err_msg;
-    }
-    return NULL;
-}
-
-void set_err(const char *msg)
-{
-    swig_c_err_num = 1;
-    strncpy(swig_c_err_msg, msg, 256);
-}
-
-// typedef for complex numbers
-typedef std::complex<float>  cxfloat;
-typedef std::complex<double> cxdouble;
-
-%}
-
-%init %{
-import_array();
-%}
-
-%include "stdint.i"
-%include "std_string.i"
-%include "std_vector.i"
-%include "carrays.i"
-
-%array_class(unsigned short, ushortArray);
-%array_class(uint16_t, ushortArray);
-%array_class(unsigned int, uintArray);
-%array_class(uint32_t, uintArray);
-%array_class(float, floatArray);
-
-%exception {
-    const char *err;
-    $action
-    if ((err = err_occurred())) {
-        PyErr_SetString(PyExc_RuntimeError, err);
-        return NULL;
-    }
-}
-
-%extend ISMRMRD::Acquisition {
-    PyObject* getData()
-    {
-        npy_intp dims[] = { $self->getData().size() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_FLOAT);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
-
-        //printf("# elements: %d\n", $self->getData().size());
-        //printf("data size:  %d\n", data_size);
-        //printf("total size: %d\n", raw_size);
-
-        std::valarray<float> data = $self->getData();
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_float *addr = (npy_float*)(raw + (i * data_size));
-            *addr = data[i];
-
-            /* slower method */
-            //PyObject *o = PyFloat_FromDouble((double)data[i]);
-            //PyArray_SETITEM(array, addr, o);
-            //Py_DECREF(o);
-        }
-
-        return array;
-    }
-
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISFLOAT(array)) {
-            set_err("Argument to setData is not a numpy float array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
-
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_float *addr = (npy_float*)(raw + i * data_size);
-            (*$self)[i] = (float)*addr;
-        }
-    }
-
-}
-%ignore ISMRMRD::Acquisition::getData;
-%ignore ISMRMRD::Acquisition::setData;
-
+    /* exception helpers */
+    static int swig_c_err_num = 0;
+    static char swig_c_err_msg[256];
 
-//
-// The Image class is overloaded so we need to do some renaming
-//
-%rename(Image_ushort_getData)   Image<unsigned short int>::getData;
-%rename(Image_ushort_setData)   Image<unsigned short int>::setData;
-%rename(Image_float_getData)    Image<float>::getData;
-%rename(Image_float_setData)    Image<float>::setData;
-%rename(Image_double_getData)   Image<double>::getData;
-%rename(Image_double_setData)   Image<double>::setData;
-%rename(Image_cxfloat_getData)  Image<cxfloat>::getData;
-%rename(Image_cxfloat_setData)  Image<cxfloat>::setData;
-%rename(Image_cxdouble_getData) Image<cxdouble>::getData;
-%rename(Image_cxdouble_setData) Image<cxdouble>::setData;
-
-%extend ISMRMRD::Image<unsigned short int>
-{
-    PyObject *getData()
+    const char *err_occurred()
     {
-        npy_intp dims[] = { $self->getData().size() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_USHORT);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
-
-        int i;
-        for (i = 0; i < $self->getNumberOfElements(); i++) {
-            npy_ushort *addr = (npy_ushort*)(raw + (i * data_size));
-            *addr = (*self)[i];
+        if (swig_c_err_num) {
+            swig_c_err_num = 0;
+            return (const char*)swig_c_err_msg;
         }
-
-        return array;
+        return NULL;
     }
 
-    void setData(PyObject *array)
+    void set_err(const char *msg)
     {
-        if (!PyArray_Check(array) || !PyArray_ISINTEGER(array)) {
-            set_err("Argument to setData is not a numpy integer array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
-
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_ushort *addr = (npy_ushort*)(raw + i * data_size);
-            (*$self)[i] = (unsigned short)*addr;
-        }
+        swig_c_err_num = 1;
+        strncpy(swig_c_err_msg, msg, 256);
     }
-}
-%ignore ISMRMRD::Image<unsigned short int>::getData;
-%ignore ISMRMRD::Image<unsigned short int>::setData;
-
-%extend ISMRMRD::Image<float>
-{
-    PyObject *getData()
-    {
-        npy_intp dims[] = { $self->getData().size() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_FLOAT);
 
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
+    // typedef for complex numbers
+    typedef std::complex<float>  cxfloat;
+    typedef std::complex<double> cxdouble;
 
-        int i;
-        for (i = 0; i < $self->getNumberOfElements(); i++) {
-            npy_float *addr = (npy_float*)(raw + (i * data_size));
-            *addr = (*self)[i];
-        }
-
-        return array;
-    }
-
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISFLOAT(array)) {
-            set_err("Argument to setData is not a numpy float array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
-
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_float *addr = (npy_float*)(raw + i * data_size);
-            (*$self)[i] = (float)*addr;
-        }
-    }
-}
-%ignore ISMRMRD::Image<float>::getData;
-%ignore ISMRMRD::Image<float>::setData;
 
-%extend ISMRMRD::Image<double>
-{
-    PyObject *getData()
+    template <typename T> PyObject *make_image_array(boost::shared_ptr< ISMRMRD::NDArrayContainer<T> > cont, unsigned int numpy_type)
     {
-        npy_intp dims[] = { $self->getData().size() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_DOUBLE);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
+        size_t all_dims = cont->dimensions_.size();
+        size_t ndim = cont->ndims();
 
-        int i;
-        for (i = 0; i < $self->getNumberOfElements(); i++) {
-            npy_double *addr = (npy_double*)(raw + (i * data_size));
-            *addr = (*self)[i];
+        npy_intp* dims = new npy_intp[ndim];
+	for (int d = 0; d < all_dims; d++){
+            int dimension = cont->dimensions_[d];
+            if (dimension > 1) {
+                dims[d] = dimension;
+            }
         }
+	PyObject *array = PyArray_New(&PyArray_Type, ndim, dims, numpy_type, NULL, NULL, 0, NPY_ARRAY_FARRAY, NULL);
+	delete[] dims;
 
         return array;
     }
 
-    void setData(PyObject *array)
+    template <typename T> PyObject* readTArray(ISMRMRD::IsmrmrdDataset *dset, const char* varname, unsigned long index, unsigned int numpy_type)
     {
-        if (!PyArray_Check(array) || !PyArray_ISFLOAT(array)) {
-            set_err("Argument to setData is not a numpy double array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
+        boost::shared_ptr< ISMRMRD::NDArrayContainer<T> > container = dset->readArray<T>(varname,index);
+        PyObject *array = make_image_array<T>(container, numpy_type);
 
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_double *addr = (npy_double*)(raw + i * data_size);
-            (*$self)[i] = (double)*addr;
-        }
-    }
-}
-%ignore ISMRMRD::Image<double>::getData;
-%ignore ISMRMRD::Image<double>::setData;
+        T *raw = (T*)PyArray_DATA((PyArrayObject*)array);
+        npy_intp raw_size = PyArray_NBYTES((PyArrayObject*)array);
 
-%extend ISMRMRD::Image<cxfloat>
-{
-    PyObject *getData()
-    {
-        npy_intp dims[] = { $self->getData().size() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_CFLOAT);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
-
-        int i;
-        for (i = 0; i < $self->getNumberOfElements(); i++) {
-            npy_cfloat *addr = (npy_cfloat*)(raw + (i * data_size));
-            addr->real = (*self)[i].real();
-            addr->imag = (*self)[i].imag();
-        }
+        memcpy(raw, &container->data_[0], raw_size);
 
         return array;
     }
 
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISCOMPLEX(array)) {
-            set_err("Argument to setData is not a numpy complex array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
-
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_cfloat *addr = (npy_cfloat*)(raw + i * data_size);
-            (*$self)[i] = cxfloat(addr->real, addr->imag);
-        }
-    }
-}
-%ignore ISMRMRD::Image<cxfloat>::getData;
-%ignore ISMRMRD::Image<cxfloat>::setData;
-
-%extend ISMRMRD::Image<cxdouble>
-{
-    PyObject *getData()
-    {
-        npy_intp dims[] = { $self->getData().size() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_CDOUBLE);
+%}
 
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
+// Initialize NumPy
+%init %{
+    import_array();
+%}
 
-        int i;
-        for (i = 0; i < $self->getNumberOfElements(); i++) {
-            npy_cdouble *addr = (npy_cdouble*)(raw + (i * data_size));
-            addr->real = (*self)[i].real();
-            addr->imag = (*self)[i].imag();
-        }
+%include "stdint.i"
+%include "std_string.i"
+%include "std_vector.i"
+%include "carrays.i"
 
-        return array;
-    }
+%array_class(uint16_t, ushortArray);
+%array_class(int32_t, intArray);
+%array_class(uint32_t, uintArray);
+%array_class(uint64_t, ulongArray);
+%array_class(float, floatArray);
 
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISCOMPLEX(array)) {
-            set_err("Argument to setData is not a numpy complex array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
 
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_cdouble *addr = (npy_cdouble*)(raw + i * data_size);
-            (*$self)[i] = cxdouble(addr->real, addr->imag);
-        }
+%exception {
+    const char *err;
+    $action
+    if ((err = err_occurred())) {
+        PyErr_SetString(PyExc_RuntimeError, err);
+        return NULL;
     }
 }
-%ignore ISMRMRD::Image<cxdouble>::getData;
-%ignore ISMRMRD::Image<cxdouble>::setData;
-
-
-//
-// The NDContainerArray class is overloaded so rename each template
-//
-%rename(Array_ushort_getData)   NDArrayContainer<unsigned short int>::getData;
-%rename(Array_ushort_setData)   NDArrayContainer<unsigned short int>::setData;
-%rename(Array_float_getData)    NDArrayContainer<float>::getData;
-%rename(Array_float_setData)    NDArrayContainer<float>::setData;
-%rename(Array_double_getData)   NDArrayContainer<double>::getData;
-%rename(Array_double_setData)   NDArrayContainer<double>::setData;
-%rename(Array_cxfloat_getData)  NDArrayContainer<cxfloat>::getData;
-%rename(Array_cxfloat_setData)  NDArrayContainer<cxfloat>::setData;
-%rename(Array_cxdouble_getData) NDArrayContainer<cxdouble>::getData;
-%rename(Array_cxdouble_setData) NDArrayContainer<cxdouble>::setData;
-
-%extend ISMRMRD::NDArrayContainer<unsigned short int>
-{
-    PyObject* getData()
-    {
-        npy_intp dims[] = { $self->elements() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_USHORT);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
 
-        int i;
-        for (i = 0; i < $self->elements(); i++) {
-            npy_ushort *addr = (npy_ushort*)(raw + (i * data_size));
-            (*addr) = (*self)[i];
-        }
-
-        return array;
-    }
-
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISINTEGER(array)) {
-            set_err("Argument to setData is not a numpy integer array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
+%ignore *::operator=;
+%ignore *::operator[];
+%ignore ISMRMRD::AcquisitionHeader_with_data;
+%ignore ISMRMRD::ImageHeader_with_data;
+%ignore ISMRMRD::Image;
+%ignore ISMRMRD::NDArrayContainer;
 
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_ushort *addr = (npy_ushort*)(raw + i * data_size);
-            (*$self)[i] = (unsigned short)*addr;
-        }
-    }
-}
-%ignore ISMRMRD::NDArrayContainer<unsigned short int>::getData;
-%ignore ISMRMRD::NDArrayContainer<unsigned short int>::setData;
 
-%extend ISMRMRD::NDArrayContainer<float>
-{
+%extend ISMRMRD::Acquisition {
+    /* Returns 1-D Numpy Array */
     PyObject* getData()
     {
-        npy_intp dims[] = { $self->elements() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_FLOAT);
+        npy_intp dims[] = { $self->getData().size() };
+	PyObject *array = PyArray_New(&PyArray_Type, 1, dims, NPY_FLOAT,
+                NULL, NULL, 0, NPY_ARRAY_FARRAY, NULL);
 
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
+        char *raw = PyArray_BYTES((PyArrayObject*)array);
+        int data_size = PyArray_ITEMSIZE((PyArrayObject*)array);
+        npy_intp raw_size = PyArray_NBYTES((PyArrayObject*)array);
 
-        int i;
-        for (i = 0; i < $self->elements(); i++) {
-            npy_float *addr = (npy_float*)(raw + (i * data_size));
-            (*addr) = (*self)[i];
-        }
+        std::valarray<float> data = $self->getData();
+        memcpy(raw, &data[0], dims[0] * data_size);
 
         return array;
     }
 
-    void setData(PyObject *array)
+    void setData(PyObject *in_array)
     {
-        if (!PyArray_Check(array) || !PyArray_ISFLOAT(array)) {
+        if (!PyArray_Check((PyArrayObject*)in_array) || !PyArray_ISFLOAT((PyArrayObject*)in_array)) {
             set_err("Argument to setData is not a numpy float array\n");
             return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
+        } else if (!PyArray_ISBEHAVED_RO((PyArrayObject*)in_array)) {
+            set_err("Argument to setData must be aligned\n");
             return;
-        }
-
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_float *addr = (npy_float*)(raw + i * data_size);
-            (*$self)[i] = (float)*addr;
-        }
-    }
-}
-%ignore ISMRMRD::NDArrayContainer<float>::getData;
-%ignore ISMRMRD::NDArrayContainer<float>::setData;
-
-%extend ISMRMRD::NDArrayContainer<double>
-{
-    PyObject* getData()
-    {
-        npy_intp dims[] = { $self->elements() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_DOUBLE);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
-
-        int i;
-        for (i = 0; i < $self->elements(); i++) {
-            npy_double *addr = (npy_double*)(raw + (i * data_size));
-            (*addr) = (*self)[i];
-        }
-
-        return array;
-    }
-
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISFLOAT(array)) {
-            set_err("Argument to setData is not a numpy double array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
+        } else if (!PyArray_ISONESEGMENT((PyArrayObject*)in_array)) {
+            set_err("Data is not one segment\n");
             return;
         }
 
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_double *addr = (npy_double*)(raw + i * data_size);
-            (*$self)[i] = (double)*addr;
-        }
-    }
-}
-%ignore ISMRMRD::NDArrayContainer<double>::getData;
-%ignore ISMRMRD::NDArrayContainer<double>::setData;
-
-%extend ISMRMRD::NDArrayContainer<cxfloat>
-{
-    PyObject* getData()
-    {
-        npy_intp dims[] = { $self->elements() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_CFLOAT);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
-
-        int i;
-        for (i = 0; i < $self->elements(); i++) {
-            npy_cfloat *addr = (npy_cfloat*)(raw + (i * data_size));
-            addr->real = (*self)[i].real();
-            addr->imag = (*self)[i].imag();
+        PyObject *array = NULL;
+        /* if array is C-style contiguous, make a Fortran-style contiguous copy */
+        if (PyArray_ISCONTIGUOUS((PyArrayObject*)in_array)) {
+            array = PyArray_NewCopy((PyArrayObject*)in_array, NPY_FORTRANORDER);
+        } else {
+            array = in_array;
         }
 
-        return array;
-    }
+        int ndim = PyArray_NDIM((PyArrayObject*)array);
+        int itemsize = PyArray_ITEMSIZE((PyArrayObject*)array);
+        npy_intp nbytes = PyArray_NBYTES((PyArrayObject*)array);
+        npy_intp nelements = PyArray_SIZE((PyArrayObject*)array);
+        npy_intp* dims = PyArray_DIMS((PyArrayObject*)array);
+        npy_intp* strides = PyArray_STRIDES((PyArrayObject*)array);
+        void *raw = PyArray_DATA((PyArrayObject*)array);
 
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISCOMPLEX(array)) {
-            set_err("Argument to setData is not a numpy complex array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
-
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_cfloat *addr = (npy_cfloat*)(raw + i * data_size);
-            (*$self)[i] = cxfloat(addr->real, addr->imag);
-        }
+        std::valarray<float> data(0.0, nelements);
+        memcpy(&(data[0]), raw, nbytes);
+        $self->setData(data);
     }
 }
-%ignore ISMRMRD::NDArrayContainer<cxfloat>::getData;
-%ignore ISMRMRD::NDArrayContainer<cxfloat>::setData;
-
-%extend ISMRMRD::NDArrayContainer<cxdouble>
-{
-    PyObject* getData()
-    {
-        npy_intp dims[] = { $self->elements() };
-        PyObject *array = PyArray_SimpleNew(1, dims, NPY_CDOUBLE);
-
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        npy_intp raw_size = PyArray_NBYTES(array);
-
-        int i;
-        for (i = 0; i < $self->elements(); i++) {
-            npy_cdouble *addr = (npy_cdouble*)(raw + (i * data_size));
-            addr->real = (*self)[i].real();
-            addr->imag = (*self)[i].imag();
-        }
 
-        return array;
-    }
-
-    void setData(PyObject *array)
-    {
-        if (!PyArray_Check(array) || !PyArray_ISCOMPLEX(array)) {
-            set_err("Argument to setData is not a numpy complex array\n");
-            return;
-        } 
-
-        int ndim = PyArray_NDIM(array);
-        npy_intp *dims = PyArray_DIMS(array);
-        char *raw = PyArray_BYTES(array);
-        int data_size = PyArray_ITEMSIZE(array);
-        if (ndim != 1) {
-            set_err("Argument to setData must be a 1-D array\n");
-            return;
-        }
+%ignore ISMRMRD::Acquisition::getData;
+%ignore ISMRMRD::Acquisition::setData;
 
-        int i;
-        for (i = 0; i < dims[0]; i++) {
-            npy_cdouble *addr = (npy_cdouble*)(raw + i * data_size);
-            (*$self)[i] = cxdouble(addr->real, addr->imag);
-        }
-    }
-}
-%ignore ISMRMRD::NDArrayContainer<cxdouble>::getData;
-%ignore ISMRMRD::NDArrayContainer<cxdouble>::setData;
 
-//
 // IsmrmrdDataset
-//
-%rename(readImage_ushort)   readImage<unsigned short int>;
-%rename(readImage_float)    readImage<float>;
-%rename(readImage_double)   readImage<double>;
-%rename(readImage_cxfloat)  readImage<cxfloat>;
-%rename(readImage_cxdouble) readImage<cxdouble>;
-
-%rename(readArray_ushort)   readArray<unsigned short int>;
-%rename(readArray_float)    readArray<float>;
-%rename(readArray_double)   readArray<double>;
-%rename(readArray_cxfloat)  readArray<cxfloat>;
-%rename(readArray_cxdouble) readArray<cxdouble>;
 
 %extend ISMRMRD::IsmrmrdDataset {
+
+    // XML
     std::string readHeader() {
         boost::shared_ptr<std::string> hdr = $self->readHeader();
         return *(hdr.get()); 
     }
 
+    // Acquisition
     ISMRMRD::Acquisition* readAcquisition(unsigned long index = 0) {
         ISMRMRD::Acquisition* acq = new ISMRMRD::Acquisition(*$self->readAcquisition(index).get());
         return acq;
     }
 
+    // Image Header
     ISMRMRD::ImageHeader* readImageHeader(const char* varname, unsigned long index = 0) {
         ISMRMRD::ImageHeader* imghdr = new ISMRMRD::ImageHeader(*$self->readImageHeader(varname,index).get());
         return imghdr;
     }
 
-    // Image
-    ISMRMRD::Image<float>* readImage<float>(const char* varname, unsigned long index = 0) {
-        ISMRMRD::Image<float>* img = new ISMRMRD::Image<float>(*$self->readImage<float>(varname,index).get());
-        return img;
-    }
-
-    ISMRMRD::Image<double>* readImage<double>(const char* varname, unsigned long index = 0) {
-        ISMRMRD::Image<double>* img = new ISMRMRD::Image<double>(*$self->readImage<double>(varname,index).get());
-        return img;
-    }
-
-    ISMRMRD::Image<unsigned short int>* readImage<unsigned short>(const char* varname, unsigned long index = 0) {
-        ISMRMRD::Image<unsigned short>* img = new ISMRMRD::Image<unsigned short>(*$self->readImage<unsigned short>(varname,index).get());
-        return img;
-    }
-
-    ISMRMRD::Image<cxfloat>* readImage<cxfloat>(const char* varname, unsigned long index = 0) {
-        ISMRMRD::Image< cxfloat >* img = new ISMRMRD::Image< cxfloat >(*$self->readImage< cxfloat >(varname,index).get());
-        return img;
-    }
-
-    ISMRMRD::Image<cxdouble>* readImage<cxdouble>(const char* varname, unsigned long index = 0) {
-        ISMRMRD::Image<cxdouble>* img = new ISMRMRD::Image<cxdouble>(*$self->readImage<cxdouble>(varname,index).get());
-        return img;
-    }
-
-    // NDArray
-    ISMRMRD::NDArrayContainer<float>* readArray<float>(const char* varname, unsigned long index = 0) {
-        boost::shared_ptr< ISMRMRD::NDArrayContainer<float> > tmp = $self->readArray<float>(varname,index);
-        ISMRMRD::NDArrayContainer<float>* img = new ISMRMRD::NDArrayContainer<float>(tmp->dimensions_, tmp->data_);
-        return img;
-    }
-
-    ISMRMRD::NDArrayContainer<double>* readArray<double>(const char* varname, unsigned long index = 0) {
-        boost::shared_ptr< ISMRMRD::NDArrayContainer<double> > tmp = $self->readArray<double>(varname,index);
-        ISMRMRD::NDArrayContainer<double>* img = new ISMRMRD::NDArrayContainer<double>(tmp->dimensions_, tmp->data_);
-        return img;
-    }
-
-    ISMRMRD::NDArrayContainer<unsigned short>* readArray<unsigned short>(const char* varname, unsigned long index = 0) {
-        boost::shared_ptr< ISMRMRD::NDArrayContainer<unsigned short> > tmp = $self->readArray<unsigned short>(varname,index);
-        ISMRMRD::NDArrayContainer<unsigned short>* img = new ISMRMRD::NDArrayContainer<unsigned short>(tmp->dimensions_, tmp->data_);
-        return img;
-    }
+    // Image Data
+    PyObject* readArray(ISMRMRD::ImageHeader *hdr, const char* varname, unsigned long index = 0)
+    {
+        PyObject *array = NULL;
+        if (!hdr) {
+            return NULL;
+        }
 
-    ISMRMRD::NDArrayContainer< cxfloat >* readArray< cxfloat >(const char* varname, unsigned long index = 0) {
-        boost::shared_ptr< ISMRMRD::NDArrayContainer<cxfloat> >  tmp = $self->readArray< cxfloat >(varname,index);
-        ISMRMRD::NDArrayContainer<cxfloat>* img = new ISMRMRD::NDArrayContainer< cxfloat >(tmp->dimensions_, tmp->data_);
-        return img;
+        switch (hdr->image_data_type) {
+        case ISMRMRD::DATA_UNSIGNED_SHORT: {
+            return readTArray<unsigned short>($self, varname, index, NPY_USHORT);
+            break;
+        }
+        case ISMRMRD::DATA_FLOAT: {
+            return readTArray<float>($self, varname, index, NPY_FLOAT);
+            break;
+        }
+        case ISMRMRD::DATA_DOUBLE: {
+            return readTArray<double>($self, varname, index, NPY_DOUBLE);
+            break;
+        }
+        case ISMRMRD::DATA_COMPLEX_FLOAT: {
+            return readTArray<cxfloat>($self, varname, index, NPY_CFLOAT);
+            break;
+        }
+        case ISMRMRD::DATA_COMPLEX_DOUBLE: {
+            return readTArray<cxdouble>($self, varname, index, NPY_CDOUBLE);
+            break;
+        }
+        default:
+            array = NULL;
+        }
+        return array;
     }
 
-    ISMRMRD::NDArrayContainer<cxdouble>* readArray<cxdouble>(const char* varname, unsigned long index = 0) {
-        boost::shared_ptr< ISMRMRD::NDArrayContainer<cxdouble> > tmp = $self->readArray<cxdouble>(varname,index);
-        ISMRMRD::NDArrayContainer<cxdouble>* img = new ISMRMRD::NDArrayContainer<cxdouble>(tmp->dimensions_, tmp->data_);
-        return img;
+    int appendArray(PyObject *in_array, const char* varname)
+    {
+        if (!PyArray_Check((PyArrayObject*)in_array)) {
+            set_err("array arg to appendArray is not a numpy array\n");
+            return -1;
+        } else if (!PyArray_ISBEHAVED_RO((PyArrayObject*)in_array)) {
+            set_err("array arg to appendArray must be aligned and in machine byte-order\n");
+            return -1;
+        }
+
+        PyObject *array = NULL;
+        /* if in_array is C-style contiguous, make it a Fortran-style contiguous copy */
+        if (PyArray_ISCONTIGUOUS((PyArrayObject*)in_array)) {
+            array = PyArray_NewCopy((PyArrayObject*)in_array, NPY_FORTRANORDER);
+        } else {
+            array = in_array;
+        }
+
+        int ndim = PyArray_NDIM((PyArrayObject*)array);
+        npy_intp* dims = PyArray_DIMS((PyArrayObject*)array);
+
+        std::vector<unsigned int> dimensions;
+        for (int d = 0; d < ndim; d++) {
+            dimensions.push_back(dims[d]);
+        }
+
+        int ret = 0;
+        switch (PyArray_TYPE((PyArrayObject*)array)) {
+            case NPY_USHORT: {
+                npy_ushort *raw = (npy_ushort*)PyArray_DATA((PyArrayObject*)array);
+                ret = $self->appendArray(dimensions, raw, varname);
+                break;
+            }
+            case NPY_FLOAT: {
+                npy_float *raw = (npy_float*)PyArray_DATA((PyArrayObject*)array);
+                ret = $self->appendArray(dimensions, raw, varname);
+                break;
+            }
+            case NPY_DOUBLE: {
+                npy_double *raw = (npy_double*)PyArray_DATA((PyArrayObject*)array);
+                ret = $self->appendArray(dimensions, raw, varname);
+                break;
+            }
+            case NPY_CFLOAT: {
+                npy_cfloat *raw = (npy_cfloat*)PyArray_DATA((PyArrayObject*)array);
+                ret = $self->appendArray(dimensions, (std::complex<float>*)raw, varname);
+                break;
+            }
+            case NPY_CDOUBLE: {
+                npy_cdouble *raw = (npy_cdouble*)PyArray_DATA((PyArrayObject*)array);
+                ret = $self->appendArray(dimensions, (std::complex<float>*)raw, varname);
+                break;
+            }
+            default:
+                set_err("Invalid array dtype\n");
+                return -1;
+        }
+        return ret;
     }
 
 }
+
 %ignore readHeader;
 %ignore readAcquisition;
 %ignore readImageHeader;
 %ignore readImage;
 %ignore readArray;
+%ignore appendImage;
+%ignore appendArray;
 
-//
-// The header files to process
-//
+// Process the main ISMRMRD header
 %include "ismrmrd.h"
 
-// These defines are needed for the HDF5 stuff to work
+// These definitions are needed for the HDF5 stuff to work
 %define EXPORTISMRMRD %enddef
-namespace H5 {
-   
-}
+namespace H5 { }
 
+// Process the HDF5 ISMRMD headers
 %include "ismrmrd_hdf5.h"
 %include "ismrmrd_hdf5_datatypes.h"
-
-// Instantiate some of the overloaded objects and methods
-namespace ISMRMRD {
-    // The Image and ArrayContainer types
-    %template(Image_ushort)   Image<unsigned short int>;
-    %template(Image_float)    Image<float>;
-    %template(Image_double)   Image<double>;
-    %template(Image_cxfloat)  Image<cxfloat>;
-    %template(Image_cxdouble) Image<cxdouble>;
-
-    %template(Array_ushort)   NDArrayContainer<unsigned short int>;
-    %template(Array_float)    NDArrayContainer<float>;
-    %template(Array_double)   NDArrayContainer<double>;
-    %template(Array_cxfloat)  NDArrayContainer<cxfloat>;
-    %template(Array_cxdouble) NDArrayContainer<cxdouble>;
-
-    // The Image and ArrayContainer Append methods
-    %template(appendImage_ushort)   IsmrmrdDataset::appendImage<unsigned short int>;
-    %template(appendImage_float)    IsmrmrdDataset::appendImage<float>;
-    %template(appendImage_double)   IsmrmrdDataset::appendImage<double>;
-    %template(appendImage_cxfloat)  IsmrmrdDataset::appendImage<cxfloat>;
-    %template(appendImage_cxdouble) IsmrmrdDataset::appendImage<cxdouble>;
-
-    %template(appendArray_ushort)   IsmrmrdDataset::appendArray<unsigned short int>;
-    %template(appendArray_float)    IsmrmrdDataset::appendArray<float>;
-    %template(appendArray_double)   IsmrmrdDataset::appendArray<double>;
-    %template(appendArray_cxfloat)  IsmrmrdDataset::appendArray<cxfloat>;
-    %template(appendArray_cxdouble) IsmrmrdDataset::appendArray<cxdouble>;
-
-}
diff --git a/cmake/FindJava.cmake b/cmake/FindJava.cmake
new file mode 100644
index 0000000..4d6f888
--- /dev/null
+++ b/cmake/FindJava.cmake
@@ -0,0 +1,212 @@
+# - Find Java
+# This module finds if Java is installed and determines where the
+# include files and libraries are. This code sets the following
+# variables:
+#
+#  Java_JAVA_EXECUTABLE    = the full path to the Java runtime
+#  Java_JAVAC_EXECUTABLE   = the full path to the Java compiler
+#  Java_JAVAH_EXECUTABLE   = the full path to the Java header generator
+#  Java_JAVADOC_EXECUTABLE = the full path to the Java documention generator
+#  Java_XJC_EXECUTABLE     = the full path to the Java JAXB generator
+#  Java_JAR_EXECUTABLE     = the full path to the Java archiver
+#  Java_VERSION_STRING     = Version of the package found (java version), eg. 1.6.0_12
+#  Java_VERSION_MAJOR      = The major version of the package found.
+#  Java_VERSION_MINOR      = The minor version of the package found.
+#  Java_VERSION_PATCH      = The patch version of the package found.
+#  Java_VERSION_TWEAK      = The tweak version of the package found (after '_')
+#  Java_VERSION            = This is set to: $major.$minor.$patch(.$tweak)
+#
+# The minimum required version of Java can be specified using the
+# standard CMake syntax, e.g. find_package(Java 1.5)
+#
+# NOTE: ${Java_VERSION} and ${Java_VERSION_STRING} are not guaranteed to be
+# identical. For example some java version may return:
+# Java_VERSION_STRING = 1.5.0_17
+# and
+# Java_VERSION        = 1.5.0.17
+#
+# another example is the Java OEM, with:
+# Java_VERSION_STRING = 1.6.0-oem
+# and
+# Java_VERSION        = 1.6.0
+#
+# For these components the following variables are set:
+#
+#  Java_FOUND                    - TRUE if all components are found.
+#  Java_INCLUDE_DIRS             - Full paths to all include dirs.
+#  Java_LIBRARIES                - Full paths to all libraries.
+#  Java_<component>_FOUND        - TRUE if <component> is found.
+#
+# Example Usages:
+#  find_package(Java)
+#  find_package(Java COMPONENTS Runtime)
+#  find_package(Java COMPONENTS Development)
+#
+
+#=============================================================================
+# Copyright 2002-2009 Kitware, Inc.
+# Copyright 2009-2011 Mathieu Malaterre <mathieu.malaterre at gmail.com>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# The HINTS option should only be used for values computed from the system.
+set(_JAVA_HINTS
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\2.0;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/bin"
+  "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/bin"
+  $ENV{JAVA_HOME}/bin
+  )
+# Hard-coded guesses should still go in PATHS. This ensures that the user
+# environment can always override hard guesses.
+set(_JAVA_PATHS
+  /usr/lib/java/bin
+  /usr/share/java/bin
+  /usr/local/java/bin
+  /usr/local/java/share/bin
+  /usr/java/j2sdk1.4.2_04
+  /usr/lib/j2sdk1.4-sun/bin
+  /usr/java/j2sdk1.4.2_09/bin
+  /usr/lib/j2sdk1.5-sun/bin
+  /opt/sun-jdk-1.5.0.04/bin
+  )
+find_program(Java_JAVA_EXECUTABLE
+  NAMES java
+  HINTS ${_JAVA_HINTS}
+  PATHS ${_JAVA_PATHS}
+)
+
+if(Java_JAVA_EXECUTABLE)
+    execute_process(COMMAND ${Java_JAVA_EXECUTABLE} -version
+      RESULT_VARIABLE res
+      OUTPUT_VARIABLE var
+      ERROR_VARIABLE var # sun-java output to stderr
+      OUTPUT_STRIP_TRAILING_WHITESPACE
+      ERROR_STRIP_TRAILING_WHITESPACE)
+    if( res )
+      if(${Java_FIND_REQUIRED})
+        message( FATAL_ERROR "Error executing java -version" )
+      else()
+        message( STATUS "Warning, could not run java --version")
+      endif()
+    else()
+      # extract major/minor version and patch level from "java -version" output
+      # Tested on linux using
+      # 1. Sun / Sun OEM
+      # 2. OpenJDK 1.6
+      # 3. GCJ 1.5
+      # 4. Kaffe 1.4.2
+      if(var MATCHES "java version \"[0-9]+\\.[0-9]+\\.[0-9_.]+.*\".*")
+        # This is most likely Sun / OpenJDK, or maybe GCJ-java compat layer
+        string( REGEX REPLACE ".* version \"([0-9]+\\.[0-9]+\\.[0-9_.]+.*)\".*"
+                "\\1" Java_VERSION_STRING "${var}" )
+      elseif(var MATCHES "java full version \"kaffe-[0-9]+\\.[0-9]+\\.[0-9_]+\".*")
+        # Kaffe style
+        string( REGEX REPLACE "java full version \"kaffe-([0-9]+\\.[0-9]+\\.[0-9_]+).*"
+                "\\1" Java_VERSION_STRING "${var}" )
+      else()
+        if(NOT Java_FIND_QUIETLY)
+          message(WARNING "regex not supported: ${var}. Please report")
+        endif()
+      endif()
+      string( REGEX REPLACE "([0-9]+).*" "\\1" Java_VERSION_MAJOR "${Java_VERSION_STRING}" )
+      string( REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" Java_VERSION_MINOR "${Java_VERSION_STRING}" )
+      string( REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" Java_VERSION_PATCH "${Java_VERSION_STRING}" )
+      # warning tweak version can be empty:
+      string( REGEX REPLACE "[0-9]+\\.[0-9]+\\.[0-9]+[_\\.]?([0-9]*).*$" "\\1" Java_VERSION_TWEAK "${Java_VERSION_STRING}" )
+      if( Java_VERSION_TWEAK STREQUAL "" ) # check case where tweak is not defined
+        set(Java_VERSION ${Java_VERSION_MAJOR}.${Java_VERSION_MINOR}.${Java_VERSION_PATCH})
+      else()
+        set(Java_VERSION ${Java_VERSION_MAJOR}.${Java_VERSION_MINOR}.${Java_VERSION_PATCH}.${Java_VERSION_TWEAK})
+      endif()
+    endif()
+
+endif()
+
+
+find_program(Java_JAR_EXECUTABLE
+  NAMES jar
+  HINTS ${_JAVA_HINTS}
+  PATHS ${_JAVA_PATHS}
+)
+
+find_program(Java_JAVAC_EXECUTABLE
+  NAMES javac
+  HINTS ${_JAVA_HINTS}
+  PATHS ${_JAVA_PATHS}
+)
+
+find_program(Java_XJC_EXECUTABLE
+  NAMES xjc
+  HINTS ${_JAVA_HINTS}
+  PATHS ${_JAVA_PATHS}
+)
+
+find_program(Java_JAVAH_EXECUTABLE
+  NAMES javah
+  HINTS ${_JAVA_HINTS}
+  PATHS ${_JAVA_PATHS}
+)
+
+find_program(Java_JAVADOC_EXECUTABLE
+  NAMES javadoc
+  HINTS ${_JAVA_HINTS}
+  PATHS ${_JAVA_PATHS}
+)
+
+include(FindPackageHandleStandardArgs)
+if(Java_FIND_COMPONENTS)
+  foreach(component ${Java_FIND_COMPONENTS})
+    # User just want to execute some Java byte-compiled
+    if(component STREQUAL "Runtime")
+      find_package_handle_standard_args(Java
+        REQUIRED_VARS Java_JAVA_EXECUTABLE
+        VERSION_VAR Java_VERSION
+        )
+    elseif(component STREQUAL "Development")
+      find_package_handle_standard_args(Java
+        REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
+                      Java_XJC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
+        VERSION_VAR Java_VERSION
+        )
+    else()
+      message(FATAL_ERROR "Comp: ${component} is not handled")
+    endif()
+    set(Java_${component}_FOUND TRUE)
+  endforeach()
+else()
+  # Check for everything
+  find_package_handle_standard_args(Java
+    REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
+                  Java_XJC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
+    VERSION_VAR Java_VERSION
+    )
+endif()
+
+
+mark_as_advanced(
+  Java_JAVA_EXECUTABLE
+  Java_JAR_EXECUTABLE
+  Java_JAVAC_EXECUTABLE
+  Java_XJC_EXECUTABLE
+  Java_JAVAH_EXECUTABLE
+  Java_JAVADOC_EXECUTABLE
+  )
+
+# LEGACY
+set(JAVA_RUNTIME ${Java_JAVA_EXECUTABLE})
+set(JAVA_ARCHIVE ${Java_JAR_EXECUTABLE})
+set(JAVA_COMPILE ${Java_JAVAC_EXECUTABLE})
+
diff --git a/cmake/FindNumPy.cmake b/cmake/FindNumPy.cmake
new file mode 100644
index 0000000..6feeb73
--- /dev/null
+++ b/cmake/FindNumPy.cmake
@@ -0,0 +1,101 @@
+# - Find the NumPy libraries
+# This module finds if NumPy is installed, and sets the following variables
+# indicating where it is.
+#
+# TODO: Update to provide the libraries and paths for linking npymath lib.
+#
+#  NUMPY_FOUND               - was NumPy found
+#  NUMPY_VERSION             - the version of NumPy found as a string
+#  NUMPY_VERSION_MAJOR       - the major version number of NumPy
+#  NUMPY_VERSION_MINOR       - the minor version number of NumPy
+#  NUMPY_VERSION_PATCH       - the patch version number of NumPy
+#  NUMPY_VERSION_DECIMAL     - e.g. version 1.6.1 is 10601
+#  NUMPY_INCLUDE_DIRS        - path to the NumPy include files
+
+#============================================================================
+# Copyright 2012 Continuum Analytics, Inc.
+#
+# MIT License
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#============================================================================
+
+# Finding NumPy involves calling the Python interpreter
+if(NumPy_FIND_REQUIRED)
+    find_package(PythonInterp REQUIRED)
+else()
+    find_package(PythonInterp)
+endif()
+
+if(NOT PYTHONINTERP_FOUND)
+    set(NUMPY_FOUND FALSE)
+    return()
+endif()
+
+execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
+    "import numpy as n; print(n.__version__); print(n.get_include());"
+    RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS
+    OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT
+    ERROR_VARIABLE _NUMPY_ERROR_VALUE
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0)
+    if(NumPy_FIND_REQUIRED)
+        message(FATAL_ERROR
+            "NumPy import failure:\n${_NUMPY_ERROR_VALUE}")
+    endif()
+    set(NUMPY_FOUND FALSE)
+    return()
+endif()
+
+# Convert the process output into a list
+string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT})
+string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES})
+list(GET _NUMPY_VALUES 0 NUMPY_VERSION)
+list(GET _NUMPY_VALUES 1 NUMPY_INCLUDE_DIRS)
+
+string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}")
+if("${_VER_CHECK}" STREQUAL "")
+    # The output from Python was unexpected. Raise an error always
+    # here, because we found NumPy, but it appears to be corrupted somehow.
+    message(FATAL_ERROR
+        "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n")
+    return()
+endif()
+
+# Make sure all directory separators are '/'
+string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS})
+
+# Get the major and minor version numbers
+string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION})
+list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR)
+list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR)
+list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH)
+string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH})
+math(EXPR NUMPY_VERSION_DECIMAL
+    "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}")
+
+find_package_message(NUMPY
+    "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}"
+    "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}")
+
+set(NUMPY_FOUND TRUE)
+
diff --git a/cmake/FindXSD.cmake b/cmake/FindXSD.cmake
index ed83d61..59a8834 100644
--- a/cmake/FindXSD.cmake
+++ b/cmake/FindXSD.cmake
@@ -1,57 +1,26 @@
-# - Find CodeSource Xsd
-# This module can be used to find Xsd and it's include path
+# - Find CodeSynthesis XSD
+# This module can be used to find XSD and it's include path
 # Variables:
-#	XSD_EXECUTABLE
-#	XSD_INCLUDE_DIR
-#	XSD_FOUND
+#	XSD_FOUND - System has XSD
+#	XSD_EXECUTABLE - XSD binary executable
+#	XSD_INCLUDE_DIR - XSD include directory
+#
+# Functions:
+#       WRAP_XSD - Generates C++ bindings in the given output directory for a given schema file
 
-SET(XSD_FOUND FALSE)
+if(NOT DEFINED XSD_DIR AND DEFINED ENV{XSD_DIR})
+    set(XSD_DIR $ENV{XSD_DIR})
+endif(NOT DEFINED XSD_DIR AND DEFINED ENV{XSD_DIR})
 
-if(WIN32)
-	SET(__XSD_NAME xsd.exe)
-else(WIN32)
-	SET(__XSD_NAME xsdcxx xsd)
-endif(WIN32)
+find_program(XSD_EXECUTABLE NAMES xsd xsdcxx xsd.exe
+    PATHS ${XSD_DIR} /usr /usr/local
+    PATH_SUFFIXES bin
+)
 
-if(XSD_INCLUDE_DIR)
-	#in cache already
-	SET(XSD_FOUND TRUE)
-else(XSD_INCLUDE_DIR)
-	IF (WIN32) 
-	find_program(XSD_EXECUTABLE NAMES "bin/${__XSD_NAME}" "${__XSD_NAME}"
-	     PATHS
-		 ${XSD_DIR}
-		 ${XSD_DIR}/bin
-	)
-	ELSE(WIN32)
-	find_file(XSD_EXECUTABLE NAMES ${__XSD_NAME}
-	     PATHS
-	         /usr/local/bin
-		 /usr/bin
-		 ${XSD_DIR}
-		 ${XSD_DIR}/bin
-	)
-	ENDIF(WIN32)
-
-	if(XSD_EXECUTABLE)
-		SET(XSD_FOUND TRUE)
-	else(XSD_EXECUTABLE)
-		SET(XSD_EXECUTABLE "xsd-NOTFOUND" CACHE FILE "xsd executable path")
-	endif(XSD_EXECUTABLE)
-
-	find_path(XSD_INCLUDE_DIR NAMES xsd 
-	    PATHS
-		${XSD_DIR}/include
-		/usr/include
-		/usr/local/include
-	)
-
-	if(XSD_INCLUDE_DIR)
-		SET(XSD_FOUND TRUE)
-	else(XSD_INCLUDE_DIR)
-		SET(XSD_INCLUDE_DIR "xsd-include-NOTFOUND" CACHE PATH "xsd include path")
-	endif(XSD_INCLUDE_DIR)
-endif(XSD_INCLUDE_DIR)
+find_path(XSD_INCLUDE_DIR NAMES xsd/cxx/pre.hxx
+    PATHS ${XSD_DIR} /usr /usr/local
+    PATH_SUFFIXES include
+)
 
 FUNCTION(XSD_EXTRACT_OPTIONS _xsd_files _xsd_options)
 	foreach(current_arg ${ARGN})
@@ -94,3 +63,6 @@ FUNCTION(WRAP_XSD XSD_SRCS XSD_INCLUDES OUT_PATH)
 	SET(${XSD_SRCS} ${_XSD_SRCS} PARENT_SCOPE)
 ENDFUNCTION(WRAP_XSD)
 
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(XSD DEFAULT_MSG XSD_INCLUDE_DIR XSD_EXECUTABLE)
+mark_as_advanced(XSD_INCLUDE_DIR XSD_EXECUTABLE)
diff --git a/examples/java/ismrmrd_test.java b/examples/java/ismrmrd_test.java
index 07177ac..85b9fb7 100644
--- a/examples/java/ismrmrd_test.java
+++ b/examples/java/ismrmrd_test.java
@@ -5,42 +5,51 @@ public class ismrmrd_test {
 
     public static void main(String argv[]) {
         // Load the ISMRMRD JNI library
-	try {
-	    JNILibLoader.load();
-	}
-	catch (java.net.URISyntaxException e) {
-	    System.err.println("JNI Library failed to load: " + e.getMessage());
+        try {
+            JNILibLoader.load();
+        }
+        catch (java.net.URISyntaxException e) {
+            System.err.println("JNI Library failed to load: " + e.getMessage());
             System.exit(1);
-	}
-	
-	String filename = "";
-	if (argv.length == 1) {
-	    filename = argv[0];
-	}
-	else {
-	    System.err.println("Give me a filename.");
+        }
+
+        String filename = "";
+        if (argv.length == 1) {
+            filename = argv[0];
+        }
+        else {
+            System.err.println("Give me a filename.");
             System.exit(1);
-	}
-     
+        }
+
         IsmrmrdDataset f = new IsmrmrdDataset(filename, "/dataset");
         String xmlstring = f.readHeader();
-        System.out.println("The XML Header");
+
         System.out.println(xmlstring);
 
-	IsmrmrdHeader hdr = new IsmrmrdHeader();;
-	try {
-	    hdr = XMLString.StringToIsmrmrdHeader(xmlstring);
-	}
-	catch (javax.xml.bind.JAXBException e){
-	    System.err.println("XML Header could not be parsed." + e.getMessage());
+        IsmrmrdHeader hdr = new IsmrmrdHeader();
+        try {
+            hdr = XMLString.StringToIsmrmrdHeader(xmlstring);
+        } catch (javax.xml.bind.JAXBException e) {
+            System.err.format("XML Header could not be parsed.%n%s", e.getMessage());
             System.exit(1);
-	}
+        }
+
         long freq = hdr.getExperimentalConditions().getH1ResonanceFrequencyHz();
         System.out.format("%n%n The resonance frequency is %d.%n", freq);
 
         long nacq = f.getNumberOfAcquisitions();
         System.out.format("%n%n The number of Acquisitions is %d.%n", nacq);
 
+        String xmlcopy = "";
+        try {
+            xmlcopy = XMLString.IsmrmrdHeaderToString(hdr);
+        } catch (javax.xml.bind.JAXBException e) {
+            System.err.format("XML Header could not be generated.%n%s", e.getMessage());
+            System.exit(1);
+        }
+
+        System.out.println(xmlcopy);
     }
 
 }
diff --git a/examples/matlab/ismrmrd_header2struct.m b/examples/matlab/old/ismrmrd_header2struct.m
similarity index 100%
rename from examples/matlab/ismrmrd_header2struct.m
rename to examples/matlab/old/ismrmrd_header2struct.m
diff --git a/examples/matlab/old/simple_cartesian_recon.m b/examples/matlab/old/simple_cartesian_recon.m
new file mode 100644
index 0000000..08913f7
--- /dev/null
+++ b/examples/matlab/old/simple_cartesian_recon.m
@@ -0,0 +1,127 @@
+function [images] = simple_cartesian_recon(ismrmrdfile, dataset)
+%
+%   [images] = simple_cartesian_recon(ismrmrdfile, dataset)
+%
+%   Simple example of how to reconstruct a 2D/3D cartesian dataset stored
+%   in ISMRMRD dataformat. Reconstruction handles partial fourier,
+%   oversampling, etc. 
+%
+%   Michael S. Hansen (michael.hansen at nih.gov), 2012
+%   Souheil J. Inati  (souheil.inati at nih.gov),  2013
+%
+%   Usage notes:
+%     ismrmrdfile: string, required.
+%     dataset:     string, optional, default='dataset'
+%
+
+switch nargin
+    case 1
+        dset = 'dataset';
+    case 2
+        dset = dataset;
+    otherwise
+        error('Wrong number of input arguments.')
+end
+
+% Open the dataset
+f = ismrmrd.IsmrmrdDataset(ismrmrdfile, dset);
+
+% Is this a cartesian acquisition
+traj = f.xmlhdr.getEncoding.get(0).getTrajectory();
+if (~traj.equals(traj.CARTESIAN))
+   error('This is not a cartesian dataset'); 
+end
+
+% Get the matrix sizes and the number of slices and channels
+matrix_size = [f.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getX, ...
+               f.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getY, ...
+               f.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getZ];
+
+recon_size = [f.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getX, ...
+              f.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getY, ...
+              f.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getZ];
+
+if ~isempty(f.xmlhdr.getEncoding.get(0).getEncodingLimits.getSlice)
+    slices = f.xmlhdr.getEncoding.get(0).getEncodingLimits.getSlice;
+else
+    slices = 1;
+end
+
+channels = f.xmlhdr.getAcquisitionSystemInformation.getReceiverChannels.doubleValue;
+
+
+% Get the encoding centers
+center_line = f.xmlhdr.getEncoding.get(0).getEncodingLimits.getKspaceEncodingStep1.getCenter;
+if (matrix_size(3) > 1)
+    % 3D
+    center_partition = f.xmlhdr.getEncoding.get(0).getEncodingLimits.getKspaceEncodingStep2.getCenter;
+else
+    % 2D
+    center_partition = 0;
+end
+
+% Allocate a buffer for storing 1 repetition's worth of data
+buffer = zeros([matrix_size(1),matrix_size(2),matrix_size(3),slices,channels],'single');
+
+% Initalize the output
+images = [];
+
+% read all the acquisitions
+acq = f.readAcquisition();
+
+% Loop over all the acquisitions
+counter = 0;
+for p = 1:acq.getNumber()
+    
+    % ignore the noise scans
+    if acq.head.flagIsSet(acq.head.FLAGS.ACQ_IS_NOISE_MEASUREMENT,p)
+        continue
+    end
+
+    % stuff the data in the buffer
+    line_number      = int32(acq.head.idx.kspace_encode_step_1(p)) - center_line + matrix_size(2)/2 + 1;
+    if matrix_size(3) > 1
+        partition_number = int32(acq.head.idx.kspace_encode_step_2(p)) - center_partition + matrix_size(3)/2 + 1;
+    else
+        partition_number = 1;
+    end
+    slice_number     = acq.head.idx.slice(p) + 1;
+    buffer(:,line_number,partition_number,slice_number,:) = acq.data{p};
+    
+    % Is this the last in slice? We should make an image
+    if acq.head.flagIsSet(acq.head.FLAGS.ACQ_LAST_IN_SLICE,p)
+        counter = counter + 1;
+        fprintf('Reconstructing image %d\n', counter); 
+        fprintf('   slice: %d\n', slice_number); 
+        fprintf('   rep:   %d\n', acq.head.idx.repetition(p)+1); 
+
+        % FFT
+        img = fftshift(ifft(ifftshift(buffer(:,:,:,slice_number,:)),[],1)) ./ sqrt(size(buffer,1));
+        img = fftshift(ifft(ifftshift(img),[],2)) ./ sqrt(size(img,2));
+        if (matrix_size(3) > 1), 
+            img = fftshift(ifft(ifftshift(img),[],3)) ./ sqrt(size(img,3));
+        end
+
+        % Handle over-sampling
+        if matrix_size(3) > 1
+            img = img((1:recon_size(1)) + (matrix_size(1)-recon_size(1))/2, ...
+                      (1:recon_size(2)) + (matrix_size(2)-recon_size(2))/2, ...
+                      (1:recon_size(3)) + (matrix_size(3)-recon_size(3))/2, :);
+        else
+            img = img((1:recon_size(1)) + (matrix_size(1)-recon_size(1))/2, ...
+                      (1:recon_size(2)) + (matrix_size(2)-recon_size(2))/2, ...
+                      1, :);
+        end
+
+        % RMS coil combination
+        img = sqrt(sum(abs(img).^2,4));
+        
+        % Append to the output buffer
+        images(:,:,:,counter) = img;
+    end
+
+end
+fprintf('done\n'); 
+
+% Display the middle slice image
+% imagesc(images(:,:,bitshift(size(images,3),-1)+1, 1));colormap(gray);axis image;
diff --git a/examples/matlab/simple_gridder.m b/examples/matlab/old/simple_gridder.m
similarity index 100%
rename from examples/matlab/simple_gridder.m
rename to examples/matlab/old/simple_gridder.m
diff --git a/examples/matlab/simple_spiral_recon.m b/examples/matlab/old/simple_spiral_recon.m
similarity index 100%
rename from examples/matlab/simple_spiral_recon.m
rename to examples/matlab/old/simple_spiral_recon.m
diff --git a/examples/matlab/testsynth.m b/examples/matlab/old/testsynth.m
similarity index 100%
rename from examples/matlab/testsynth.m
rename to examples/matlab/old/testsynth.m
diff --git a/matlab/xml2struct.m b/examples/matlab/old/xml2struct.m
similarity index 100%
rename from matlab/xml2struct.m
rename to examples/matlab/old/xml2struct.m
diff --git a/examples/matlab/simple_cartesian_recon.m b/examples/matlab/simple_cartesian_recon.m
deleted file mode 100644
index 9e9daec..0000000
--- a/examples/matlab/simple_cartesian_recon.m
+++ /dev/null
@@ -1,82 +0,0 @@
-function [images] = simple_cartesian_recon(ismrmrdfile)
-%
-%   [images] = simple_cartesian_recon(ismrmrdfile)
-%
-%   Simple example of how to reconstruct a 2D/3D cartesian dataset stored
-%   in ISMRMRD dataformat. Reconstruction handles partial fourier,
-%   oversampling, etc. 
-%
-%   Michael S. Hansen (michael.hansen at nih.gov), 2012
-%
-
-
-%read the header
-header = ismrmrd_header2struct(h5read(ismrmrdfile,'/dataset/xml'));
-
-
-%Is this a cartesian acquisition
-if (~strcmp(header.ismrmrdHeader.encoding.trajectory.Text,'cartesian')),
-   error('This is not a cartesian dataset'); 
-end
-
-%if (str2num(header.ismrmrdHeader.encoding.encodedSpace.matrixSize.z.Text) <= 1),
-%    error('This is not a 3D dataset'); 
-%end
-    
-%Let's get the matrix size
-matrix_size = [str2num(header.ismrmrdHeader.encoding.encodedSpace.matrixSize.x.Text), ...
-               str2num(header.ismrmrdHeader.encoding.encodedSpace.matrixSize.y.Text), ...
-               str2num(header.ismrmrdHeader.encoding.encodedSpace.matrixSize.z.Text)];
-
-           
-recon_size = [str2num(header.ismrmrdHeader.encoding.reconSpace.matrixSize.x.Text), ...
-              str2num(header.ismrmrdHeader.encoding.reconSpace.matrixSize.y.Text), ...
-              str2num(header.ismrmrdHeader.encoding.reconSpace.matrixSize.z.Text)];
-
-
-%Let's load the data
-raw_data = h5read(ismrmrdfile,'/dataset/data');
-
-channels = max(raw_data.head.active_channels);
-samples = max(raw_data.head.number_of_samples);
-center_line = str2num(header.ismrmrdHeader.encoding.encodingLimits.kspace_encoding_step_1.center.Text);
-center_partition = str2num(header.ismrmrdHeader.encoding.encodingLimits.kspace_encoding_step_2.center.Text);
-
-if (samples ~= matrix_size(1)),
-    error('Mismatch between number of samples and matrix size');
-end
-
-buffer = zeros(matrix_size(1),matrix_size(2),matrix_size(3),channels);           
-counter = 0;
-for p=1:length(raw_data.head.flags),
-   if (bitget(uint64(raw_data.head.flags(p)),19)), %if this is noise, we will skip it
-      continue; 
-   end
-   line_number      = (int32(raw_data.head.idx.kspace_encode_step_1(p))-center_line)+bitshift(matrix_size(2),-1);  
-   partition_number = (int32(raw_data.head.idx.kspace_encode_step_2(p))-center_partition)+bitshift(matrix_size(3),-1);  
-   buffer(:,line_number+1,partition_number+1,:) = reshape(complex(raw_data.data{p}(1:2:end), raw_data.data{p}(2:2:end)), samples, 1, 1, channels);
-   
-   if (bitget(uint64(raw_data.head.flags(p)),8)), %Is this the last in slice? We should make an image
-      fprintf('Reconstructing image %d....', counter+1); 
-
-      img = fftshift(ifft(ifftshift(buffer),[],1)) ./ sqrt(size(buffer,1));
-      img = fftshift(ifft(ifftshift(img),[],2)) ./ sqrt(size(img,2));
-      if (matrix_size(3) > 1), 
-          img = fftshift(ifft(ifftshift(img),[],3)) ./ sqrt(size(img,3));
-      end
-      
-      img = img((1:recon_size(1))+bitshift(matrix_size(1)-recon_size(1),-1), ...
-                (1:recon_size(2))+bitshift(matrix_size(2)-recon_size(2),-1), ...
-                (1:recon_size(3))+bitshift(matrix_size(3)-recon_size(3),-1), :);
-      
-      images(:,:,:,counter+1) = sqrt(sum(abs(img).^2,4)); %RMS coil combination
-      counter = counter + 1;
-      fprintf('done\n'); 
-      buffer = zeros(matrix_size(1),matrix_size(2),matrix_size(3), channels);           
-   end  
-end
-
-%Let's just show the middle slice image
-imagesc(images(:,:,bitshift(size(images,3),-1)+1, 1));colormap(gray);axis image;
-
-
diff --git a/examples/matlab/test_create_dataset.m b/examples/matlab/test_create_dataset.m
new file mode 100644
index 0000000..a9c17f8
--- /dev/null
+++ b/examples/matlab/test_create_dataset.m
@@ -0,0 +1,170 @@
+%% Generating a simple ISMRMRD data set
+
+% This is an example of how to construct a datset from synthetic data
+% simulating a fully sampled acquisition on a cartesian grid.
+% data from 4 coils from a single slice object that looks like a square
+
+% File Name
+filename = 'testdata.h5';
+
+% Create an empty ismrmrd dataset
+if exist(filename,'file')
+    error(['File ' filename ' already exists.  Please remove first'])
+end
+dset = ismrmrd.IsmrmrdDataset(filename);
+
+% Synthesize the object
+nX = 256;
+nY = 256;
+rho = zeros(nX,nY);
+indxstart = floor(nX/4)+1;
+indxend   = floor(3*nX/4);
+indystart = floor(nY/4)+1;
+indyend   = floor(3*nY/4);
+rho(indxstart:indxend,indystart:indyend) = 1;
+
+% Synthesize some coil sensitivities
+[X,Y] = ndgrid((0:nX-1)/nX/2.0 - 0.5, (0:nY-1)/nY/2.0 - 0.5);
+C = zeros(nX,nY,4);
+C(:,:,1) = exp(-((X-.5).^2 + (Y).^2)    + 1i*(X-.5));
+C(:,:,2) = exp(-((X+.5).^2 + (Y).^2)    - 1i*(X+.5));
+C(:,:,3) = exp(-((X).^2    + (Y-.5).^2) + 1i*(Y-.5));
+C(:,:,4) = exp(-((X).^2    + (Y+.5).^2) - 1i*(Y+.5));
+nCoils = size(C,3);
+
+% Synthesize the k-space data
+nReps = 5;
+noiselevel = 0.05;
+K = zeros(nX, nY, nCoils, nReps);
+for rep = 1:nReps
+    for coil = 1:nCoils
+        noise = noiselevel * (randn(nX,nY)+1j*randn(nX,nY));
+        K(:,:,coil,rep) = fftshift(fft2(fftshift( C(:,:,coil).*rho + noise)));
+    end
+end
+
+% It is very slow to append one acquisition at a time, so we're going
+% to append a block of acquisitions at a time.
+% In this case, we'll do it one repetition at a time to show off this
+% feature.  Each block has nY aquisitions
+acqblock = ismrmrd.Acquisition(nY);
+
+% Set the header elements that don't change
+acqblock.head.version(:) = 1.0;
+acqblock.head.number_of_samples(:) = nX;
+acqblock.head.center_sample(:) = floor(nX/2);
+acqblock.head.active_channels(:) = nCoils;
+acqblock.head.read_dir  = repmat(single([1 0 0]'),[1 nY]);
+acqblock.head.phase_dir = repmat(single([0 1 0]'),[1 nY]);
+acqblock.head.slice_dir = repmat(single([0 0 1]'),[1 nY]);
+
+% Loop over the acquisitions, set the header, set the data and append
+for rep = 1:nReps
+    for acqno = 1:nY
+        
+        % Set the header elements that change from acquisition to the next
+        % c-style counting
+        acqblock.head.scan_counter(acqno) = (rep-1)*nY + acqno-1;
+        acqblock.head.idx.kspace_encode_step_1(acqno) = acqno-1; 
+        acqblock.head.idx.repetition(acqno) = rep - 1;
+        
+        % Set the flags
+        acqblock.head.flagClearAll(acqno);
+        if acqno == 1
+            acqblock.head.flagSet(acqblock.head.FLAGS.ACQ_FIRST_IN_ENCODE_STEP1, acqno);
+            acqblock.head.flagSet(acqblock.head.FLAGS.ACQ_FIRST_IN_SLICE, acqno);
+            acqblock.head.flagSet(acqblock.head.FLAGS.ACQ_FIRST_IN_REPETITION, acqno);
+        elseif acqno==size(K,2)
+            acqblock.head.flagSet(acqblock.head.FLAGS.ACQ_LAST_IN_ENCODE_STEP1, acqno);
+            acqblock.head.flagSet(acqblock.head.FLAGS.ACQ_LAST_IN_SLICE, acqno);
+            acqblock.head.flagSet(acqblock.head.FLAGS.ACQ_LAST_IN_REPETITION, acqno);
+        end
+        
+        % fill the data
+        acqblock.data{acqno} = squeeze(K(:,acqno,:,rep));
+    end
+
+    % Append the acquisition block
+    dset.appendAcquisition(acqblock);
+        
+end % rep loop
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%
+%% Fill the xml header %
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Experimental Conditions
+expcond = org.ismrm.ismrmrd.ExperimentalConditionsType;
+expcond.setH1ResonanceFrequencyHz(128000000); % 3T
+dset.xmlhdr.setExperimentalConditions(expcond);
+
+%% Acquisition System Information
+acqsysinfo = org.ismrm.ismrmrd.AcquisitionSystemInformationType;
+acqsysinfo.setReceiverChannels(java.lang.Integer(nCoils));
+dset.xmlhdr.setAcquisitionSystemInformation(acqsysinfo);
+
+%% The Encoding
+encoding = org.ismrm.ismrmrd.Encoding;
+encoding.setTrajectory(org.ismrm.ismrmrd.TrajectoryType.CARTESIAN);
+
+% Encoded Space
+fov = org.ismrm.ismrmrd.FieldOfViewMm;
+fov.setX(256);
+fov.setX(256);
+fov.setZ(5);
+matrix = org.ismrm.ismrmrd.MatrixSize;
+matrix.setX(size(K,1));
+matrix.setY(size(K,2));
+matrix.setZ(1);
+encodedspace = org.ismrm.ismrmrd.EncodingSpaceType;
+encodedspace.setMatrixSize(matrix);
+encodedspace.setFieldOfViewMm(fov);
+encoding.setEncodedSpace(encodedspace);
+
+% Recon Space
+% (same as encoding space)
+encoding.setReconSpace(encodedspace);
+
+% Encoding Limits
+% Be careful!!! All of the XML Header stuff is  JAVA so it is
+% being done with objects.  Make sure that you
+% create one object per thing you care about
+encodinglimits = org.ismrm.ismrmrd.EncodingLimitsType;
+
+limitsa = org.ismrm.ismrmrd.LimitType;
+limitsa.setMinimum(0);
+limitsa.setCenter(floor(size(K,1)/2)); 
+limitsa.setMaximum(size(K,1)-1); 
+encodinglimits.setKspaceEncodingStep0(limitsa);
+
+limitsb = org.ismrm.ismrmrd.LimitType;
+limitsb.setMinimum(0);
+limitsb.setCenter(floor(size(K,2)/2)); 
+limitsb.setMaximum(size(K,2)-1); 
+encodinglimits.setKspaceEncodingStep1(limitsb);
+
+limitsc = org.ismrm.ismrmrd.LimitType;
+limitsc.setMinimum(0);
+limitsc.setCenter(floor(nReps/2)); 
+limitsc.setMaximum(nReps-1);
+encodinglimits.setRepetition(limitsc);
+
+% All the rest are zero and we can use the same one for all of them
+limits = org.ismrm.ismrmrd.LimitType;
+limits.setMinimum(0);
+limits.setCenter(0); 
+limits.setMaximum(0);
+encodinglimits.setAverage(limits);
+encodinglimits.setContrast(limits);
+encodinglimits.setKspaceEncodingStep2(limits);
+encodinglimits.setPhase(limits);
+encodinglimits.setSegment(limits);
+encodinglimits.setSet(limits);
+encodinglimits.setSlice(limits);
+% Stuff
+encoding.setEncodingLimits(encodinglimits);
+dset.xmlhdr.getEncoding.add(encoding);
+
+%% Write the dataset
+dset.close();
diff --git a/examples/matlab/test_recon_dataset.m b/examples/matlab/test_recon_dataset.m
new file mode 100644
index 0000000..3cb0a16
--- /dev/null
+++ b/examples/matlab/test_recon_dataset.m
@@ -0,0 +1,158 @@
+%% Working with an existing ISMRMRD data set
+
+% This is a simple example of how to reconstruct images from data
+% acquired on a fully sampled cartesian grid
+%
+% Capabilities:
+%   2D/3D
+%   multiple slices/slabs
+%   multiple contrasts, repetitions
+%   
+% Limitations:
+%   only works with a single encoded space
+%   fully sampled k-space (no partial fourier or undersampling)
+%   doesn't handle averages, phases, segments and sets
+%   ignores noise scans (no pre-whitening)
+% 
+
+% We first create a data set using the example program like this:
+%   ismrmrd_generate_cartesian_shepp_logan -r 5 -C -o shepp-logan.h5
+% This will produce the file shepp-logan.h5 containing an ISMRMRD
+% dataset sampled evenly on the k-space grid -128:0.5:127.5 x -128:127
+% (i.e. oversampled by a factor of 2 in the readout direction)
+% with 8 coils, 5 repetitions and a noise level of 0.5
+% with a noise calibration scan at the beginning
+%
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
+% Loading an existing file %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
+filename = 'shepp-logan.h5';
+if exist(filename, 'file')
+    dset = ismrmrd.IsmrmrdDataset(filename, 'dataset');
+else
+    error(['File ' filename ' does not exist.  Please generate it.'])
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Read some fields from the XML header %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% We need to check if optional fields exists before trying to read them
+% Some functions return java.lang.Integer type and we convert to double
+
+%% Encoding and reconstruction information
+% Matrix size
+enc_Nx = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getX;
+enc_Ny = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getY;
+enc_Nz = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getZ;
+rec_Nx = dset.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getX;
+rec_Ny = dset.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getY;
+rec_Nz = dset.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getZ;
+
+% Field of View
+enc_FOVx = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getFieldOfViewMm.getX;
+enc_FOVy = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getFieldOfViewMm.getY;
+enc_FOVz = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getFieldOfViewMm.getZ;
+rec_FOVx = dset.xmlhdr.getEncoding.get(0).getReconSpace.getFieldOfViewMm.getX;
+rec_FOVy = dset.xmlhdr.getEncoding.get(0).getReconSpace.getFieldOfViewMm.getY;
+rec_FOVz = dset.xmlhdr.getEncoding.get(0).getReconSpace.getFieldOfViewMm.getZ;
+
+% Number of slices
+if isempty(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getSlice)
+    nSlices = 1;
+else
+    nSlices = dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getSlice.getMaximum;
+end
+
+% Number of coils, in the system information
+nCoils = double(dset.xmlhdr.getAcquisitionSystemInformation.getReceiverChannels);
+
+% Repetitions, contrasts etc.
+if isempty(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getRepetition)
+    nReps = 1;
+else
+    nReps = double(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getRepetition.getMaximum);
+end
+
+if isempty(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getContrast)
+    nContrasts = 1;
+else
+    nContrasts = double(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getContrast.getMaximum);
+end
+
+% TODO add the other possibilites
+
+%% Read all the data
+% Reading can be done one acquisition (or chunk) at a time, 
+% but this is much faster for data sets that fit into RAM.
+D = dset.readAcquisition();
+
+% Note: can select a single acquisition or header from the block, e.g.
+% acq = D.select(5);
+% hdr = D.head.select(5);
+% or you can work with them all together
+
+%% Ignore noise scans
+% TODO add a pre-whitening example
+% Find the first non-noise scan
+% This is how to check if a flag is set in the acquisition header
+isNoise = D.head.flagIsSet(D.head.FLAGS.ACQ_IS_NOISE_MEASUREMENT);
+firstScan = find(isNoise==0,1,'first');
+if firstScan > 1
+    noise = D.select(1:firstScan-1);
+else
+    noise = [];
+end
+meas  = D.select(firstScan:D.getNumber);
+clear D;
+
+%% Reconstruct images
+% Since the entire file is in memory we can use random access
+% Loop over repetitions, contrasts, slices
+reconImages = {};
+nimages = 0;
+for rep = 1:nReps
+    for contrast = 1:nContrasts
+        for slice = 1:nSlices
+            % Initialize the K-space storage array
+            K = zeros(enc_Nx, enc_Ny, enc_Nz, nCoils);
+            % Select the appropriate measurements from the data
+            acqs = find(  (meas.head.idx.contrast==(contrast-1)) ...
+                        & (meas.head.idx.repetition==(rep-1)) ...
+                        & (meas.head.idx.slice==(slice-1)));
+            for p = 1:length(acqs)
+                ky = meas.head.idx.kspace_encode_step_1(acqs(p)) + 1;
+                kz = meas.head.idx.kspace_encode_step_2(acqs(p)) + 1;
+                K(:,ky,kz,:) = meas.data{acqs(p)};
+            end
+            % Reconstruct in x
+            K = fftshift(ifft(fftshift(K,1),[],1),1);
+            % Chop if needed
+            if (enc_Nx == rec_Nx)
+                im = K;
+            else
+                ind1 = floor((enc_Nx - rec_Nx)/2)+1;
+                ind2 = floor((enc_Nx - rec_Nx)/2)+rec_Nx;
+                im = K(ind1:ind2,:,:,:);
+            end
+            % Reconstruct in y then z
+            im = fftshift(ifft(fftshift(im,2),[],2),2);
+            if size(im,3)>1
+                im = fftshift(ifft(fftshift(im,3),[],3),3);
+            end
+            
+            % Combine SOS across coils
+            im = sqrt(sum(abs(im).^2,4));
+            
+            % Append
+            nimages = nimages + 1;
+            reconImages{nimages} = im;
+        end
+    end
+end
+
+%% Display the first image
+figure
+colormap gray
+imagesc(reconImages{1}); axis image; axis off; colorbar;
diff --git a/ismrmrd.h b/ismrmrd.h
index 66cd880..9b3d031 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -46,7 +46,7 @@ typedef unsigned __int64 uint64_t;
 #define ISMRMRD_DIRECTION_LENGTH  3
 #define ISMRMRD_USER_INTS         8
 #define ISMRMRD_USER_FLOATS       8
-#define ISMRMRD_PHYS_STAMPS       8
+#define ISMRMRD_PHYS_STAMPS       8  //TODO: This should be changed to 3 (Major impact)
 #define ISMRMRD_CHANNEL_MASKS     16
 
 #ifdef __cplusplus
@@ -60,8 +60,8 @@ public:
    : bitmask_(0)
     {
       if (b > 0) {
-	bitmask_ = 1;
-	bitmask_ = (bitmask_ << (b-1));
+    bitmask_ = 1;
+    bitmask_ = (bitmask_ << (b-1));
       }
     }
   
@@ -76,40 +76,46 @@ public:
 
 /** ACQUISITION FLAGS */
 enum AcquisitionFlags {
-	/* Looping indicators */
-        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
+    /* Looping indicators */
+    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_LAST_IN_MEASUREMENT                     = 25,
+
+    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_IS_PHASECORR_DATA                       = 24,
+    ACQ_IS_RTFEEDBACK_DATA                      = 25,
+    ACQ_IS_HPFEEDBACK_DATA                      = 26,
+    ACQ_IS_DUMMYSCAN_DATA                       = 27,
+
+    ACQ_USER1                                   = 57,
+    ACQ_USER2                                   = 58,
+    ACQ_USER3                                   = 59,
+    ACQ_USER4                                   = 60,
+    ACQ_USER5                                   = 61,
+    ACQ_USER6                                   = 62,
+    ACQ_USER7                                   = 63,
+    ACQ_USER8                                   = 64
 };
 
 /**
@@ -117,16 +123,16 @@ enum AcquisitionFlags {
 
  */
 typedef 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[ISMRMRD_USER_INTS];  /**< 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[ISMRMRD_USER_INTS];  /**< Free user parameters */
 } EncodingCounters;
 
 /**
@@ -134,62 +140,62 @@ typedef struct EncodingCounters {
  */
 typedef 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[ISMRMRD_PHYS_STAMPS];       /**< 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[ISMRMRD_CHANNEL_MASKS];              /**< 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[ISMRMRD_POSITION_LENGTH];                /**< Three-dimensional spatial offsets from isocenter */
-	float              read_dir[ISMRMRD_DIRECTION_LENGTH];               /**< Directional cosines of the readout/frequency encoding */
-	float              phase_dir[ISMRMRD_DIRECTION_LENGTH];              /**< Directional cosines of the phase */
-	float              slice_dir[ISMRMRD_DIRECTION_LENGTH];              /**< Directional cosines of the slice direction */
-	float              patient_table_position[ISMRMRD_POSITION_LENGTH];  /**< Patient table off-center */
-	EncodingCounters   idx;                                              /**< Encoding loop counters, see above */
-	int32_t            user_int[ISMRMRD_USER_INTS];                      /**< Free user parameters */
-	float              user_float[ISMRMRD_USER_FLOATS];                  /**< 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[ISMRMRD_PHYS_STAMPS];       /**< 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[ISMRMRD_CHANNEL_MASKS];              /**< 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[ISMRMRD_POSITION_LENGTH];                /**< Three-dimensional spatial offsets from isocenter */
+    float              read_dir[ISMRMRD_DIRECTION_LENGTH];               /**< Directional cosines of the readout/frequency encoding */
+    float              phase_dir[ISMRMRD_DIRECTION_LENGTH];              /**< Directional cosines of the phase */
+    float              slice_dir[ISMRMRD_DIRECTION_LENGTH];              /**< Directional cosines of the slice direction */
+    float              patient_table_position[ISMRMRD_POSITION_LENGTH];  /**< Patient table off-center */
+    EncodingCounters   idx;                                              /**< Encoding loop counters, see above */
+    int32_t            user_int[ISMRMRD_USER_INTS];                      /**< Free user parameters */
+    float              user_float[ISMRMRD_USER_FLOATS];                  /**< Free user parameters */
 } AcquisitionHeader;
 
 enum ImageDataType
 {
-	DATA_FLOAT = 1,
-	DATA_DOUBLE,
-	DATA_COMPLEX_FLOAT,
-	DATA_COMPLEX_DOUBLE,
-	DATA_UNSIGNED_SHORT
+    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
+    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
+    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
 };
 
 /**
@@ -197,31 +203,31 @@ enum ImageFlags {
  */
 typedef 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[ISMRMRD_POSITION_LENGTH];               /**< Three-dimensional spatial offsets from isocenter */
-	float               read_dir[ISMRMRD_DIRECTION_LENGTH];              /**< Directional cosines of the readout/frequency encoding */
-	float               phase_dir[ISMRMRD_DIRECTION_LENGTH];             /**< Directional cosines of the phase */
-	float               slice_dir[ISMRMRD_DIRECTION_LENGTH];             /**< Directional cosines of the slice direction */
-	float               patient_table_position[ISMRMRD_POSITION_LENGTH]; /**< 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[ISMRMRD_PHYS_STAMPS];      /**< 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[ISMRMRD_USER_INTS];                     /**< Free user parameters */
-	float               user_float[ISMRMRD_USER_FLOATS];                 /**< 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[ISMRMRD_POSITION_LENGTH];               /**< Three-dimensional spatial offsets from isocenter */
+    float               read_dir[ISMRMRD_DIRECTION_LENGTH];              /**< Directional cosines of the readout/frequency encoding */
+    float               phase_dir[ISMRMRD_DIRECTION_LENGTH];             /**< Directional cosines of the phase */
+    float               slice_dir[ISMRMRD_DIRECTION_LENGTH];             /**< Directional cosines of the slice direction */
+    float               patient_table_position[ISMRMRD_POSITION_LENGTH]; /**< 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[ISMRMRD_PHYS_STAMPS];      /**< 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[ISMRMRD_USER_INTS];                     /**< Free user parameters */
+    float               user_float[ISMRMRD_USER_FLOATS];                 /**< Free user parameters */
 } ImageHeader;
 
 #ifdef __cplusplus
@@ -231,50 +237,50 @@ typedef struct ImageHeader
 template <typename T> class NDArrayContainer {
 
 public:
-	NDArrayContainer() {}
+    NDArrayContainer() {}
 
     /**
      * @brief Construct with dimensions and data
      */
-	NDArrayContainer(const std::vector<unsigned int>& dimensions) {
-		dimensions_ = dimensions;
-		data_.resize(elements());
-	}
+    NDArrayContainer(const std::vector<unsigned int>& dimensions) {
+        dimensions_ = dimensions;
+        data_.resize(elements());
+    }
 
     /**
      * @brief Construct with dimensions and data
      */
-	NDArrayContainer(const std::vector<unsigned int>& dimensions, const T* d) {
-		dimensions_ = dimensions;
-		data_.resize(elements());
-		memcpy(&data_[0],d,sizeof(T)*elements());
-	}
+    NDArrayContainer(const std::vector<unsigned int>& dimensions, const T* d) {
+        dimensions_ = dimensions;
+        data_.resize(elements());
+        memcpy(&data_[0],d,sizeof(T)*elements());
+    }
 
     /**
      * @brief Construct with dimensions and preset value
      */
-	NDArrayContainer(const std::vector<unsigned int>& dimensions, const std::valarray<T>& t) {
-		dimensions_ = dimensions;
-		data_.resize(elements());
-		data_ = t;
-	}
-
-	virtual ~NDArrayContainer() {}
-
-	std::vector<unsigned int> dimensions_; /**< Array with dimensions of the array. First dimension is fastest moving in the array */
-	std::valarray<T> data_;               /**< The data itself. A vector is used here for easy memory management                  */
-
-	size_t elements() const {
-		if (dimensions_.size() == 0) {
-			return 0;
-		}
-		size_t elements = 1;
-		std::vector<unsigned int>::const_iterator it = dimensions_.begin();
-		while (it != dimensions_.end()) {
-			elements *= *(it++);
-		}
-		return elements;
-	}
+    NDArrayContainer(const std::vector<unsigned int>& dimensions, const std::valarray<T>& t) {
+        dimensions_ = dimensions;
+        data_.resize(elements());
+        data_ = t;
+    }
+
+    virtual ~NDArrayContainer() {}
+
+    std::vector<unsigned int> dimensions_; /**< Array with dimensions of the array. First dimension is fastest moving in the array */
+    std::valarray<T> data_;               /**< The data itself. A vector is used here for easy memory management                  */
+
+    size_t elements() const {
+        if (dimensions_.size() == 0) {
+            return 0;
+        }
+        size_t elements = 1;
+        std::vector<unsigned int>::const_iterator it = dimensions_.begin();
+        while (it != dimensions_.end()) {
+            elements *= *(it++);
+        }
+        return elements;
+    }
 
     T& operator[] (const size_t& p) {
         return data_[p];
@@ -292,16 +298,16 @@ public:
         data_.resize(s,t);
     }
 
-	bool is_consistent() const {
-		return (elements() == data_.size());
-	}
+    bool is_consistent() const {
+        return (elements() == data_.size());
+    }
 
-	size_t ndims() const {
-		size_t i = 1, n_dimensions = 1;
-		for (; i < dimensions_.size(); i++)
-			n_dimensions += (size_t) (dimensions_[i] > 1);
-		return n_dimensions;
-	}
+    size_t ndims() const {
+        size_t i = 1, n_dimensions = 1;
+        for (; i < dimensions_.size(); i++)
+            n_dimensions += (size_t) (dimensions_[i] > 1);
+        return n_dimensions;
+    }
 
 };
 
@@ -312,227 +318,227 @@ template <typename T>
 class Image {
 
 public:
-	Image(unsigned int matrix_size_x = 0,
-		  unsigned int matrix_size_y = 1,
-		  unsigned int matrix_size_z = 1,
-		  unsigned int channels      = 1)
+    Image(unsigned int matrix_size_x = 0,
+          unsigned int matrix_size_y = 1,
+          unsigned int matrix_size_z = 1,
+          unsigned int channels      = 1)
     {
-		memset(&head_,0,sizeof(ImageHeader));
-		head_.version = ISMRMRD_VERSION;
+        memset(&head_,0,sizeof(ImageHeader));
+        head_.version = ISMRMRD_VERSION;
         head_.matrix_size[0] = matrix_size_x;
         head_.matrix_size[1] = matrix_size_y;
         head_.matrix_size[2] = matrix_size_z;
         head_.channels       = channels;
         setSpecificDataType();
         makeConsistent();
-	}
+    }
 
 
     Image(const Image& a) {   // copy constructor
-		if (this != &a) {
+        if (this != &a) {
             head_ = a.head_;
             this->data_ = a.data_;
             makeConsistent();
-		}
-	}
+        }
+    }
 
-	Image& operator=(const Image& a) {
-		if (this != &a) {
+    Image& operator=(const Image& a) {
+        if (this != &a) {
             head_ = a.head_;
             this->data_ = a.data_;
             makeConsistent();
-		}
-		return *this;
-	}
+        }
+        return *this;
+    }
 
-	~Image() {}
+    ~Image() {}
 
-	bool isFlagSet(FlagBit& f) const {
-		return f.isSet(head_.flags);
-	}
+    bool isFlagSet(FlagBit& f) const {
+        return f.isSet(head_.flags);
+    }
 
-	void setFlag(FlagBit& f) {
-		head_.flags |= f.bitmask_;
-	}
+    void setFlag(FlagBit& f) {
+        head_.flags |= f.bitmask_;
+    }
 
-	size_t getNumberOfElements() const {
-		return head_.matrix_size[0]*
+    size_t getNumberOfElements() const {
+        return head_.matrix_size[0]*
             head_.matrix_size[1]*
             head_.matrix_size[2]*
             head_.channels;
-	}
+    }
+
+
+    uint32_t getAcquisitionTimeStamp() const {
+        return head_.acquisition_time_stamp;
+    }
+
+    void setAcquisitionTimeStamp(uint32_t acquisitionTimeStamp) {
+        head_.acquisition_time_stamp = acquisitionTimeStamp;
+    }
+
+    uint16_t getAverage() const {
+        return head_.average;
+    }
+
+    void setAverage(uint16_t average) {
+        this->head_.average = average;
+    }
+
+    uint16_t getChannels() const {
+        return head_.channels;
+    }
+
+    void setChannels(uint16_t channels) {
+        this->head_.channels = channels;
+    }
+
+    uint16_t getContrast() const {
+        return head_.contrast;
+    }
+
+    void setContrast(uint16_t contrast) {
+        this->head_.contrast = contrast;
+    }
+
+    float getFieldOfViewX() const {
+        return head_.field_of_view[0];
+    }
+
+    void setFieldOfViewX(float f) {
+        head_.field_of_view[0] = f;
+    }
+
+    float getFieldOfViewY() const {
+        return head_.field_of_view[1];
+    }
+
+    void setFieldOfViewY(float f) {
+        head_.field_of_view[1] = f;
+    }
+
+    float getFieldOfViewZ() const {
+        return head_.field_of_view[2];
+    }
+
+    void setFieldOfViewZ(float f) {
+        head_.field_of_view[2] = f;
+    }
+
+    uint64_t getFlags() const {
+        return head_.flags;
+    }
+
+    void setFlags(uint64_t flags) {
+        this->head_.flags = flags;
+    }
+
+    uint16_t getImageDataType() const {
+        return head_.image_data_type;
+    }
+
+    void setImageDataType(uint16_t imageDataType) {
+        head_.image_data_type = imageDataType;
+    }
+
+    uint16_t getImageIndex() const {
+        return head_.image_index;
+    }
+
+    void setImageIndex(uint16_t imageIndex) {
+        head_.image_index = imageIndex;
+    }
+
+    uint16_t getImageSeriesIndex() const {
+        return head_.image_series_index;
+    }
+
+    void setImageSeriesIndex(uint16_t imageSeriesIndex) {
+        head_.image_series_index = imageSeriesIndex;
+    }
+
+    uint16_t getImageType() const {
+        return head_.image_type;
+    }
+
+    void setImageType(uint16_t imageType) {
+        head_.image_type = imageType;
+    }
 
+    uint16_t getMatrixSizeX() const {
+        return head_.matrix_size[0];
+    }
 
-	uint32_t getAcquisitionTimeStamp() const {
-		return head_.acquisition_time_stamp;
-	}
+    void setMatrixSizeX(uint16_t s) {
+        head_.matrix_size[0] = s;
+        makeConsistent();
+    }
 
-	void setAcquisitionTimeStamp(uint32_t acquisitionTimeStamp) {
-		head_.acquisition_time_stamp = acquisitionTimeStamp;
-	}
+    uint16_t getMatrixSizeY() const {
+        return head_.matrix_size[1];
+    }
 
-	uint16_t getAverage() const {
-		return head_.average;
-	}
+    void setMatrixSizeY(uint16_t s) {
+        head_.matrix_size[1] = s;
+        makeConsistent();
+    }
 
-	void setAverage(uint16_t average) {
-		this->head_.average = average;
-	}
+    uint16_t getMatrixSizeZ() const {
+        return head_.matrix_size[2];
+    }
 
-	uint16_t getChannels() const {
-		return head_.channels;
-	}
+    void setMatrixSizeZ(uint16_t s) {
+        head_.matrix_size[2] = s;
+        makeConsistent();
+    }
 
-	void setChannels(uint16_t channels) {
-		this->head_.channels = channels;
-	}
 
-	uint16_t getContrast() const {
-		return head_.contrast;
-	}
+    uint32_t getMeasurementUid() const {
+        return head_.measurement_uid;
+    }
 
-	void setContrast(uint16_t contrast) {
-		this->head_.contrast = contrast;
-	}
+    void setMeasurementUid(uint32_t measurementUid) {
+        head_.measurement_uid = measurementUid;
+    }
 
-	float getFieldOfViewX() const {
-		return head_.field_of_view[0];
-	}
+    const float getPatientTablePosition(unsigned int axis) const {
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            return head_.patient_table_position[axis];
+        }
+        return 0;
+    }
 
-	void setFieldOfViewX(float f) {
-		head_.field_of_view[0] = f;
-	}
+    void setPatientTablePosition(unsigned int axis, float value) {
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            head_.patient_table_position[axis] = value;
+        }
+    }
 
-	float getFieldOfViewY() const {
-		return head_.field_of_view[1];
-	}
+    const uint32_t getPhysiologyTimeStamp(unsigned int stamp_id) const {
+        if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+            return head_.physiology_time_stamp[stamp_id];
+        }
+        return 0;
+    }
 
-	void setFieldOfViewY(float f) {
-		head_.field_of_view[1] = f;
-	}
+    void setPhysiologyTimeStamp(unsigned int stamp_id, uint32_t value){
+        if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+            head_.physiology_time_stamp[stamp_id] = value;
+        }
+    }
 
-	float getFieldOfViewZ() const {
-		return head_.field_of_view[2];
-	}
+    const float getPosition(unsigned int axis) const {
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            return head_.position[axis];
+        }
+        return 0;
+    }
 
-	void setFieldOfViewZ(float f) {
-		head_.field_of_view[2] = f;
-	}
-
-	uint64_t getFlags() const {
-		return head_.flags;
-	}
-
-	void setFlags(uint64_t flags) {
-		this->head_.flags = flags;
-	}
-
-	uint16_t getImageDataType() const {
-		return head_.image_data_type;
-	}
-
-	void setImageDataType(uint16_t imageDataType) {
-		head_.image_data_type = imageDataType;
-	}
-
-	uint16_t getImageIndex() const {
-		return head_.image_index;
-	}
-
-	void setImageIndex(uint16_t imageIndex) {
-		head_.image_index = imageIndex;
-	}
-
-	uint16_t getImageSeriesIndex() const {
-		return head_.image_series_index;
-	}
-
-	void setImageSeriesIndex(uint16_t imageSeriesIndex) {
-		head_.image_series_index = imageSeriesIndex;
-	}
-
-	uint16_t getImageType() const {
-		return head_.image_type;
-	}
-
-	void setImageType(uint16_t imageType) {
-		head_.image_type = imageType;
-	}
-
-	uint16_t getMatrixSizeX() const {
-		return head_.matrix_size[0];
-	}
-
-	void setMatrixSizeX(uint16_t s) {
-		head_.matrix_size[0] = s;
-		makeConsistent();
-	}
-
-	uint16_t getMatrixSizeY() const {
-		return head_.matrix_size[1];
-	}
-
-	void setMatrixSizeY(uint16_t s) {
-		head_.matrix_size[1] = s;
-		makeConsistent();
-	}
-
-	uint16_t getMatrixSizeZ() const {
-		return head_.matrix_size[2];
-	}
-
-	void setMatrixSizeZ(uint16_t s) {
-		head_.matrix_size[2] = s;
-		makeConsistent();
-	}
-
-
-	uint32_t getMeasurementUid() const {
-		return head_.measurement_uid;
-	}
-
-	void setMeasurementUid(uint32_t measurementUid) {
-		head_.measurement_uid = measurementUid;
-	}
-
-	const float getPatientTablePosition(unsigned int axis) const {
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			return head_.patient_table_position[axis];
-		}
-		return 0;
-	}
-
-	void setPatientTablePosition(unsigned int axis, float value) {
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			head_.patient_table_position[axis] = value;
-		}
-	}
-
-	const uint32_t getPhysiologyTimeStamp(unsigned int stamp_id) const {
-		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
-			return head_.physiology_time_stamp[stamp_id];
-		}
-		return 0;
-	}
-
-	void setPhysiologyTimeStamp(unsigned int stamp_id, uint32_t value){
-		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
-			head_.physiology_time_stamp[stamp_id] = value;
-		}
-	}
-
-	const float getPosition(unsigned int axis) const {
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			return head_.position[axis];
-		}
-		return 0;
-	}
-
-	void setPosition(unsigned int axis, float value){
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			head_.position[axis] = value;
-		}
-	}
+    void setPosition(unsigned int axis, float value){
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            head_.position[axis] = value;
+        }
+    }
 
         const float getReadDirection(unsigned int index) const {
                 if (index < ISMRMRD_DIRECTION_LENGTH) {
@@ -573,89 +579,89 @@ public:
                 }
         }
 
-	uint16_t getPhase() const {
-		return head_.phase;
-	}
-
-	void setPhase(uint16_t phase) {
-		this->head_.phase = phase;
-	}
-
-
-	uint16_t getRepetition() const {
-		return head_.repetition;
-	}
-
-	void setRepetition(uint16_t repetition) {
-		this->head_.repetition = repetition;
-	}
-
-	uint16_t getSet() const {
-		return head_.set;
-	}
-
-	void setSet(uint16_t set) {
-		this->head_.set = set;
-	}
-
-	uint16_t getSlice() const {
-		return head_.slice;
-	}
-
-	void setSlice(uint16_t slice) {
-		this->head_.slice = slice;
-	}
-
-	const float getUserFloat(unsigned int index) const {
-		if (index < ISMRMRD_USER_FLOATS) {
-			return head_.user_float[index];
-		}
-		return 0.0f;
-	}
-
-	void setUserFloat(unsigned int index, float value) {
-		if (index < ISMRMRD_USER_FLOATS) {
-			head_.user_float[index] = value;
-		}
-	}
-
-	const int32_t getUserInt(unsigned int index) const {
-		if (index < ISMRMRD_USER_INTS) {
-			return head_.user_int[index];
-		}
-		return 0;
-	}
-
-	void setUserInt(unsigned int index, int32_t value) {
-		if (index < ISMRMRD_USER_INTS) {
-			head_.user_int[index] = value;
-		}
-	}
-
-	uint16_t getVersion() const {
-		return head_.version;
-	}
-
-	void setVersion(uint16_t version) {
-		this->head_.version = version;
-	}
-
-	const std::valarray<T>& getData() const {
-		return data_;
-	}
-
-	void setData(const std::valarray<T>& data) {
-		data_ = data;
-	}
-
-	const ImageHeader& getHead() const {
-		return head_;
-	}
-
-	void setHead(const ImageHeader& head) {
-		head_ = head;
-		makeConsistent();
-	}
+    uint16_t getPhase() const {
+        return head_.phase;
+    }
+
+    void setPhase(uint16_t phase) {
+        this->head_.phase = phase;
+    }
+
+
+    uint16_t getRepetition() const {
+        return head_.repetition;
+    }
+
+    void setRepetition(uint16_t repetition) {
+        this->head_.repetition = repetition;
+    }
+
+    uint16_t getSet() const {
+        return head_.set;
+    }
+
+    void setSet(uint16_t set) {
+        this->head_.set = set;
+    }
+
+    uint16_t getSlice() const {
+        return head_.slice;
+    }
+
+    void setSlice(uint16_t slice) {
+        this->head_.slice = slice;
+    }
+
+    const float getUserFloat(unsigned int index) const {
+        if (index < ISMRMRD_USER_FLOATS) {
+            return head_.user_float[index];
+        }
+        return 0.0f;
+    }
+
+    void setUserFloat(unsigned int index, float value) {
+        if (index < ISMRMRD_USER_FLOATS) {
+            head_.user_float[index] = value;
+        }
+    }
+
+    const int32_t getUserInt(unsigned int index) const {
+        if (index < ISMRMRD_USER_INTS) {
+            return head_.user_int[index];
+        }
+        return 0;
+    }
+
+    void setUserInt(unsigned int index, int32_t value) {
+        if (index < ISMRMRD_USER_INTS) {
+            head_.user_int[index] = value;
+        }
+    }
+
+    uint16_t getVersion() const {
+        return head_.version;
+    }
+
+    void setVersion(uint16_t version) {
+        this->head_.version = version;
+    }
+
+    const std::valarray<T>& getData() const {
+        return data_;
+    }
+
+    void setData(const std::valarray<T>& data) {
+        data_ = data;
+    }
+
+    const ImageHeader& getHead() const {
+        return head_;
+    }
+
+    void setHead(const ImageHeader& head) {
+        head_ = head;
+        makeConsistent();
+    }
 
     T& operator[] (const size_t& p) {
         return data_[p];
@@ -667,36 +673,36 @@ public:
 
 
 protected:
-	ImageHeader head_;     /**< ImageHeader as defined above */
-	std::valarray<T> data_;
-	void makeConsistent() {
-		if (getNumberOfElements() != data_.size()) {
-			data_.resize(getNumberOfElements());
-		}
-	}
+    ImageHeader head_;     /**< ImageHeader as defined above */
+    std::valarray<T> data_;
+    void makeConsistent() {
+        if (getNumberOfElements() != data_.size()) {
+            data_.resize(getNumberOfElements());
+        }
+    }
 
-	void setSpecificDataType();
+    void setSpecificDataType();
 
 };
 
 template <> inline void Image<float>::setSpecificDataType() {
-	head_.image_data_type = DATA_FLOAT;
+    head_.image_data_type = DATA_FLOAT;
 }
 
 template <> inline void Image<double>::setSpecificDataType() {
-	head_.image_data_type = DATA_DOUBLE;
+    head_.image_data_type = DATA_DOUBLE;
 }
 
 template <> inline void Image< std::complex<float> >::setSpecificDataType() {
-	head_.image_data_type = DATA_COMPLEX_FLOAT;
+    head_.image_data_type = DATA_COMPLEX_FLOAT;
 }
 
 template <> inline void Image< std::complex<double> >::setSpecificDataType() {
-	head_.image_data_type = DATA_COMPLEX_DOUBLE;
+    head_.image_data_type = DATA_COMPLEX_DOUBLE;
 }
 
 template <> inline void Image< unsigned short >::setSpecificDataType() {
-	head_.image_data_type = DATA_UNSIGNED_SHORT;
+    head_.image_data_type = DATA_UNSIGNED_SHORT;
 }
 
 
@@ -717,207 +723,207 @@ template <> inline void Image< unsigned short >::setSpecificDataType() {
 class Acquisition {
 
 public:
-	Acquisition()
+    Acquisition()
         : traj_(), data_() {
-		memset(&head_,0,sizeof(AcquisitionHeader));
-		head_.version = ISMRMRD_VERSION;
-	}
-
-	~Acquisition() {}
-
-	Acquisition (const Acquisition& a) {   // copy constructor
-		if (this != &a) {
-			head_ = a.head_;
-			data_.resize(a.data_.size());
-			memcpy(&data_[0],&a.data_[0],sizeof(float)*a.data_.size());
-			traj_.resize(a.traj_.size());
-			memcpy(&traj_[0],&a.traj_[0],sizeof(float)*a.traj_.size());
-		}
-	}
-
-	Acquisition& operator=(const Acquisition& a) {
-		if (this != &a) {
+        memset(&head_,0,sizeof(AcquisitionHeader));
+        head_.version = ISMRMRD_VERSION;
+    }
+
+    ~Acquisition() {}
+
+    Acquisition (const Acquisition& a) {   // copy constructor
+        if (this != &a) {
+            head_ = a.head_;
+            data_.resize(a.data_.size());
+            memcpy(&data_[0],&a.data_[0],sizeof(float)*a.data_.size());
+            traj_.resize(a.traj_.size());
+            memcpy(&traj_[0],&a.traj_[0],sizeof(float)*a.traj_.size());
+        }
+    }
+
+    Acquisition& operator=(const Acquisition& a) {
+        if (this != &a) {
             head_ = a.head_;
-			data_.resize(a.data_.size());
-			memcpy(&data_[0],&a.data_[0],sizeof(float)*a.data_.size());
-			traj_.resize(a.traj_.size());
-			memcpy(&traj_[0],&a.traj_[0],sizeof(float)*a.traj_.size());
-		}
-		return *this;
-	}
-
-	const AcquisitionHeader& getHead() {
-		return head_;
-	}
-
-	void setHead(const AcquisitionHeader& h) {
-		head_ = h;
-		makeConsistent();
-	}
-
-	bool isFlagSet(const FlagBit& f) const {
-		return f.isSet(head_.flags);
-	}
-
-	void setFlag(const FlagBit& f) {
-		head_.flags |= f.bitmask_;
-	}
-
-	uint32_t getAcquisitionTimeStamp() const {
-		return head_.acquisition_time_stamp;
-	}
-
-	void setAcquisitionTimeStamp(uint32_t acquisitionTimeStamp) {
-		head_.acquisition_time_stamp = acquisitionTimeStamp;
-	}
-
-	uint16_t getActiveChannels() const {
-		return head_.active_channels;
-	}
-
-	void setActiveChannels(uint16_t activeChannels) {
-		head_.active_channels = activeChannels;
-		makeConsistent();
-	}
-
-	uint16_t getAvailableChannels() const {
-		return head_.available_channels;
-	}
-
-	void setAvailableChannels(uint16_t availableChannels) {
-		head_.available_channels = availableChannels;
-	}
-
-	uint16_t getCenterSample() const {
-		return head_.center_sample;
-	}
-
-	void setCenterSample(uint16_t centerSample) {
-		head_.center_sample = centerSample;
-	}
-
-	bool isChannelActive(unsigned int channel_id) {
-		if (channel_id < 64*ISMRMRD_CHANNEL_MASKS) {
-			unsigned int mask_idx = channel_id>>6;
-			unsigned int mask_bit = channel_id-mask_idx*64;
-			return ((head_.channel_mask[mask_idx] & ( (uint64_t)1 << mask_bit)) > 0);
-		}
-		return false;
-	}
-
-	void setChannelActive(unsigned int channel_id) {
-		if (channel_id < 64*ISMRMRD_CHANNEL_MASKS) {
-			unsigned int mask_idx = channel_id>>6;
-			unsigned int mask_bit = channel_id-mask_idx*64;
-			head_.channel_mask[mask_idx] |= ( (uint64_t)1 << mask_bit);
-		}
-	}
-
-	unsigned int getActiveChannelBits() {
-		unsigned int bits = 0;
-		for (unsigned int i = 0; i < ISMRMRD_CHANNEL_MASKS*64; i++) {
-			if (isChannelActive(i)) {
-				bits++;
-			}
-		}
-		return bits;
-	}
-
-	uint16_t getDiscardPost() const {
-		return head_.discard_post;
-	}
-
-	void setDiscardPost(uint16_t discardPost) {
-		head_.discard_post = discardPost;
-	}
-
-	uint16_t getDiscardPre() const {
-		return head_.discard_pre;
-	}
-
-	void setDiscardPre(uint16_t discardPre) {
-		head_.discard_pre = discardPre;
-	}
-
-	uint16_t getEncodingSpaceRef() const {
-		return head_.encoding_space_ref;
-	}
-
-	void setEncodingSpaceRef(uint16_t encodingSpaceRef) {
-		head_.encoding_space_ref = encodingSpaceRef;
-	}
-
-	uint64_t getFlags() const {
-		return head_.flags;
-	}
-
-	void setFlags(uint64_t flags) {
-		this->head_.flags = flags;
-	}
-
-	EncodingCounters& getIdx() {
-		return head_.idx;
-	}
-
-	void setIdx(const EncodingCounters& idx) {
-		this->head_.idx = idx;
-	}
-
-	uint32_t getMeasurementUid() const {
-		return head_.measurement_uid;
-	}
-
-	void setMeasurementUid(uint32_t measurementUid) {
-		head_.measurement_uid = measurementUid;
-	}
-
-	uint16_t getNumberOfSamples() const {
-		return head_.number_of_samples;
-	}
-
-	void setNumberOfSamples(uint16_t numberOfSamples) {
-		head_.number_of_samples = numberOfSamples;
-		makeConsistent();
-	}
-
-	const float getPatientTablePosition(unsigned int axis) const {
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			return head_.patient_table_position[axis];
-		}
-		return 0;
-	}
-
-	void setPatientTablePosition(unsigned int axis, float value) {
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			head_.patient_table_position[axis] = value;
-		}
-	}
-
-	const uint32_t getPhysiologyTimeStamp(unsigned int stamp_id) const {
-		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
-			return head_.physiology_time_stamp[stamp_id];
-		}
-		return 0;
-	}
-
-	void setPhysiologyTimeStamp(unsigned int stamp_id, uint32_t value){
-		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
-			head_.physiology_time_stamp[stamp_id] = value;
-		}
-	}
-
-	const float getPosition(unsigned int axis) const {
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			return head_.position[axis];
-		}
-		return 0;
-	}
-
-	void setPosition(unsigned int axis, float value){
-		if (axis < ISMRMRD_POSITION_LENGTH) {
-			head_.position[axis] = value;
-		}
-	}
+            data_.resize(a.data_.size());
+            memcpy(&data_[0],&a.data_[0],sizeof(float)*a.data_.size());
+            traj_.resize(a.traj_.size());
+            memcpy(&traj_[0],&a.traj_[0],sizeof(float)*a.traj_.size());
+        }
+        return *this;
+    }
+
+    const AcquisitionHeader& getHead() {
+        return head_;
+    }
+
+    void setHead(const AcquisitionHeader& h) {
+        head_ = h;
+        makeConsistent();
+    }
+
+    bool isFlagSet(const FlagBit& f) const {
+        return f.isSet(head_.flags);
+    }
+
+    void setFlag(const FlagBit& f) {
+        head_.flags |= f.bitmask_;
+    }
+
+    uint32_t getAcquisitionTimeStamp() const {
+        return head_.acquisition_time_stamp;
+    }
+
+    void setAcquisitionTimeStamp(uint32_t acquisitionTimeStamp) {
+        head_.acquisition_time_stamp = acquisitionTimeStamp;
+    }
+
+    uint16_t getActiveChannels() const {
+        return head_.active_channels;
+    }
+
+    void setActiveChannels(uint16_t activeChannels) {
+        head_.active_channels = activeChannels;
+        makeConsistent();
+    }
+
+    uint16_t getAvailableChannels() const {
+        return head_.available_channels;
+    }
+
+    void setAvailableChannels(uint16_t availableChannels) {
+        head_.available_channels = availableChannels;
+    }
+
+    uint16_t getCenterSample() const {
+        return head_.center_sample;
+    }
+
+    void setCenterSample(uint16_t centerSample) {
+        head_.center_sample = centerSample;
+    }
+
+    bool isChannelActive(unsigned int channel_id) {
+        if (channel_id < 64*ISMRMRD_CHANNEL_MASKS) {
+            unsigned int mask_idx = channel_id>>6;
+            unsigned int mask_bit = channel_id-mask_idx*64;
+            return ((head_.channel_mask[mask_idx] & ( (uint64_t)1 << mask_bit)) > 0);
+        }
+        return false;
+    }
+
+    void setChannelActive(unsigned int channel_id) {
+        if (channel_id < 64*ISMRMRD_CHANNEL_MASKS) {
+            unsigned int mask_idx = channel_id>>6;
+            unsigned int mask_bit = channel_id-mask_idx*64;
+            head_.channel_mask[mask_idx] |= ( (uint64_t)1 << mask_bit);
+        }
+    }
+
+    unsigned int getActiveChannelBits() {
+        unsigned int bits = 0;
+        for (unsigned int i = 0; i < ISMRMRD_CHANNEL_MASKS*64; i++) {
+            if (isChannelActive(i)) {
+                bits++;
+            }
+        }
+        return bits;
+    }
+
+    uint16_t getDiscardPost() const {
+        return head_.discard_post;
+    }
+
+    void setDiscardPost(uint16_t discardPost) {
+        head_.discard_post = discardPost;
+    }
+
+    uint16_t getDiscardPre() const {
+        return head_.discard_pre;
+    }
+
+    void setDiscardPre(uint16_t discardPre) {
+        head_.discard_pre = discardPre;
+    }
+
+    uint16_t getEncodingSpaceRef() const {
+        return head_.encoding_space_ref;
+    }
+
+    void setEncodingSpaceRef(uint16_t encodingSpaceRef) {
+        head_.encoding_space_ref = encodingSpaceRef;
+    }
+
+    uint64_t getFlags() const {
+        return head_.flags;
+    }
+
+    void setFlags(uint64_t flags) {
+        this->head_.flags = flags;
+    }
+
+    EncodingCounters& getIdx() {
+        return head_.idx;
+    }
+
+    void setIdx(const EncodingCounters& idx) {
+        this->head_.idx = idx;
+    }
+
+    uint32_t getMeasurementUid() const {
+        return head_.measurement_uid;
+    }
+
+    void setMeasurementUid(uint32_t measurementUid) {
+        head_.measurement_uid = measurementUid;
+    }
+
+    uint16_t getNumberOfSamples() const {
+        return head_.number_of_samples;
+    }
+
+    void setNumberOfSamples(uint16_t numberOfSamples) {
+        head_.number_of_samples = numberOfSamples;
+        makeConsistent();
+    }
+
+    const float getPatientTablePosition(unsigned int axis) const {
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            return head_.patient_table_position[axis];
+        }
+        return 0;
+    }
+
+    void setPatientTablePosition(unsigned int axis, float value) {
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            head_.patient_table_position[axis] = value;
+        }
+    }
+
+    const uint32_t getPhysiologyTimeStamp(unsigned int stamp_id) const {
+        if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+            return head_.physiology_time_stamp[stamp_id];
+        }
+        return 0;
+    }
+
+    void setPhysiologyTimeStamp(unsigned int stamp_id, uint32_t value){
+        if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+            head_.physiology_time_stamp[stamp_id] = value;
+        }
+    }
+
+    const float getPosition(unsigned int axis) const {
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            return head_.position[axis];
+        }
+        return 0;
+    }
+
+    void setPosition(unsigned int axis, float value){
+        if (axis < ISMRMRD_POSITION_LENGTH) {
+            head_.position[axis] = value;
+        }
+    }
 
         const float getReadDirection(unsigned int index) const {
                 if (index < ISMRMRD_DIRECTION_LENGTH) {
@@ -958,80 +964,80 @@ public:
                 }
         }
 
-	float getSampleTimeUs() const {
-		return head_.sample_time_us;
-	}
-
-	void setSampleTimeUs(float sampleTimeUs) {
-		head_.sample_time_us = sampleTimeUs;
-	}
-
-	uint32_t getScanCounter() const {
-		return head_.scan_counter;
-	}
-
-	void setScanCounter(uint32_t scanCounter) {
-		head_.scan_counter = scanCounter;
-	}
-
-	uint16_t getTrajectoryDimensions() const {
-		return head_.trajectory_dimensions;
-	}
-
-	void setTrajectoryDimensions(uint16_t trajectoryDimensions) {
-		head_.trajectory_dimensions = trajectoryDimensions;
-		makeConsistent();
-	}
-
-	const float getUserFloat(unsigned int index) const {
-		if (index < ISMRMRD_USER_FLOATS) {
-			return head_.user_float[index];
-		}
-		return 0.0f;
-	}
-
-	void setUserFloat(unsigned int index, float value) {
-		if (index < ISMRMRD_USER_FLOATS) {
-			head_.user_float[index] = value;
-		}
-	}
-
-	const int32_t getUserInt(unsigned int index) const {
-		if (index < ISMRMRD_USER_INTS) {
-			return head_.user_int[index];
-		}
-		return 0;
-	}
-
-	void setUserInt(unsigned int index, int32_t value) {
-		if (index < ISMRMRD_USER_INTS) {
-			head_.user_int[index] = value;
-		}
-	}
-
-	uint16_t getVersion() const {
-		return head_.version;
-	}
-
-	void setVersion(uint16_t version) {
-		this->head_.version = version;
-	}
-
-	const std::valarray<float>& getData() const {
-		return data_;
-	}
-
-	void setData(const std::valarray<float>& data) {
-		data_ = data;
-	}
-
-	const std::valarray<float>& getTraj() const {
-		return traj_;
-	}
-
-	void setTraj(const std::valarray<float>& traj) {
-		traj_ = traj;
-	}
+    float getSampleTimeUs() const {
+        return head_.sample_time_us;
+    }
+
+    void setSampleTimeUs(float sampleTimeUs) {
+        head_.sample_time_us = sampleTimeUs;
+    }
+
+    uint32_t getScanCounter() const {
+        return head_.scan_counter;
+    }
+
+    void setScanCounter(uint32_t scanCounter) {
+        head_.scan_counter = scanCounter;
+    }
+
+    uint16_t getTrajectoryDimensions() const {
+        return head_.trajectory_dimensions;
+    }
+
+    void setTrajectoryDimensions(uint16_t trajectoryDimensions) {
+        head_.trajectory_dimensions = trajectoryDimensions;
+        makeConsistent();
+    }
+
+    const float getUserFloat(unsigned int index) const {
+        if (index < ISMRMRD_USER_FLOATS) {
+            return head_.user_float[index];
+        }
+        return 0.0f;
+    }
+
+    void setUserFloat(unsigned int index, float value) {
+        if (index < ISMRMRD_USER_FLOATS) {
+            head_.user_float[index] = value;
+        }
+    }
+
+    const int32_t getUserInt(unsigned int index) const {
+        if (index < ISMRMRD_USER_INTS) {
+            return head_.user_int[index];
+        }
+        return 0;
+    }
+
+    void setUserInt(unsigned int index, int32_t value) {
+        if (index < ISMRMRD_USER_INTS) {
+            head_.user_int[index] = value;
+        }
+    }
+
+    uint16_t getVersion() const {
+        return head_.version;
+    }
+
+    void setVersion(uint16_t version) {
+        this->head_.version = version;
+    }
+
+    const std::valarray<float>& getData() const {
+        return data_;
+    }
+
+    void setData(const std::valarray<float>& data) {
+        data_ = data;
+    }
+
+    const std::valarray<float>& getTraj() const {
+        return traj_;
+    }
+
+    void setTraj(const std::valarray<float>& traj) {
+        traj_ = traj;
+    }
 
     float& operator[] (const size_t& p) {
         return data_[p];
@@ -1042,28 +1048,28 @@ public:
     }
 
 protected:
-	size_t calcTrajLength() {
-		return head_.trajectory_dimensions*head_.number_of_samples;
-	}
-
-	size_t calcDataLength() {
-		return head_.active_channels*head_.number_of_samples*2;
-	}
-
-
-	void makeConsistent() {
-		if (head_.active_channels > head_.available_channels) {
-			head_.available_channels = head_.active_channels;
-		}
-		if (calcTrajLength() != traj_.size()) {
-			traj_.resize(calcTrajLength());
-		}
-		if (calcDataLength() != data_.size()) {
-			data_.resize(calcDataLength());
-		}
-	}
-
-	AcquisitionHeader head_; /**< Header, see above */
+    size_t calcTrajLength() {
+        return head_.trajectory_dimensions*head_.number_of_samples;
+    }
+
+    size_t calcDataLength() {
+        return head_.active_channels*head_.number_of_samples*2;
+    }
+
+
+    void makeConsistent() {
+        if (head_.active_channels > head_.available_channels) {
+            head_.available_channels = head_.active_channels;
+        }
+        if (calcTrajLength() != traj_.size()) {
+            traj_.resize(calcTrajLength());
+        }
+        if (calcDataLength() != data_.size()) {
+            data_.resize(calcDataLength());
+        }
+    }
+
+    AcquisitionHeader head_; /**< Header, see above */
     std::valarray<float> traj_;
     std::valarray<float> data_;
 
diff --git a/ismrmrd_hdf5_datatypes.h b/ismrmrd_hdf5_datatypes.h
index 016897b..ea6e75f 100644
--- a/ismrmrd_hdf5_datatypes.h
+++ b/ismrmrd_hdf5_datatypes.h
@@ -96,6 +96,8 @@ template <> inline boost::shared_ptr<DataType> getIsmrmrdHDF5Type<AcquisitionHea
 	ret->insertMember( "scan_counter", 				HOFFSET(AcquisitionHeader, scan_counter), 			PredType::NATIVE_UINT32);
 	ret->insertMember( "acquisition_time_stamp", 	HOFFSET(AcquisitionHeader, acquisition_time_stamp), PredType::NATIVE_UINT32);
 
+        // TODO: change ISMRMRD_PHYS_STAMPS to 3 (Major change)
+        // we should use the size defines and not hard coded numbers.
 	std::vector<hsize_t> dims(1,3);
 	boost::shared_ptr<DataType> array_type(new ArrayType(PredType::NATIVE_UINT32, 1, &dims[0]));
 	ret->insertMember( "physiology_time_stamp", HOFFSET(AcquisitionHeader, physiology_time_stamp), 		*array_type);
@@ -244,6 +246,8 @@ template <> inline boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader>()
 	ret->insertMember( "set",   					HOFFSET(ImageHeader, set), 						PredType::NATIVE_UINT16);
 	ret->insertMember( "acquisition_time_stamp", 	HOFFSET(ImageHeader, acquisition_time_stamp),   PredType::NATIVE_UINT32);
 
+        // TODO: ISMRMRD_PHYS_STAMPS should be 3 (Major change)
+        // we should use the size defines and not hard coded numbers.
 	dims[0] = 3;
 	boost::shared_ptr<DataType> array_type(new ArrayType(PredType::NATIVE_UINT32, 1, &dims[0]));
 	ret->insertMember( "physiology_time_stamp", HOFFSET(ImageHeader, physiology_time_stamp), 		*array_type);
diff --git a/matlab/+ismrmrd/+util/AcquisitionHeaderFromBytes.m b/matlab/+ismrmrd/+util/AcquisitionHeaderFromBytes.m
new file mode 100644
index 0000000..70352a8
--- /dev/null
+++ b/matlab/+ismrmrd/+util/AcquisitionHeaderFromBytes.m
@@ -0,0 +1,47 @@
+function hdr = AcquisitionHeaderFromBytes(bytes)
+% Construct an ISMRMRD Acquisition Header structure from a byte array.
+
+hdr = struct( ...
+    'version',                typecast(bytes(  1:  2), 'uint16'), ... % First unsigned int indicates the version %
+    'flags',                  typecast(bytes(  3: 10), 'uint64'), ... % bit field with flags %
+    'measurement_uid',        typecast(bytes( 11: 10), 'uint32'), ... % Unique ID for the measurement %
+    'scan_counter',           typecast(bytes( 15: 14), 'uint32'), ... % Current acquisition number in the measurement %
+    'acquisition_time_stamp', typecast(bytes( 19: 18), 'uint32'), ... % Acquisition clock %
+    'physiology_time_stamp',  typecast(bytes( 23: 30), 'uint32'), ... % Physiology time stamps, e.g. ecg, breating, etc. %
+                                                                  ... %   TODO: the C header has a bug.  3 is correct
+    'number_of_samples',      typecast(bytes( 55: 56), 'uint16'), ... % Number of samples acquired %
+    'available_channels',     typecast(bytes( 57: 58), 'uint16'), ... % Available coils %
+    'active_channels',        typecast(bytes( 59: 60), 'uint16'), ... % Active coils on current acquisiton %
+    'channel_mask',           typecast(bytes( 61:188), 'uint64'), ... % Mask to indicate which channels are active. Support for 1024 channels %
+    'discard_pre',            typecast(bytes(189:190), 'uint16'), ... % Samples to be discarded at the beginning of acquisition %
+    'discard_post',           typecast(bytes(191:192), 'uint16'), ... % Samples to be discarded at the end of acquisition %
+    'center_sample',          typecast(bytes(193:194), 'uint16'), ... % Sample at the center of k-space %
+    'encoding_space_ref',     typecast(bytes(195:196), 'uint16'), ... % Reference to an encoding space, typically only one per acquisition %
+    'trajectory_dimensions',  typecast(bytes(197:198), 'uint16'), ... % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
+    'sample_time_us',         typecast(bytes(199:202), 'single'), ... % Time between samples in micro seconds, sampling BW %
+    'position',               typecast(bytes(203:214), 'single'), ... % Three-dimensional spatial offsets from isocenter %
+    'read_dir',               typecast(bytes(215:226), 'single'), ... % Directional cosines of the readout/frequency encoding %
+    'phase_dir',              typecast(bytes(227:238), 'single'), ... % Directional cosines of the phase encoding %
+    'slice_dir',              typecast(bytes(239:250), 'single'), ... % Directional cosines of the slice %
+    'patient_table_position', typecast(bytes(251:262), 'single'), ... % Patient table off-center %
+    'idx',                    struct(),                           ... % Encoding counters %
+    'user_int',               typecast(bytes(297:328), 'int32'),  ... % Free user parameters %
+    'user_float',             typecast(bytes(329:360), 'single')  ... % Free user parameters %
+    );
+
+    
+% Encoding Counters
+hdr.idx = struct( ...
+    'kspace_encode_step_1',   typecast(bytes(263:264), 'uint16'), ... % phase encoding line number %
+    'kspace_encode_step_2',   typecast(bytes(265:266), 'uint16'), ... % partition encodning number %
+    'average',                typecast(bytes(263:268), 'uint16'), ... % signal average number %
+    'slice',                  typecast(bytes(265:270), 'uint16'), ... % imaging slice number %
+    'contrast',               typecast(bytes(267:272), 'uint16'), ... % echo number in multi-echo %
+    'phase',                  typecast(bytes(269:274), 'uint16'), ... % cardiac phase number %
+    'repetition',             typecast(bytes(271:276), 'uint16'), ... % dynamic number for dynamic scanning %
+    'set',                    typecast(bytes(273:278), 'uint16'), ... % flow encoding set %
+    'segment',                typecast(bytes(275:280), 'uint16'), ... % segment number for segmented acquisition %
+    'user',                   typecast(bytes(281:296), 'uint16')  ... % Free user parameters %
+    );
+
+end
diff --git a/matlab/+ismrmrd/+util/AcquisitionHeaderToBytes.m b/matlab/+ismrmrd/+util/AcquisitionHeaderToBytes.m
new file mode 100644
index 0000000..f0f4292
--- /dev/null
+++ b/matlab/+ismrmrd/+util/AcquisitionHeaderToBytes.m
@@ -0,0 +1,47 @@
+function bytes = AcquisitionHeaderToBytes(hdr)
+% Convert to an ISMRMRD AcquisitionHeader struct to a byte array.
+
+    % TODO: physiology_time_stamp should be 3.
+    %bytes = zeros(340,1,'int8');
+    bytes = zeros(360,1,'int8');
+    off = 1;
+    bytes(off:off+1)   = typecast(hdr.version               ,'int8'); off=off+2;
+    bytes(off:off+7)   = typecast(hdr.flags                 ,'int8'); off=off+8;
+    bytes(off:off+3)   = typecast(hdr.measurement_uid       ,'int8'); off=off+4;
+    bytes(off:off+3)   = typecast(hdr.scan_counter          ,'int8'); off=off+4;
+    bytes(off:off+3)   = typecast(hdr.acquisition_time_stamp,'int8'); off=off+4;
+    
+    % TODO: physiology_time_stamp should be 3.
+    % but the C struct has a bug, so convert to padding.
+    bytes(off:off+11)  = typecast(hdr.physiology_time_stamp ,'int8'); off=off+12;
+    off = off+20; % Discard 5*uint32;
+
+    bytes(off:off+1)   = typecast(hdr.number_of_samples     ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.available_channels    ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.active_channels       ,'int8'); off=off+2;
+    bytes(off:off+127) = typecast(hdr.channel_mask          ,'int8'); off=off+128;
+    bytes(off:off+1)   = typecast(hdr.discard_pre           ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.discard_post          ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.center_sample         ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.encoding_space_ref    ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.trajectory_dimensions ,'int8'); off=off+2;
+    bytes(off:off+3)   = typecast(hdr.sample_time_us        ,'int8'); off=off+4;
+    bytes(off:off+11)  = typecast(hdr.position              ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.read_dir              ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.phase_dir             ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.slice_dir             ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.patient_table_position,'int8'); off=off+12;
+    bytes(off:off+1)   = typecast(hdr.idx.kspace_encode_step_1,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.kspace_encode_step_2,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.average           ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.slice             ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.contrast          ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.phase             ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.repetition        ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.set               ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.idx.segment           ,'int8'); off=off+2;
+    bytes(off:off+15)  = typecast(hdr.idx.user              ,'int8'); off=off+16;
+    bytes(off:off+31)  = typecast(hdr.user_int              ,'int8'); off=off+32;
+    bytes(off:off+31)  = typecast(hdr.user_float            ,'int8');
+
+end
diff --git a/matlab/+ismrmrd/+util/ImageHeaderFromBytes.m b/matlab/+ismrmrd/+util/ImageHeaderFromBytes.m
new file mode 100644
index 0000000..c5bde23
--- /dev/null
+++ b/matlab/+ismrmrd/+util/ImageHeaderFromBytes.m
@@ -0,0 +1,32 @@
+function hdr = ImageHeaderFromBytes(bytes)
+% Construct an ISMRMRD Image Header structure from a byte array.
+
+    off = 1;
+    hdr = struct();
+    hdr.version                = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.flags                  = typecast(bytes(off:off+7),  'uint64'); off=off+8;
+    hdr.measurement_uid        = typecast(bytes(off:off+3),  'uint32'); off=off+4;
+    hdr.matrix_size            = typecast(bytes(off:off+5),  'uint16'); off=off+6;
+    hdr.field_of_view          = typecast(bytes(off:off+11), 'single'); off=off+12;
+    hdr.channels               = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.position               = typecast(bytes(off:off+11), 'single'); off=off+12;
+    hdr.read_dir               = typecast(bytes(off:off+11), 'single'); off=off+12;
+    hdr.phase_dir              = typecast(bytes(off:off+11), 'single'); off=off+12;
+    hdr.slice_dir              = typecast(bytes(off:off+11), 'single'); off=off+12;
+    hdr.patient_table_position = typecast(bytes(off:off+11), 'single'); off=off+12;
+    hdr.average                = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.slice                  = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.contrast               = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.phase                  = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.repetition             = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.set                    = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.acquisition_time_stamp = typecast(bytes(off:off+3),  'uint32'); off=off+4;
+    hdr.physiology_time_stamp  = typecast(bytes(off:off+31), 'uint32'); off=off+32;
+    hdr.image_data_type        = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.image_type             = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.image_index            = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.image_series_index     = typecast(bytes(off:off+1),  'uint16'); off=off+2;
+    hdr.user_int               = typecast(bytes(off:off+31), 'uint32'); off=off+32;
+    hdr.user_float             = typecast(bytes(off:off+31), 'single');
+
+end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/+util/ImageHeaderToBytes.m b/matlab/+ismrmrd/+util/ImageHeaderToBytes.m
new file mode 100644
index 0000000..54f2452
--- /dev/null
+++ b/matlab/+ismrmrd/+util/ImageHeaderToBytes.m
@@ -0,0 +1,32 @@
+function bytes = ImageHeaderToBytes(hdr)
+% Convert to an ISMRMRD ImageHeader struct to a byte array.
+
+    bytes = zeros(214,1,'int8');
+    off = 1;
+    bytes(off:off+1)   = typecast(hdr.version               ,'int8'); off=off+2;
+    bytes(off:off+7)   = typecast(hdr.flags                 ,'int8'); off=off+8;
+    bytes(off:off+3)   = typecast(hdr.measurement_uid       ,'int8'); off=off+4;
+    bytes(off:off+5)   = typecast(hdr.matrix_size           ,'int8'); off=off+6;
+    bytes(off:off+11)  = typecast(hdr.field_of_view         ,'int8'); off=off+12;
+    bytes(off:off+1)   = typecast(hdr.channels              ,'int8'); off=off+2;
+    bytes(off:off+11)  = typecast(hdr.position              ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.read_dir              ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.phase_dir             ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.slice_dir             ,'int8'); off=off+12;
+    bytes(off:off+11)  = typecast(hdr.patient_table_position,'int8'); off=off+12;
+    bytes(off:off+1)   = typecast(hdr.average               ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.slice                 ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.contrast              ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.phase                 ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.repetition            ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.set                   ,'int8'); off=off+2;
+    bytes(off:off+3)   = typecast(hdr.acquisition_time_stamp,'int8'); off=off+4;
+    bytes(off:off+31)  = typecast(hdr.physiology_time_stamp ,'int8'); off=off+32;
+    bytes(off:off+1)   = typecast(hdr.image_data_type       ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.image_type            ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.image_index           ,'int8'); off=off+2;
+    bytes(off:off+1)   = typecast(hdr.image_series_index    ,'int8'); off=off+2;
+    bytes(off:off+31)  = typecast(hdr.user_int              ,'int8'); off=off+32;
+    bytes(off:off+31)  = typecast(hdr.user_float            ,'int8');
+
+end
diff --git a/matlab/+ismrmrd/old/hdf5_datatypes.m b/matlab/+ismrmrd/+util/hdf5_datatypes.m
similarity index 90%
rename from matlab/+ismrmrd/old/hdf5_datatypes.m
rename to matlab/+ismrmrd/+util/hdf5_datatypes.m
index 6954366..14788d7 100644
--- a/matlab/+ismrmrd/old/hdf5_datatypes.m
+++ b/matlab/+ismrmrd/+util/hdf5_datatypes.m
@@ -1,83 +1,112 @@
 classdef hdf5_datatypes
+% This convenience class defines the HDF5 types used in the
+% ISMRMRD HDF5 file
+    properties
+        T_float;
+        T_double;
+        T_char;
+        T_complexfloat;
+        T_complexdouble;
+        T_ushort;
+        T_EncodingCounters;
+        T_AcquisitionHeader;
+        T_Acquisition;
+    end
     
-    methods (Static)
+    methods
+        
+        function obj = hdf5_datatypes()
+            obj.T_float = ismrmrd.util.hdf5_datatypes.getType_float();
+            obj.T_double = ismrmrd.util.hdf5_datatypes.getType_double();
+            obj.T_char = ismrmrd.util.hdf5_datatypes.getType_char();
+            obj.T_complexfloat = ismrmrd.util.hdf5_datatypes.getType_complexfloat();
+            obj.T_complexdouble = ismrmrd.util.hdf5_datatypes.getType_complexdouble();
+            obj.T_ushort = ismrmrd.util.hdf5_datatypes.getType_ushort();
+            obj.T_EncodingCounters = ismrmrd.util.hdf5_datatypes.getType_EncodingCounters();
+            obj.T_AcquisitionHeader = ismrmrd.util.hdf5_datatypes.getType_AcquisitionHeader();
+            obj.T_Acquisition = ismrmrd.util.hdf5_datatypes.getType_Acquisition();
+        end
         
+    end
+   
+    methods (Static)
+
         function b = getType_float()
             b = H5T.copy('H5T_NATIVE_FLOAT');
         end
-        
+
         function b = getType_double()
             b = H5T.copy('H5T_NATIVE_DOUBLE');
         end
-        
+
         function b = getType_char()
             b = H5T.copy('H5T_NATIVE_CHAR');
         end
-        
+
         function b = getType_complexfloat()
             typesize = 2*H5T.get_size('H5T_NATIVE_FLOAT');
             b = H5T.create ('H5T_COMPOUND', typesize);
             H5T.insert (b, 'real', 0, 'H5T_NATIVE_FLOAT');
             H5T.insert (b, 'imag', H5T.get_size('H5T_NATIVE_FLOAT'), 'H5T_NATIVE_FLOAT');
         end
-        
+
         function b = getType_complexdouble()
             b = H5T.create ('H5T_COMPOUND', ...
                              2*H5T.get_size('H5T_NATIVE_DOUBLE'));
             H5T.insert (b, 'real', 0, 'H5T_NATIVE_DOUBLE');
             H5T.insert (b, 'imag', H5T.get_size('H5T_NATIVE_DOUBLE'), 'H5T_NATIVE_DOUBLE');
         end
-        
+
         function b = getType_ushort()
             b = H5T.copy('H5T_NATIVE_USHORT');
         end
-        
+
         function b = getType_EncodingCounters()
-            
+
             typesize = 17*H5T.get_size('H5T_NATIVE_UINT16');
             b = H5T.create ('H5T_COMPOUND', typesize);
-            
+
             offset = 0;
             H5T.insert(b, 'kspace_encode_step_1', offset, 'H5T_NATIVE_UINT16');
-            
+
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            H5T.insert(b, 'kspace_encode_step_2', offset, 'H5T_NATIVE_UINT16');            
+            H5T.insert(b, 'kspace_encode_step_2', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'average', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'slice', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'contrast', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'phase', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'repetition', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'set', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'segment', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'user', offset, H5T.array_create('H5T_NATIVE_UINT16',[8]));
-            
+
         end
- 
+
         function b = getType_AcquisitionHeader()
-            
+
             typesize = 0;
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % version
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT64'); % flag
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT32'); % measurement_uid
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT32'); % scan_counter
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT32'); % acquisition_time_stamp
-            typesize = typesize + 3*H5T.get_size('H5T_NATIVE_UINT32'); % pysio_time_stampe(3)
+            typesize = typesize + 3*H5T.get_size('H5T_NATIVE_UINT32'); % physio_time_stamps
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % number_of_samples
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % available_channels
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % active_channels
@@ -87,37 +116,37 @@ classdef hdf5_datatypes
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % center_sample
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % encoding_space_ref
             typesize = typesize + H5T.get_size('H5T_NATIVE_UINT16'); % trajectory_dimension
-            typesize = typesize + H5T.get_size('H5T_NATIVE_FLOAT');  % sample_time_us 
+            typesize = typesize + H5T.get_size('H5T_NATIVE_FLOAT');  % sample_time_us
             typesize = typesize + 3*H5T.get_size('H5T_NATIVE_FLOAT'); % position
             typesize = typesize + 3*H5T.get_size('H5T_NATIVE_FLOAT'); % read_dir
             typesize = typesize + 3*H5T.get_size('H5T_NATIVE_FLOAT'); % phase_dir
             typesize = typesize + 3*H5T.get_size('H5T_NATIVE_FLOAT'); % slice_dir
             typesize = typesize + 3*H5T.get_size('H5T_NATIVE_FLOAT'); % patient_table_position
-            typesize = typesize + H5T.get_size(ismrmrd.hdf5_datatypes.getType_EncodingCounters()); % idx
+            typesize = typesize + H5T.get_size(ismrmrd.util.hdf5_datatypes.getType_EncodingCounters()); % idx
             typesize = typesize + 8*H5T.get_size('H5T_NATIVE_INT32'); % user_int
             typesize = typesize + 8*H5T.get_size('H5T_NATIVE_FLOAT'); % user_float
-            
+
             b = H5T.create ('H5T_COMPOUND', typesize);
-            
+
             offset = 0;
-            H5T.insert(b, 'version', offset, 'H5T_NATIVE_UINT16'); 
+            H5T.insert(b, 'version', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
 
             H5T.insert(b, 'flags', offset, 'H5T_NATIVE_UINT64');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT64');
-            
+
             H5T.insert(b, 'measurement_uid', offset, 'H5T_NATIVE_UINT32');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT32');
-            
+
             H5T.insert(b, 'scan_counter', offset, 'H5T_NATIVE_UINT32');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT32');
-            
+
             H5T.insert(b, 'acquisition_time_stamp', offset, 'H5T_NATIVE_UINT32');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT32');
-            
+
             H5T.insert(b, 'physiology_time_stamp', offset, H5T.array_create('H5T_NATIVE_UINT32',[3]));
             offset = offset + 3*H5T.get_size('H5T_NATIVE_UINT32');
-            
+
             H5T.insert(b, 'number_of_samples', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
 
@@ -126,10 +155,10 @@ classdef hdf5_datatypes
 
             H5T.insert(b, 'active_channels', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'channel_mask', offset, H5T.array_create('H5T_NATIVE_UINT64',[16]));
             offset = offset + 16*H5T.get_size('H5T_NATIVE_UINT64');
-            
+
             H5T.insert(b, 'discard_pre', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
 
@@ -141,10 +170,10 @@ classdef hdf5_datatypes
 
             H5T.insert(b, 'encoding_space_ref', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'trajectory_dimensions', offset, 'H5T_NATIVE_UINT16');
             offset = offset + H5T.get_size('H5T_NATIVE_UINT16');
-            
+
             H5T.insert(b, 'sample_time_us', offset, 'H5T_NATIVE_FLOAT');
             offset = offset + H5T.get_size('H5T_NATIVE_FLOAT');
 
@@ -159,13 +188,13 @@ classdef hdf5_datatypes
 
             H5T.insert(b, 'slice_dir', offset, H5T.array_create('H5T_NATIVE_FLOAT',[3]));
             offset = offset + 3*H5T.get_size('H5T_NATIVE_FLOAT');
-            
+
             H5T.insert(b, 'patient_table_position', offset, H5T.array_create('H5T_NATIVE_FLOAT',[3]));
             offset = offset + 3*H5T.get_size('H5T_NATIVE_FLOAT');
-            
-            H5T.insert(b, 'idx', offset, ismrmrd.hdf5_datatypes.getType_EncodingCounters);
-            offset = offset + H5T.get_size(ismrmrd.hdf5_datatypes.getType_EncodingCounters);
-            
+
+            H5T.insert(b, 'idx', offset, ismrmrd.util.hdf5_datatypes.getType_EncodingCounters);
+            offset = offset + H5T.get_size(ismrmrd.util.hdf5_datatypes.getType_EncodingCounters);
+
             H5T.insert(b, 'user_int', offset, H5T.array_create('H5T_NATIVE_INT32',[8]));
             offset = offset + 8*H5T.get_size('H5T_NATIVE_INT32');
 
@@ -175,13 +204,13 @@ classdef hdf5_datatypes
         end
 
         function b = getType_Acquisition()
-            
-            head = H5T.copy(ismrmrd.hdf5_datatypes.getType_AcquisitionHeader);
-            traj = H5T.vlen_create(ismrmrd.hdf5_datatypes.getType_float());
-            data = H5T.vlen_create(ismrmrd.hdf5_datatypes.getType_float());
-            
+
+            head = H5T.copy(ismrmrd.util.hdf5_datatypes.getType_AcquisitionHeader());
+            traj = H5T.vlen_create(ismrmrd.util.hdf5_datatypes.getType_float());
+            data = H5T.vlen_create(ismrmrd.util.hdf5_datatypes.getType_float());
+
             typesize = H5T.get_size(head) + H5T.get_size(traj) + H5T.get_size(data);
-            
+
             b = H5T.create ('H5T_COMPOUND', typesize);
 
             offset = 0;
@@ -190,51 +219,51 @@ classdef hdf5_datatypes
             H5T.insert(b, 'traj', offset, traj);
             offset = offset + H5T.get_size(traj);
             H5T.insert(b, 'data', offset, data);
-            
+
         end
     end % Methods (Static)
-    
+
 end
 
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(AcquisitionHeader_with_data)));
-% 
+%
 % 	boost::shared_ptr<DataType>  head_type = getIsmrmrdHDF5Type<AcquisitionHeader>();
 % 	boost::shared_ptr<DataType> cxvdatatype = getIsmrmrdHDF5Type<complex_t>();
 % 	cxvdatatype = boost::shared_ptr<DataType>(new DataType(H5Tvlen_create (cxvdatatype->getId())));
 % 	boost::shared_ptr<DataType> realvdatatype = boost::shared_ptr<DataType>(new DataType(H5Tvlen_create (PredType::NATIVE_FLOAT.getId())));
-% 
+%
 % 	ret->insertMember( "head",  HOFFSET(AcquisitionHeader_with_data,head),   	*head_type);
 % 	ret->insertMember( "traj", HOFFSET(AcquisitionHeader_with_data,traj),  		*realvdatatype);
 % 	ret->insertMember( "data", HOFFSET(AcquisitionHeader_with_data,data),  		*cxvdatatype);
 
 
 
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader>()
 % {
-% 
+%
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(ImageHeader)));
-% 
+%
 % 	ret->insertMember( "version", 					HOFFSET(ImageHeader, version), 					PredType::NATIVE_UINT16);
 % 	ret->insertMember( "flags", 					HOFFSET(ImageHeader, flags), 				   	PredType::NATIVE_UINT64);
 % 	ret->insertMember( "measurement_uid", 			HOFFSET(ImageHeader, measurement_uid), 		    PredType::NATIVE_UINT32);
-% 
+%
 % 	std::vector<hsize_t> dims(1,0);
-% 
+%
 % 	dims[0] = 3;
 % 	boost::shared_ptr<DataType> mat_size_array_type(new ArrayType(PredType::NATIVE_UINT16, 1, &dims[0]));
 % 	ret->insertMember( "matrix_size", 				HOFFSET(ImageHeader, matrix_size), 		*mat_size_array_type);
-% 
+%
 % 	dims[0] = 3;
 % 	boost::shared_ptr<DataType> fov_array_type(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
 % 	ret->insertMember( "field_of_view", 			HOFFSET(ImageHeader, field_of_view), 		*fov_array_type);
-% 
+%
 % 	ret->insertMember( "channels", 					HOFFSET(ImageHeader, channels), 					PredType::NATIVE_UINT16);
-% 
+%
 % 	dims[0] = 3;
 % 	boost::shared_ptr<DataType> position_array_type(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
 % 	ret->insertMember( "position", 					HOFFSET(ImageHeader, position), 				*position_array_type);
-% 
+%
 %	dims[0] = 3;
 %	boost::shared_ptr<DataType> phase_dir_array_type(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
 %	ret->insertMember( "phase_dir", 				HOFFSET(ImageHeader, phase_dir), 			*phase_dir_array_type);
@@ -246,12 +275,12 @@ end
 %	dims[0] = 3;
 %	boost::shared_ptr<DataType> table_array_type(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
 %	ret->insertMember( "patient_table_position", 	HOFFSET(ImageHeader, patient_table_position), *table_array_type);
-% 
+%
 % 	dims[0] = 3;
 % 	boost::shared_ptr<DataType> table_array_type(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
 % 	ret->insertMember( "patient_table_position", 	HOFFSET(ImageHeader, patient_table_position), *table_array_type);
-% 
-% 
+%
+%
 % 	ret->insertMember( "average", 					HOFFSET(ImageHeader, average), 					PredType::NATIVE_UINT16);
 % 	ret->insertMember( "slice", 					HOFFSET(ImageHeader, slice), 					PredType::NATIVE_UINT16);
 % 	ret->insertMember( "contrast", 					HOFFSET(ImageHeader, contrast), 				PredType::NATIVE_UINT16);
@@ -259,28 +288,28 @@ end
 % 	ret->insertMember( "repetition", 				HOFFSET(ImageHeader, repetition), 				PredType::NATIVE_UINT16);
 % 	ret->insertMember( "set",   					HOFFSET(ImageHeader, set), 						PredType::NATIVE_UINT16);
 % 	ret->insertMember( "acquisition_time_stamp", 	HOFFSET(ImageHeader, acquisition_time_stamp),   PredType::NATIVE_UINT32);
-% 
+%
 % 	dims[0] = 3;
 % 	boost::shared_ptr<DataType> array_type(new ArrayType(PredType::NATIVE_UINT32, 1, &dims[0]));
 % 	ret->insertMember( "physiology_time_stamp", HOFFSET(ImageHeader, physiology_time_stamp), 		*array_type);
-% 
+%
 % 	ret->insertMember( "image_data_type",   		HOFFSET(ImageHeader, image_data_type),			PredType::NATIVE_UINT16);
 % 	ret->insertMember( "image_type",   				HOFFSET(ImageHeader, image_type),				PredType::NATIVE_UINT16);
 % 	ret->insertMember( "image_index",   			HOFFSET(ImageHeader, image_index),				PredType::NATIVE_UINT16);
 % 	ret->insertMember( "image_series_index",		HOFFSET(ImageHeader, image_series_index),		PredType::NATIVE_UINT16);
-% 
+%
 % 	dims[0] = 8;
 % 	boost::shared_ptr<DataType> user_int_array_type(new ArrayType(PredType::NATIVE_INT32, 1, &dims[0]));
 % 	ret->insertMember( "user_int", 				HOFFSET(ImageHeader, user_int), *user_int_array_type);
-% 
+%
 % 	dims[0] = 8;
 % 	boost::shared_ptr<DataType> user_float_array_type(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
 % 	ret->insertMember( "user_float", 				HOFFSET(ImageHeader, user_float), *user_float_array_type);
-% 
+%
 % 	return ret;
 % }
-% 
-% 
+%
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data<float> >()
 % {
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(ImageHeader_with_data<float>)));
@@ -291,7 +320,7 @@ end
 % 	ret->insertMember( "data", HOFFSET(ImageHeader_with_data<float>,data),  	*vdatatype);
 % 	return ret;
 % }
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data<double> >()
 % {
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(ImageHeader_with_data<double>)));
@@ -302,7 +331,7 @@ end
 % 	ret->insertMember( "data", HOFFSET(ImageHeader_with_data<double>,data),  	*vdatatype);
 % 	return ret;
 % }
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data<unsigned short> >()
 % {
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(ImageHeader_with_data<unsigned short>)));
@@ -313,7 +342,7 @@ end
 % 	ret->insertMember( "data", HOFFSET(ImageHeader_with_data<unsigned short>,data),  	*vdatatype);
 % 	return ret;
 % }
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data<complex_t> >()
 % {
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(ImageHeader_with_data<complex_t>)));
@@ -324,7 +353,7 @@ end
 % 	ret->insertMember( "data", HOFFSET(ImageHeader_with_data<complex_t>,data),  	*vdatatype);
 % 	return ret;
 % }
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data<double_complex_t> >()
 % {
 % 	boost::shared_ptr<CompType> ret = boost::shared_ptr<CompType>(new CompType(sizeof(ImageHeader_with_data<double_complex_t>)));
@@ -335,16 +364,16 @@ end
 % 	ret->insertMember( "data", HOFFSET(ImageHeader_with_data<double_complex_t>,data),  	*vdatatype);
 % 	return ret;
 % }
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data< std::complex<float> > >()
 % {
 % 	return getIsmrmrdHDF5Type<ImageHeader_with_data<complex_t> >();
 % }
-% 
+%
 % template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<ImageHeader_with_data< std::complex<double> > >()
 % {
 % 	return getIsmrmrdHDF5Type<ImageHeader_with_data<double_complex_t> >();
 % }
-% 
+%
 % }
-% 
+%
diff --git a/matlab/+ismrmrd/+util/includejar.m b/matlab/+ismrmrd/+util/includejar.m
new file mode 100644
index 0000000..dcaa62e
--- /dev/null
+++ b/matlab/+ismrmrd/+util/includejar.m
@@ -0,0 +1,15 @@
+function includejar()
+% Set the javaclasspath to be able to load the xml header bits
+
+    % Path to the jar file
+    fpath = mfilename('fullpath');
+    [pathstr, name, ext] = fileparts(fpath);
+    jar = fullfile(pathstr, 'ismrmrd-matlab.jar');
+    
+    % Only add if it's not already on our path
+    jpath = javaclasspath('-all');
+    if ~any(strcmp(jar,jpath))
+        javaaddpath(jar);
+    end
+
+end
diff --git a/matlab/+ismrmrd/old/isInt.m b/matlab/+ismrmrd/+util/isInt.m
similarity index 100%
rename from matlab/+ismrmrd/old/isInt.m
rename to matlab/+ismrmrd/+util/isInt.m
diff --git a/matlab/+ismrmrd/Acquisition.m b/matlab/+ismrmrd/Acquisition.m
new file mode 100644
index 0000000..9dd441d
--- /dev/null
+++ b/matlab/+ismrmrd/Acquisition.m
@@ -0,0 +1,122 @@
+classdef Acquisition < handle
+
+    properties
+        head = [];
+        traj = {};
+        data = {};
+    end
+
+    methods
+
+        function obj = Acquisition(arg1, traj, data)
+            switch nargin
+                case 0
+                    % No argument constructor
+                    % initialize to a single acquisition
+                    extend(obj,1);
+                    
+                case 1
+                    % One argument constructor
+                    if ismrmrd.util.isInt(arg1)
+                        % First argument is a number
+                        M = arg1;
+                        extend(obj,M);
+                    else                        
+                        % First argument is a header (hopefully)
+                        M = length(arg1.version);
+                        obj.head = ismrmrd.AcquisitionHeader(arg1);
+                        obj.traj{M} = [];
+                        obj.data{M} = [];
+                    end
+                    
+                case 3
+                    % Three argument constructor
+                    obj.head = ismrmrd.AcquisitionHeader(arg1);
+                    M = length(arg1.version);
+                    if isempty(traj)
+                        obj.traj{M} = [];
+                    else
+                        obj.traj = traj;
+                    end
+                    if isempty(data)
+                        obj.data{M} = [];
+                    else
+                        if isreal(data{1})
+                            dataFromFloat(obj,data);
+                        else
+                            obj.data = data;
+                        end
+                    end
+                    
+            otherwise
+                    error('ismrmrd.Acquistion constructor, wrong number of arguments.');
+            end
+        end
+        
+        function nacq = getNumber(obj)
+            nacq = obj.head.getNumber();
+        end
+        
+        function acq = select(obj, range)
+            % Return a copy of a range of acquisitions
+            
+            % create an empty acquisition
+            acq = ismrmrd.Acquisition();
+            % Fill the header
+            acq.head = obj.head.select(range);
+            % Fill the trajectory and the data
+            for p = 1:length(range)
+                acq.traj{p} = obj.traj{range(p)};
+                acq.data{p} = obj.data{range(p)};
+            end    
+        end
+        
+        function append(obj, head, traj, data)
+            Nstart = obj.getNumber + 1;
+            Nend   = obj.getNumber + length(head.version);
+            Nrange = Nstart:Nend;
+            obj.head.append(head);
+            if isempty(traj) > 0
+                obj.traj{Nrange} = traj;
+            end
+            if isempty(data) > 0
+                obj.data{Nrange} = data;
+            end
+            
+        end
+        
+        function extend(obj,N)
+            % Extend with blank head and empty traj and data.
+            M = N+obj.getNumber();
+            obj.head.extend(N);
+            obj.traj{M} = [];
+            obj.data{M} = []; 
+        end
+        
+        function dataFromFloat(obj,v)
+            if (isempty(obj.head) || (length(v) ~= length(obj.head.version)))
+                error('Mismatch between size of head and data.  Please set head first.');
+            end
+            obj.data = cell(1,length(v));
+            for p = 1:length(v)
+                dims = [obj.head.number_of_samples(p), ...
+                        obj.head.active_channels(p)];
+                buff = v{p};
+                obj.data{p} = reshape(buff(1:2:end) + 1j*buff(2:2:end), dims);
+            end
+        end
+
+        function v = dataToFloat(obj)
+            v = cell(1,length(obj.data));
+            for p = 1:length(obj.data)
+                dim = size(obj.data{p});
+                buff = zeros([2*prod(dim),1],'single');
+                buff(1:2:end) = real(reshape(obj.data{p},prod(dim),1));
+                buff(2:2:end) = imag(reshape(obj.data{p},prod(dim),1));
+                v{p} = buff;
+            end
+        end
+        
+    end
+
+end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/AcquisitionFlags.m b/matlab/+ismrmrd/AcquisitionFlags.m
deleted file mode 100644
index f8ea364..0000000
--- a/matlab/+ismrmrd/AcquisitionFlags.m
+++ /dev/null
@@ -1,38 +0,0 @@
-classdef AcquisitionFlags
-    properties(Constant)
-        % Looping indicators %
-        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
-    end
-end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/AcquisitionHeader.m b/matlab/+ismrmrd/AcquisitionHeader.m
index 1fbb742..cd4e3db 100644
--- a/matlab/+ismrmrd/AcquisitionHeader.m
+++ b/matlab/+ismrmrd/AcquisitionHeader.m
@@ -1,237 +1,468 @@
-classdef AcquisitionHeader
+classdef AcquisitionHeader < handle
     
     properties
-        version = uint16(0);                           % First unsigned int indicates the version %
-        flags = uint64(0);                             % bit field with flags %
-        measurement_uid = uint32(0);                   % Unique ID for the measurement %
-        scan_counter = uint32(0);                      % Current acquisition number in the measurement %
-        acquisition_time_stamp = uint32(0);            % Acquisition clock %
-        physiology_time_stamp = zeros(8,1,'uint32');   % Physiology time stamps, e.g. ecg, breating, etc. %
-        number_of_samples = uint16(0);                 % Number of samples acquired %
-        available_channels = uint16(0);                % Available coils %
-        active_channels = uint16(0);                   % Active coils on current acquisiton %
-        channel_mask = zeros(16,1,'uint64');           % Mask to indicate which channels are active. Support for 1024 channels %
-        discard_pre = uint16(0);                       % Samples to be discarded at the beginning of acquisition %
-        discard_post = uint16(0);                      % Samples to be discarded at the end of acquisition %
-        center_sample = uint16(0);                     % Sample at the center of k-space %
-        encoding_space_ref = uint16(0);                % Reference to an encoding space, typically only one per acquisition %
-        trajectory_dimensions = uint16(0);             % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
-        sample_time_us = single(0);                    % Time between samples in micro seconds, sampling BW %
-        position = zeros(3,1,'single');                % Three-dimensional spatial offsets from isocenter %
-        read_dir = zeros(3,1,'single');                % Directional cosines of the readout/frequency encoding %
-        phase_dir = zeros(3,1,'single');               % Directional cosines of the phase encoding %
-        slice_dir = zeros(3,1,'single');               % Directional cosines of the slice %
-        patient_table_position = zeros(3,1, 'single'); % Patient table off-center %
-        idx = ismrmrd.EncodingCounters;                % Encoding loop counters, see above %
-        user_int = zeros(8,1,'int32');                 % Free user parameters %
-        user_float = zeros(8,1,'single');              % Free user parameters %
+        
+        version = uint16([]);                          % First unsigned int indicates the version %
+        flags = uint64([]);                            % bit field with flags %
+        measurement_uid = uint32([]);                  % Unique ID for the measurement %
+        scan_counter = uint32([]);                     % Current acquisition number in the measurement %
+        acquisition_time_stamp = uint32([]);           % Acquisition clock %
+        physiology_time_stamp = uint32([]);            % Physiology time stamps, e.g. ecg, breating, etc. %
+        number_of_samples = uint16([]);                % Number of samples acquired %
+        available_channels = uint16([]);               % Available coils %
+        active_channels = uint16([]);                  % Active coils on current acquisiton %
+        channel_mask = uint64([]);                     % Mask to indicate which channels are active. Support for 1024 channels %
+        discard_pre = uint16([]);                      % Samples to be discarded at the beginning of acquisition %
+        discard_post = uint16([]);                     % Samples to be discarded at the end of acquisition %
+        center_sample = uint16([]);                    % Sample at the center of k-space %
+        encoding_space_ref = uint16([]);               % Reference to an encoding space, typically only one per acquisition %
+        trajectory_dimensions = uint16([]);            % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
+        sample_time_us = single([]);                   % Time between samples in micro seconds, sampling BW %
+        position = single([]);                         % Three-dimensional spatial offsets from isocenter %
+        read_dir = single([]);                         % Directional cosines of the readout/frequency encoding %
+        phase_dir = single([]);                        % Directional cosines of the phase encoding %
+        slice_dir = single([]);                        % Directional cosines of the slice %
+        patient_table_position = single([]);           % Patient table off-center %
+        idx = struct(  ...                             % Encoding loop counters, see above %
+            'kspace_encode_step_1', uint16([]), ...   
+            'kspace_encode_step_2', uint16([]), ...
+            'average', uint16([]), ...
+            'slice', uint16([]), ...
+            'contrast', uint16([]), ...
+            'phase', uint16([]), ...
+            'repetition', uint16([]), ...
+            'set', uint16([]), ...
+            'segment', uint16([]), ...
+            'user', uint16([]));
+        user_int = int32([]);                 % Free user parameters %
+        user_float = single([]);              % Free user parameters %
+        
+    end
+    
+    properties(Constant)
+        FLAGS = struct( ...
+            '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);
     end
     
     methods
         
-        % Constructor
-        function obj = AcquisitionHeader(bytes)
-            if (nargin == 1)
-                off = 1;
-                obj.version                = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.flags                  = typecast(bytes(off:off+7),  'uint64'); off=off+8;
-                obj.measurement_uid        = typecast(bytes(off:off+3),  'uint32'); off=off+4;
-                obj.scan_counter           = typecast(bytes(off:off+3),  'uint32'); off=off+4;
-                obj.acquisition_time_stamp = typecast(bytes(off:off+3),  'uint32'); off=off+4;
-                obj.physiology_time_stamp  = typecast(bytes(off:off+31), 'uint32'); off=off+32;
-                obj.number_of_samples      = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.available_channels     = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.active_channels        = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.channel_mask           = typecast(bytes(off:off+127),'uint64'); off=off+128;
-                obj.discard_pre            = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.discard_post           = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.center_sample          = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.encoding_space_ref     = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.trajectory_dimensions  = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.sample_time_us         = typecast(bytes(off:off+3),  'single'); off=off+4;
-                obj.position               = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.read_dir               = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.phase_dir              = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.slice_dir              = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.patient_table_position = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.idx              = ismrmrd.EncodingCounters(bytes(off:off+33)); off=off+34;
-                obj.user_int               = typecast(bytes(off:off+31), 'uint32'); off=off+32;
-                obj.user_float             = typecast(bytes(off:off+31), 'single');
+        function obj = AcquisitionHeader(arg)
+            switch nargin
+                case 0
+                    % No argument constructor
+                    % initialize to a single acquisition header
+                    extend(obj,1);
+                    
+                case 1
+                    % One argument constructor
+                    if isstruct(arg)
+                        % plain struct
+                        fromStruct(obj,arg);
+                    elseif (length(arg)==1 && ismrmrd.util.isInt(arg)) == 1
+                        % number
+                        extend(obj,arg);
+                    elseif isa(arg,'int8')
+                        % Byte array
+                        fromBytes(obj,arg);
+                    else
+                        % Unknown type
+                        error('Unknown argument type.')
+                    end
+                    
+                otherwise
+                    error('Wrong number of arguments.')
+                    
             end
         end
         
-        % Convert to Bytes
-        function bytes = toBytes(obj)
-            bytes = zeros(360,1,'int8');
-            off = 1;
-            bytes(off:off+1)   = typecast(obj.version               ,'int8'); off=off+2;
-            bytes(off:off+7)   = typecast(obj.flags                 ,'int8'); off=off+8;
-            bytes(off:off+3)   = typecast(obj.measurement_uid       ,'int8'); off=off+4;
-            bytes(off:off+3)   = typecast(obj.scan_counter          ,'int8'); off=off+4;
-            bytes(off:off+3)   = typecast(obj.acquisition_time_stamp,'int8'); off=off+4;
-            bytes(off:off+31)  = typecast(obj.physiology_time_stamp ,'int8'); off=off+32;
-            bytes(off:off+1)   = typecast(obj.number_of_samples     ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.available_channels    ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.active_channels       ,'int8'); off=off+2;
-            bytes(off:off+127) = typecast(obj.channel_mask          ,'int8'); off=off+128;
-            bytes(off:off+1)   = typecast(obj.discard_pre           ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.discard_post          ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.center_sample         ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.encoding_space_ref    ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.trajectory_dimensions ,'int8'); off=off+2;
-            bytes(off:off+3)   = typecast(obj.sample_time_us        ,'int8'); off=off+4;
-            bytes(off:off+11)  = typecast(obj.position              ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.read_dir              ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.phase_dir             ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.slice_dir             ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.patient_table_position,'int8'); off=off+12;
-            bytes(off:off+33)  = obj.idx.toBytes();                           off=off+34;
-            bytes(off:off+31)  = typecast(obj.user_int              ,'int8'); off=off+32;
-            bytes(off:off+31)  = typecast(obj.user_float            ,'int8');
+        function nacq = getNumber(obj)
+            nacq = length(obj.version);
         end
+
+        function hdr = select(obj, range)
+            % Return a copy of a range of acquisition headers
+            
+            % create an empty acquisition header
+            M = length(range);
+            hdr = ismrmrd.AcquisitionHeader(M);
+            
+            % Fill
+            hdr.version = obj.version(range);
+            hdr.flags = obj.flags(range);
+            hdr.measurement_uid = obj.measurement_uid(range);
+            hdr.scan_counter = obj.scan_counter(range);
+            hdr.acquisition_time_stamp = obj.acquisition_time_stamp(range);
+            hdr.physiology_time_stamp = obj.physiology_time_stamp(:,range);
+            hdr.number_of_samples = obj.number_of_samples(range);
+            hdr.available_channels = obj.available_channels(range);
+            hdr.active_channels = obj.active_channels(range);
+            hdr.channel_mask = obj.channel_mask(:,range);
+            hdr.discard_pre = obj.discard_pre(range);
+            hdr.discard_post = obj.discard_post(range);
+            hdr.center_sample = obj.center_sample(range);
+            hdr.encoding_space_ref = obj.encoding_space_ref(range);
+            hdr.trajectory_dimensions = obj.trajectory_dimensions(range);
+            hdr.sample_time_us = obj.sample_time_us(range);
+            hdr.position = obj.position(:,range);
+            hdr.read_dir = obj.read_dir(:,range);
+            hdr.phase_dir = obj.phase_dir(:,range);
+            hdr.slice_dir = obj.slice_dir(:,range);
+            hdr.patient_table_position = obj.patient_table_position(:,range);
+            hdr.idx.kspace_encode_step_1 = obj.idx.kspace_encode_step_1(range);
+            hdr.idx.kspace_encode_step_2 = obj.idx.kspace_encode_step_2(range);
+            hdr.idx.average = obj.idx.average(range);
+            hdr.idx.slice = obj.idx.slice(range);
+            hdr.idx.contrast = obj.idx.contrast(range);
+            hdr.idx.phase = obj.idx.phase(range);
+            hdr.idx.repetition = obj.idx.repetition(range);
+            hdr.idx.set = obj.idx.set(range);
+            hdr.idx.segment = obj.idx.segment(range);
+            hdr.idx.user = obj.idx.user(:,range);
+            hdr.user_int = obj.user_int(:,range);
+            hdr.user_float = obj.user_float(:,range);
+            
+        end        
         
-        % The flag methods
-        function val = isFlagSet(obj,flagstring)
-            flagbit = ismrmrd.FlagBit(getfield(ismrmrd.AcquisitionFlags,flagstring));
-            val = flagbit.isSet(obj.flags);
+        function extend(obj,N)
+            % Extend with blank header
+            range = obj.getNumber + (1:N);
+            obj.version(1,range)                  = zeros(1,N,'uint16');
+            obj.flags(1,range)                    = zeros(1,N,'uint64');
+            obj.measurement_uid(1,range)          = zeros(1,N,'uint32');
+            obj.scan_counter(1,range)             = zeros(1,N,'uint32');
+            obj.acquisition_time_stamp(1,range)   = zeros(1,N,'uint32');
+            obj.physiology_time_stamp(1:3,range)  = zeros(3,N,'uint32');
+            obj.number_of_samples(1,range)        = zeros(1,N,'uint16');
+            obj.available_channels(1,range)       = zeros(1,N,'uint16');
+            obj.active_channels(1,range)          = zeros(1,N,'uint16');
+            obj.channel_mask(1:16,range)          = zeros(16,N,'uint64');
+            obj.discard_pre(1,range)              = zeros(1,N,'uint16');
+            obj.discard_post(1,range)             = zeros(1,N,'uint16');
+            obj.center_sample(1,range)            = zeros(1,N,'uint16');
+            obj.encoding_space_ref(1,range)       = zeros(1,N,'uint16');
+            obj.trajectory_dimensions(1,range)    = zeros(1,N,'uint16');
+            obj.sample_time_us(1,range)           = zeros(1,N,'uint16');
+            obj.position(1:3,range)               = zeros(3,N,'single');
+            obj.read_dir(1:3,range)               = zeros(3,N,'single');
+            obj.phase_dir(1:3,range)              = zeros(3,N,'single');
+            obj.slice_dir(1:3,range)              = zeros(3,N,'single');
+            obj.patient_table_position(1:3,range) = zeros(3,N,'single');
+            obj.idx.kspace_encode_step_1(1,range) = zeros(1,N,'uint16');
+            obj.idx.kspace_encode_step_2(1,range) = zeros(1,N,'uint16');
+            obj.idx.average(1,range)              = zeros(1,N,'uint16');
+            obj.idx.slice(1,range)                = zeros(1,N,'uint16');
+            obj.idx.contrast(1,range)             = zeros(1,N,'uint16');
+            obj.idx.phase(1,range)                = zeros(1,N,'uint16');
+            obj.idx.repetition(1,range)           = zeros(1,N,'uint16');
+            obj.idx.set(1,range)                  = zeros(1,N,'uint16');
+            obj.idx.segment(1,range)              = zeros(1,N,'uint16');
+            obj.idx.user(1:8,range)               = zeros(8,N,'uint16');
+            obj.user_int(1:8,range)               = zeros(8,N,'int32');
+            obj.user_float(1:8,range)             = zeros(8,N,'single');
         end
         
-        function obj = setFlag(obj,flagstring)
-            flagbit = ismrmrd.FlagBit(getfield(ismrmrd.AcquisitionFlags,flagstring));
-            obj.flags = bitor(obj.flags, flagbit.bitmask);
+        function append(obj, head)
+            Nstart = obj.getNumber + 1;
+            Nend   = obj.getNumber + length(head.version);
+            Nrange = Nstart:Nend;
+            obj.version(Nrange) = hdr.version;
+            obj.flags(Nrange) = hdr.flags;
+            obj.measurement_uid(Nrange) = hdr.measurement_uid;
+            obj.scan_counter(Nrange) = hdr.scan_counter;
+            obj.acquisition_time_stamp(Nrange) = hdr.acquisition_time_stamp;
+            obj.physiology_time_stamp(:,Nrange) = hdr.physiology_time_stamp;
+            obj.number_of_samples(Nrange) = hdr.number_of_samples;
+            obj.available_channels(Nrange) = hdr.available_channels;
+            obj.active_channels(Nrange) = hdr.active_channels;
+            obj.channel_mask(:,Nrange) = hdr.channel_mask;
+            obj.discard_pre(Nrange) = hdr.discard_pre;
+            obj.discard_post(Nrange) = hdr.discard_post;
+            obj.center_sample(Nrange) = hdr.center_sample;
+            obj.encoding_space_ref(Nrange) = hdr.encoding_space_ref;
+            obj.trajectory_dimensions(Nrange) = hdr.trajectory_dimensions;
+            obj.sample_time_us(Nrange) = hdr.sample_time_us;
+            obj.position(:,Nrange) = hdr.position;
+            obj.read_dir(:,Nrange) = hdr.read_dir;
+            obj.phase_dir(:,Nrange) = hdr.phase_dir;
+            obj.slice_dir(:,Nrange) = hdr.slice_dir;
+            obj.patient_table_position(:,Nrange) = hdr.patient_table_position;
+            obj.idx.kspace_encode_step_1(Nrange) = hdr.idx.kspace_encode_step_1;
+            obj.idx.kspace_encode_step_2(Nrange) = hdr.idx.kspace_encode_step_2;
+            obj.idx.average(Nrange) = hdr.idx.average;
+            obj.idx.slice(Nrange) = hdr.idx.slice;
+            obj.idx.contrast(Nrange) = hdr.idx.contrast;
+            obj.idx.phase(Nrange) = hdr.idx.phase;
+            obj.idx.repetition(Nrange) = hdr.idx.repetition;
+            obj.idx.set(Nrange) = hdr.idx.set;
+            obj.idx.segment(Nrange) = hdr.idx.segment;
+            obj.idx.user(:,Nrange) = hdr.idx.user;
+            obj.user_int(:,Nrange) = hdr.user_int;
+            obj.user_float(:,Nrange) = hdr.user_float;            
         end
-        
-        % Set methods
-        function obj = set.version(obj,v)
-            obj.version = uint16(v);
+
+        function fromStruct(obj, hdr)
+            %warning! no error checking
+            obj.version = hdr.version;
+            obj.flags = hdr.flags;
+            obj.measurement_uid = hdr.measurement_uid;
+            obj.scan_counter = hdr.scan_counter;
+            obj.acquisition_time_stamp = hdr.acquisition_time_stamp;
+            obj.physiology_time_stamp = hdr.physiology_time_stamp;
+            obj.number_of_samples = hdr.number_of_samples;
+            obj.available_channels = hdr.available_channels;
+            obj.active_channels = hdr.active_channels;
+            obj.channel_mask = hdr.channel_mask;
+            obj.discard_pre = hdr.discard_pre;
+            obj.discard_post = hdr.discard_post;
+            obj.center_sample = hdr.center_sample;
+            obj.encoding_space_ref = hdr.encoding_space_ref;
+            obj.trajectory_dimensions = hdr.trajectory_dimensions;
+            obj.sample_time_us = hdr.sample_time_us;
+            obj.position = hdr.position;
+            obj.read_dir = hdr.read_dir;
+            obj.phase_dir = hdr.phase_dir;
+            obj.slice_dir = hdr.slice_dir;
+            obj.patient_table_position = hdr.patient_table_position;
+            obj.idx.kspace_encode_step_1 = hdr.idx.kspace_encode_step_1;
+            obj.idx.kspace_encode_step_2 = hdr.idx.kspace_encode_step_2;
+            obj.idx.average = hdr.idx.average;
+            obj.idx.slice = hdr.idx.slice;
+            obj.idx.contrast = hdr.idx.contrast;
+            obj.idx.phase = hdr.idx.phase;
+            obj.idx.repetition = hdr.idx.repetition;
+            obj.idx.set = hdr.idx.set;
+            obj.idx.segment = hdr.idx.segment;
+            obj.idx.user = hdr.idx.user;
+            obj.user_int = hdr.user_int;
+            obj.user_float = hdr.user_float;            
         end
-        
-        function obj = set.flags(obj,v)
-            obj.flags = uint64(v);
-        end
-        
-        function obj = set.measurement_uid(obj,v)
-            obj.measurement_uid = uint32(v);
+
+        function hdr = toStruct(obj)
+            %warning! no error checking
+            hdr = struct();
+            hdr.version = obj.version;
+            hdr.flags = obj.flags;
+            hdr.measurement_uid = obj.measurement_uid;
+            hdr.scan_counter = obj.scan_counter;
+            hdr.acquisition_time_stamp = obj.acquisition_time_stamp;
+            hdr.physiology_time_stamp = obj.physiology_time_stamp;
+            hdr.number_of_samples = obj.number_of_samples;
+            hdr.available_channels = obj.available_channels;
+            hdr.active_channels = obj.active_channels;
+            hdr.channel_mask = obj.channel_mask;
+            hdr.discard_pre = obj.discard_pre;
+            hdr.discard_post = obj.discard_post;
+            hdr.center_sample = obj.center_sample;
+            hdr.encoding_space_ref = obj.encoding_space_ref;
+            hdr.trajectory_dimensions = obj.trajectory_dimensions;
+            hdr.sample_time_us = obj.sample_time_us;
+            hdr.position = obj.position;
+            hdr.read_dir = obj.read_dir;
+            hdr.phase_dir = obj.phase_dir;
+            hdr.slice_dir = obj.slice_dir;
+            hdr.patient_table_position = obj.patient_table_position;
+            hdr.idx.kspace_encode_step_1 = obj.idx.kspace_encode_step_1;
+            hdr.idx.kspace_encode_step_2 = obj.idx.kspace_encode_step_2;
+            hdr.idx.average = obj.idx.average;
+            hdr.idx.slice = obj.idx.slice;
+            hdr.idx.contrast = obj.idx.contrast;
+            hdr.idx.phase = obj.idx.phase;
+            hdr.idx.repetition = obj.idx.repetition;
+            hdr.idx.set = obj.idx.set;
+            hdr.idx.segment = obj.idx.segment;
+            hdr.idx.user = obj.idx.user;
+            hdr.user_int = obj.user_int;
+            hdr.user_float = obj.user_float;            
         end
         
-        function obj = set.scan_counter(obj,v)
-            obj.scan_counter = uint32(v);
-        end
-        
-        function obj = set.acquisition_time_stamp(obj,v)
-            obj.acquisition_time_stamp = uint32(v);
-        end
-        
-        function obj = set.physiology_time_stamp(obj,v)
-            if (length(v)~=8)
-                error('AcquisitionHeader.physiology_time_stamp must have 8 elements')
-            end
-            obj.physiology_time_stamp = uint32(v);
-        end
-        
-        function obj = set.number_of_samples(obj,v)
-            obj.number_of_samples = uint16(v);
-        end
-        
-        function obj = set.available_channels(obj,v)
-            obj.available_channels = uint16(v);
-        end
-        
-        function obj = set.active_channels(obj,v)
-            obj.active_channels = uint16(v);
-        end
-        
-        function obj = set.channel_mask(obj,v)
-            if (length(v)~=16)
-                error('AcquisitionHeader.channel_mask must have 16 elements')
+        function fromBytes(obj, bytearray)
+
+            % TODO: physiology_time_stamp should be 3. So size will change
+            % from 360 to 340;
+            if size(bytearray,1) ~= 360
+                error('Wrong number of bytes for AcquisitionHeader.')
             end
-            obj.channel_mask = uint64(v);
-        end
-        
-        function obj = set.discard_pre(obj,v)
-            obj.discard_pre = uint16(v);
+            N = size(bytearray,2);
+            for p = 1:N
+                obj.version(p) =                  typecast(bytearray(  1:  2,p), 'uint16'); ... % First unsigned int indicates the version %
+                obj.flags(p) =                    typecast(bytearray(  3: 10,p), 'uint64'); ... % bit field with flags %
+                obj.measurement_uid(p) =          typecast(bytearray( 11: 14,p), 'uint32'); ... % Unique ID for the measurement %
+                obj.scan_counter(p) =             typecast(bytearray( 15: 18,p), 'uint32'); ... % Current acquisition number in the measurement %
+                obj.acquisition_time_stamp(p) =   typecast(bytearray( 19: 22,p), 'uint32'); ... % Acquisition clock %
+                obj.physiology_time_stamp(:,p) =  typecast(bytearray( 23: 30,p), 'uint32'); ... % Physiology time stamps, e.g. ecg, breating, etc. %
+                                                                                            ... %   TODO: the C header has a bug.  3 is correct
+                obj.number_of_samples(p) =        typecast(bytearray( 55: 56,p), 'uint16'); ... % Number of samples acquired %
+                obj.available_channels(p) =       typecast(bytearray( 57: 58,p), 'uint16'); ... % Available coils %
+                obj.active_channels(p) =          typecast(bytearray( 59: 60,p), 'uint16'); ... % Active coils on current acquisiton %
+                obj.channel_mask(:,p) =           typecast(bytearray( 61:188,p), 'uint64'); ... % Mask to indicate which channels are active. Support for 1024 channels %
+                obj.discard_pre(p) =              typecast(bytearray(189:190,p), 'uint16'); ... % Samples to be discarded at the beginning of acquisition %
+                obj.discard_post(p) =             typecast(bytearray(191:192,p), 'uint16'); ... % Samples to be discarded at the end of acquisition %
+                obj.center_sample(p) =            typecast(bytearray(193:194,p), 'uint16'); ... % Sample at the center of k-space %
+                obj.encoding_space_ref(p) =       typecast(bytearray(195:196,p), 'uint16'); ... % Reference to an encoding space, typically only one per acquisition %
+                obj.trajectory_dimensions(p) =    typecast(bytearray(197:198,p), 'uint16'); ... % Indicates the dimensionality of the trajectory vector (0 means no trajectory) %
+                obj.sample_time_us(p) =           typecast(bytearray(199:202,p), 'single'); ... % Time between samples in micro seconds, sampling BW %
+                obj.position(:,p) =               typecast(bytearray(203:214,p), 'single'); ... % Three-dimensional spatial offsets from isocenter %
+                obj.read_dir(:,p) =               typecast(bytearray(215:226,p), 'single'); ... % Directional cosines of the readout/frequency encoding %
+                obj.phase_dir(:,p) =              typecast(bytearray(227:238,p), 'single'); ... % Directional cosines of the phase encoding %
+                obj.slice_dir(:,p) =              typecast(bytearray(239:250,p), 'single'); ... % Directional cosines of the slice %
+                obj.patient_table_position(:,p) = typecast(bytearray(251:262,p), 'single'); ... % Patient table off-center %
+                obj.idx.kspace_encode_step_1(p) = typecast(bytearray(263:264,p), 'uint16'); ... % phase encoding line number %
+                obj.idx.kspace_encode_step_2(p) = typecast(bytearray(265:266,p), 'uint16'); ... % partition encodning number %
+                obj.idx.average(p) =              typecast(bytearray(267:268,p), 'uint16'); ... % signal average number %
+                obj.idx.slice(p) =                typecast(bytearray(269:270,p), 'uint16'); ... % imaging slice number %
+                obj.idx.contrast(p) =             typecast(bytearray(271:272,p), 'uint16'); ... % echo number in multi-echo %
+                obj.idx.phase(p) =                typecast(bytearray(273:274,p), 'uint16'); ... % cardiac phase number %
+                obj.idx.repetition(p) =           typecast(bytearray(275:276,p), 'uint16'); ... % dynamic number for dynamic scanning %
+                obj.idx.set(p) =                  typecast(bytearray(277:278,p), 'uint16'); ... % flow encoding set %
+                obj.idx.segment(p) =              typecast(bytearray(279:280,p), 'uint16'); ... % segment number for segmented acquisition %
+                obj.idx.user(:,p) =               typecast(bytearray(281:296,p), 'uint16'); ... % Free user parameters %
+                obj.user_int(:,p) =               typecast(bytearray(297:328,p), 'int32');  ... % Free user parameters %
+                obj.user_float(:,p) =             typecast(bytearray(329:360,p), 'single'); ... % Free user parameters %
+            end              
         end
         
-        function obj = set.discard_post(obj,v)
-            obj.discard_post = uint16(v);
-        end
-        
-        function obj = set.center_sample(obj,v)
-            obj.center_sample = uint16(v);
-        end
-        
-        function obj = set.encoding_space_ref(obj,v)
-            obj.encoding_space_ref = uint16(v);
-        end
-        
-        function obj = set.trajectory_dimensions(obj,v)
-            obj.trajectory_dimensions = uint16(v);
-        end
-        
-        function obj = set.sample_time_us(obj,v)
-            obj.sample_time_us = single(v);
-        end
-        
-        function obj = set.position(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.position must have 3 elements')
+        function bytes = toBytes(obj)
+            % Convert to an ISMRMRD AcquisitionHeader struct to a byte array.
+
+            N = obj.getNumber;
+            
+            % TODO: physiology_time_stamp should be 3.
+            %bytes = zeros(340,N,'int8');
+            bytes = zeros(360,N,'int8');
+            for p = 1:N
+                off = 1;
+                bytes(off:off+1,p)   = typecast(obj.version(p)               ,'int8'); off=off+2;
+                bytes(off:off+7,p)   = typecast(obj.flags(p)                 ,'int8'); off=off+8;
+                bytes(off:off+3,p)   = typecast(obj.measurement_uid(p)       ,'int8'); off=off+4;
+                bytes(off:off+3,p)   = typecast(obj.scan_counter(p)          ,'int8'); off=off+4;
+                bytes(off:off+3,p)   = typecast(obj.acquisition_time_stamp(p),'int8'); off=off+4;
+
+                % TODO: physiology_time_stamp should be 3.
+                % but the C struct has a bug, so convert to padding.
+                bytes(off:off+11,p)  = typecast(obj.physiology_time_stamp(:,p) ,'int8'); off=off+12;
+                off = off+20; % Discard 5*uint32;
+
+                bytes(off:off+1,p)   = typecast(obj.number_of_samples(p)     ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.available_channels(p)    ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.active_channels(p)       ,'int8'); off=off+2;
+                bytes(off:off+127,p) = typecast(obj.channel_mask(:,p)        ,'int8'); off=off+128;
+                bytes(off:off+1,p)   = typecast(obj.discard_pre(p)           ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.discard_post(p)          ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.center_sample(p)         ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.encoding_space_ref(p)    ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.trajectory_dimensions(p) ,'int8'); off=off+2;
+                bytes(off:off+3,p)   = typecast(obj.sample_time_us(p)        ,'int8'); off=off+4;
+                bytes(off:off+11,p)  = typecast(obj.position(:,p)            ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.read_dir(:,p)            ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.phase_dir(:,p)           ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.slice_dir(:,p)           ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.patient_table_position(:,p),'int8'); off=off+12;
+                bytes(off:off+1,p)   = typecast(obj.idx.kspace_encode_step_1(p),'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.kspace_encode_step_2(p),'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.average(p)           ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.slice(p)             ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.contrast(p)          ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.phase(p)             ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.repetition(p)        ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.set(p)               ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.idx.segment(p)           ,'int8'); off=off+2;
+                bytes(off:off+15,p)  = typecast(obj.idx.user(:,p)            ,'int8'); off=off+16;
+                bytes(off:off+31,p)  = typecast(obj.user_int(:,p)            ,'int8'); off=off+32;
+                bytes(off:off+31,p)  = typecast(obj.user_float(:,p)          ,'int8');
             end
-            obj.position = single(v);
         end
         
-        function obj = set.read_dir(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.read_dir must have 3 elements')
+        function ret = flagIsSet(obj, flag, range)
+            if nargin < 3
+                range = 1:obj.getNumber;
             end
-            obj.read_dir = single(v);
-        end
-        
-        function obj = set.phase_dir(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.phase_dir must have 3 elements')
+            if isa(flag, 'char')
+                b = obj.FLAGS.(flag);
+            elseif (flag>0)
+                b = uint64(flag);
+            else
+                error('Flag is of the wrong type.'); 
             end
-            obj.phase_dir = single(v);
-        end
-        
-        function obj = set.slice_dir(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.slice_dir must have 3 elements')
+            bitmask = bitshift(uint64(1),(b-1));
+            ret = zeros(size(range));
+            for p = 1:length(range)
+                ret(p) = (bitand(obj.flags(range(p)), bitmask)>0);
             end
-            obj.slice_dir = single(v);
         end
         
-        function obj = set.patient_table_position(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.patient_table_position must have 3 elements')
+        function flagSet(obj, flag, range)
+            if nargin < 3
+                range = 1:obj.getNumber;
             end
-            obj.patient_table_position = single(v);
-        end
-        
-        function obj = set.idx(obj,v)
-            if isa(v,'ismrmrd.EncodingCounters')
-                obj.idx = v;
+            if isa(flag, 'char')
+                b = obj.FLAGS.(flag);
+            elseif (flag>0)
+                b = uint64(flag);
             else
-                % not of the correct type, hope it's a struct
-                % and try to copy one element at a time
-                u = fieldnames(obj.idx);
-                for p = 1:length(u)
-                    obj.idx = setfield(obj.idx,u{p},getfield(v,u{p}));
+                error('Flag is of the wrong type.'); 
+            end
+            bitmask = bitshift(uint64(1),(b-1));
+
+            alreadyset = obj.flagIsSet(flag,range);
+            for p = 1:length(range)
+                if ~alreadyset(p)
+                    obj.flags(range(p)) = obj.flags(range(p)) + bitmask;
                 end
             end
         end
         
-        function obj = set.user_int(obj,v)
-            if (length(v)~=8)
-                error('AcquisitionHeader.user_int must have 8 elements')
+        function flagClear(obj, flag, range)
+            if nargin < 3
+                range = 1:obj.getNumber;
             end
-            obj.user_int = int32(v);
-        end
-        
-        function obj = set.user_float(obj,v)
-            if (length(v)~=8)
-                error('AcquisitionHeader.user_float must have 8 elements')
+            
+            if isa(flag, 'char')
+                b = obj.FLAGS.(flag);
+            elseif (flag>0)
+                b = uint64(flag);
+            else
+                error('Flag is of the wrong type.'); 
+            end
+            bitmask = bitshift(uint64(1),(b-1));
+            
+            alreadyset = obj.flagIsSet(flag,range);
+            for p = 1:length(range)
+                if alreadyset(p)
+                    obj.flags(range(p)) = obj.flags(range(p)) - bitmask;
+                end
             end
-            obj.user_float = single(v);
+                
+            
         end
         
     end
diff --git a/matlab/+ismrmrd/EncodingCounters.m b/matlab/+ismrmrd/EncodingCounters.m
deleted file mode 100644
index 7f818b5..0000000
--- a/matlab/+ismrmrd/EncodingCounters.m
+++ /dev/null
@@ -1,94 +0,0 @@
-classdef EncodingCounters
-    
-    properties
-        kspace_encode_step_1 = uint16(0); % e.g. phase encoding line number %
-        kspace_encode_step_2 = uint16(0); % e.g. partition encodning number %
-        average              = uint16(0); % e.g. signal average number %
-        slice                = uint16(0); % e.g. imaging slice number %
-        contrast             = uint16(0); % e.g. echo number in multi-echo %
-        phase                = uint16(0); % e.g. cardiac phase number %
-        repetition           = uint16(0); % e.g. dynamic number for dynamic scanning %
-        set                  = uint16(0); % e.g. flow encodning set %
-        segment              = uint16(0); % e.g. segment number for segmented acquisition %
-        user                 = zeros(1,8,'uint16'); % Free user parameters %
-    end
-    
-    methods
-
-        % Constructor
-        function obj = EncodingCounters(bytes)
-            if (nargin == 1)
-                obj.kspace_encode_step_1 = typecast(bytes( 1: 2),'uint16');
-                obj.kspace_encode_step_2 = typecast(bytes( 3: 4),'uint16');
-                obj.average              = typecast(bytes( 5: 6),'uint16');
-                obj.slice                = typecast(bytes( 7: 8),'uint16');
-                obj.contrast             = typecast(bytes( 9:10),'uint16');
-                obj.phase                = typecast(bytes(11:12),'uint16');
-                obj.repetition           = typecast(bytes(13:14),'uint16');
-                obj.set                  = typecast(bytes(15:16),'uint16');
-                obj.segment              = typecast(bytes(17:18),'uint16');
-                obj.user                 = typecast(bytes(19:34),'uint16');
-            end
-        end
-
-        function bytes = toBytes(obj)
-            bytes = zeros(34,1,'int8');
-            bytes( 1: 2) = typecast(obj.kspace_encode_step_1,'int8');
-            bytes( 3: 4) = typecast(obj.kspace_encode_step_2,'int8');
-            bytes( 5: 6) = typecast(obj.average             ,'int8');
-            bytes( 7: 8) = typecast(obj.slice               ,'int8');
-            bytes( 9:10) = typecast(obj.contrast            ,'int8');
-            bytes(11:12) = typecast(obj.phase               ,'int8');
-            bytes(13:14) = typecast(obj.repetition          ,'int8');
-            bytes(15:16) = typecast(obj.set                 ,'int8');
-            bytes(17:18) = typecast(obj.segment             ,'int8');
-            bytes(19:34) = typecast(obj.user                ,'int8');
-        end
-        
-        % Set methods
-        function obj = set.kspace_encode_step_1(obj,v)
-            obj.kspace_encode_step_1 = uint16(v);
-        end
-        
-        function obj = set.kspace_encode_step_2(obj,v)
-            obj.kspace_encode_step_2 = uint16(v);
-        end
-        
-        function obj = set.average(obj,v)
-            obj.average = uint16(v);
-        end
-        
-        function obj = set.slice(obj,v)
-            obj.slice = uint16(v);
-        end
-        
-        function obj = set.contrast(obj,v)
-            obj.contrast = uint16(v);
-        end
-        
-        function obj = set.phase(obj,v)
-            obj.phase = uint16(v);
-        end
-        
-        function obj = set.repetition(obj,v)
-            obj.repetition = uint16(v);
-        end
-        
-        function obj = set.set(obj,v)
-            obj.set = uint16(v);
-        end
-        
-        function obj = set.segment(obj,v)
-            obj.segment = uint16(v);
-        end
-        
-        function obj = set.user(obj,v)
-            if (length(v)~=8)
-                error('EncodingCounters.user must have 8 elements')
-            end
-            obj.user = uint16(v);
-        end
-        
-    end
-   
-end % EncodingCounters
diff --git a/matlab/+ismrmrd/FlagBit.m b/matlab/+ismrmrd/FlagBit.m
deleted file mode 100644
index 6008c16..0000000
--- a/matlab/+ismrmrd/FlagBit.m
+++ /dev/null
@@ -1,32 +0,0 @@
-classdef FlagBit
-    
-    properties
-        bitmask = uint64(0);
-    end
-    
-    methods
-        function obj = FlagBit(b)
-            if ~(b>0)
-                error('b must be positive');
-            else
-                obj.bitmask = bitshift(uint16(1),(b-1));
-            end
-        end % FlagBit
-    end
-    
-    methods
-        
-        function obj = set.bitmask(obj,b)
-            obj.bitmask = uint64(b);
-        end % bitmask set function
-        
-        function b = isSet(obj,m)
-            if (bitand(obj.bitmask, uint64(m))>0)
-                b = true;
-            else
-                b = false;
-            end
-        end % isSet
-    end
-    
-end % classdef
\ No newline at end of file
diff --git a/matlab/+ismrmrd/old/Image.m b/matlab/+ismrmrd/Image.m
similarity index 84%
rename from matlab/+ismrmrd/old/Image.m
rename to matlab/+ismrmrd/Image.m
index fe591b8..2f75783 100644
--- a/matlab/+ismrmrd/old/Image.m
+++ b/matlab/+ismrmrd/Image.m
@@ -1,6 +1,6 @@
 % Image
 classdef Image
-    
+
     % Properties
     properties
 
@@ -8,28 +8,28 @@ classdef Image
         data_ = [];
 
     end % Properties
-    
+
     % Methods
     methods
 
         function obj = set.head_(obj,v)
             obj.head_ = v;
         end
-        
+
         function obj = set.data_(obj,v)
             obj.data_ = single(complex(v));
         end
-        
+
         function b = isFlagSet(obj,flag)
             bitflag = ismrmrd.FlagBit(flag);
             b = bitflag.isSet(obj.head_.flag);
         end
-        
+
         function obj = setFlag(obj,flag)
-            bitflag = ismrmrd.FlagBit(flag);            
+            bitflag = ismrmrd.FlagBit(flag);
             obj.head_.flag = bitor(obj.head_.flag, bitflag.bitmask_);
         end
-        
+
     end % Methods
-    
-end
\ No newline at end of file
+
+end
diff --git a/matlab/+ismrmrd/ImageDataType.m b/matlab/+ismrmrd/ImageDataType.m
deleted file mode 100644
index e231a58..0000000
--- a/matlab/+ismrmrd/ImageDataType.m
+++ /dev/null
@@ -1,9 +0,0 @@
-classdef ImageDataType
-    properties(Constant)
-        DATA_FLOAT = 1,
-        DATA_DOUBLE = 2,
-        DATA_COMPLEX_FLOAT = 3,
-        DATA_COMPLEX_DOUBLE = 4,
-        DATA_UNSIGNED_SHORT = 5
-    end
-end
diff --git a/matlab/+ismrmrd/ImageFlags.m b/matlab/+ismrmrd/ImageFlags.m
deleted file mode 100644
index fda74b5..0000000
--- a/matlab/+ismrmrd/ImageFlags.m
+++ /dev/null
@@ -1,14 +0,0 @@
-% IMAGE FLAGS %
-classdef ImageFlags
-    properties(Constant)
-        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
-    end
-end
\ No newline at end of file
diff --git a/matlab/+ismrmrd/ImageHeader.m b/matlab/+ismrmrd/ImageHeader.m
index 6503b0f..9c0940b 100644
--- a/matlab/+ismrmrd/ImageHeader.m
+++ b/matlab/+ismrmrd/ImageHeader.m
@@ -1,236 +1,396 @@
-classdef ImageHeader
+classdef ImageHeader < handle
     
     properties
-        version = uint16(0);                          % First unsigned int indicates the version %
-        flags = uint64(0);                            % bit field with flags %
-        measurement_uid = uint32(0);                  % Unique ID for the measurement %
-        matrix_size = zeros(3,1,'uint16');            % Pixels in the 3 spatial dimensions
-        field_of_view = zeros(3,1,'single');          % Size (in mm) of the 3 spatial dimensions %
-        channels = uint16(0);                         % Number of receive channels %
-        position = zeros(3,1,'single');               % Three-dimensional spatial offsets from isocenter %
-        read_dir = zeros(3,1,'single');               % Directional cosines of the readout/frequency encoding %
-        phase_dir = zeros(3,1,'single');              % Directional cosines of the phase encoding %
-        slice_dir = zeros(3,1,'single');              % Directional cosines of the slice %
-        patient_table_position = zeros(3,1,'single'); % Patient table off-center %
-        average = uint16(0);                          % e.g. signal average number %
-        slice = uint16(0);                            % e.g. imaging slice number %
-        contrast = uint16(0);                         % e.g. echo number in multi-echo %
-        phase = uint16(0);                            % e.g. cardiac phase number %
-        repetition = uint16(0);                       % e.g. dynamic number for dynamic scanning %
-        set = uint16(0);                              % e.g. flow encodning set %
-        acquisition_time_stamp = uint32(0);           % Acquisition clock %
-        physiology_time_stamp = zeros(8,1,'uint32');  % Physiology time stamps, e.g. ecg, breating, etc. %
-        image_data_type = uint16(0);                  % e.g. unsigned short, float, complex float, etc. %
-        image_type = uint16(0);                       % e.g. magnitude, phase, complex, real, imag, etc. %
-        image_index = uint16(0);					  % e.g. image number in series of images  %
-        image_series_index = uint16(0);               % e.g. series number %
-        user_int = zeros(8,1,'int32');                % Free user parameters %
-        user_float = zeros(8,1,'single');             % Free user parameters %
+        
+        version = uint16([]);                % First unsigned int indicates the version %
+        flags = uint64([]);                  % bit field with flags %
+        measurement_uid = uint32([]);        % Unique ID for the measurement %
+        matrix_size = uint16([]);            % Pixels in the 3 spatial dimensions
+        field_of_view = single([]);          % Size (in mm) of the 3 spatial dimensions %
+        channels = uint16([]);               % Number of receive channels %
+        position = single([]);               % Three-dimensional spatial offsets from isocenter %
+        read_dir = single([]);               % Directional cosines of the readout/frequency encoding %
+        phase_dir = single([]);              % Directional cosines of the phase encoding %
+        slice_dir = single([]);              % Directional cosines of the slice %
+        patient_table_position = single([]); % Patient table off-center %
+        average = uint16([]);                % e.g. signal average number %
+        slice = uint16([]);                  % e.g. imaging slice number %
+        contrast = uint16([]);               % e.g. echo number in multi-echo %
+        phase = uint16([]);                  % e.g. cardiac phase number %
+        repetition = uint16([]);             % e.g. dynamic number for dynamic scanning %
+        set = uint16([]);                    % e.g. flow encodning set %
+        acquisition_time_stamp = uint32([]); % Acquisition clock %
+        physiology_time_stamp = uint32([]);  % Physiology time stamps, e.g. ecg, breating, etc. %
+        image_data_type = uint16([]);        % e.g. unsigned short, float, complex float, etc. %
+        image_type = uint16([]);             % e.g. magnitude, phase, complex, real, imag, etc. %
+        image_index = uint16([]);			 % e.g. image number in series of images  %
+        image_series_index = uint16([]);     % e.g. series number %
+        user_int = int32([]);                % Free user parameters %
+        user_float = single([]);             % Free user parameters %
+        
+    end
+
+    properties(Constant)
+        FLAGS = struct( ...
+            '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);
+        
+        DATA_TYPE = struct( ...
+            'FLOAT',          uint16(1), ...
+            'DOUBLE',         uint16(2), ...
+            'COMPLEX_FLOAT',  uint16(3), ...
+            'COMPLEX_DOUBLE', uint16(4), ...
+            'UNSIGNED_SHORT', uint16(5));
+        
+        IMAGE_TYPE = struct( ...
+            'TYPE_MAGNITUDE', uint16(1), ...
+            'TYPE_PHASE',     uint16(2), ...
+            'TYPE_REAL',      uint16(3), ...
+            'TYPE_IMAG',      uint16(4), ...
+            'TYPE_COMPLEX',   uint16(5));
+
     end
     
     methods
         
-        % Constructor
-        function obj = ImageHeader(bytes)
-            if (nargin == 1)
-                off = 1;
-                obj.version                = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.flags                  = typecast(bytes(off:off+7),  'uint64'); off=off+8;
-                obj.measurement_uid        = typecast(bytes(off:off+3),  'uint32'); off=off+4;
-                obj.matrix_size            = typecast(bytes(off:off+5),  'uint16'); off=off+6;
-                obj.field_of_view          = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.channels               = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.position               = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.read_dir               = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.phase_dir              = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.slice_dir              = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.patient_table_position = typecast(bytes(off:off+11), 'single'); off=off+12;
-                obj.average                = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.slice                  = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.contrast               = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.phase                  = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.repetition             = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.set                    = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.acquisition_time_stamp = typecast(bytes(off:off+3),  'uint32'); off=off+4;
-                obj.physiology_time_stamp  = typecast(bytes(off:off+31), 'uint32'); off=off+32;
-                obj.image_data_type        = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.image_type             = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.image_index            = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.image_series_index     = typecast(bytes(off:off+1),  'uint16'); off=off+2;
-                obj.user_int               = typecast(bytes(off:off+31), 'uint32'); off=off+32;
-                obj.user_float             = typecast(bytes(off:off+31), 'single');
+        function obj = ImageHeader(arg)
+            switch nargin
+                case 0
+                    % No argument constructor
+                    % initialize to a single image header
+                    extend(obj,1);
+                    
+                case 1
+                    % One argument constructor
+                    if isstruct(arg)
+                        % plain struct
+                        fromStruct(obj,arg);
+                    elseif (length(arg)==1 && ismrmrd.util.isInt(arg)) == 1
+                        % number
+                        extend(obj,arg);
+                    elseif isa(arg,'int8')
+                        % Byte array
+                        fromBytes(obj,arg);
+                    else
+                        % Unknown type
+                        error('Unknown argument type.')
+                    end
+                    
+                otherwise
+                    error('Wrong number of arguments.')
+                    
             end
         end
         
-        function bytes = toBytes(obj)
-            bytes = zeros(214,1,'int8');
-            off = 1;
-            bytes(off:off+1)   = typecast(obj.version               ,'int8'); off=off+2;
-            bytes(off:off+7)   = typecast(obj.flags                 ,'int8'); off=off+8;
-            bytes(off:off+3)   = typecast(obj.measurement_uid       ,'int8'); off=off+4;
-            bytes(off:off+5)   = typecast(obj.matrix_size           ,'int8'); off=off+6;
-            bytes(off:off+11)  = typecast(obj.field_of_view         ,'int8'); off=off+12;
-            bytes(off:off+1)   = typecast(obj.channels              ,'int8'); off=off+2;
-            bytes(off:off+11)  = typecast(obj.position              ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.read_dir              ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.phase_dir             ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.slice_dir             ,'int8'); off=off+12;
-            bytes(off:off+11)  = typecast(obj.patient_table_position,'int8'); off=off+12;
-            bytes(off:off+1)   = typecast(obj.average               ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.slice                 ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.contrast              ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.phase                 ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.repetition            ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.set                   ,'int8'); off=off+2;
-            bytes(off:off+3)   = typecast(obj.acquisition_time_stamp,'int8'); off=off+4;
-            bytes(off:off+31)  = typecast(obj.physiology_time_stamp ,'int8'); off=off+32;
-            bytes(off:off+1)   = typecast(obj.image_data_type       ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.image_type            ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.image_index           ,'int8'); off=off+2;
-            bytes(off:off+1)   = typecast(obj.image_series_index    ,'int8'); off=off+2;
-            bytes(off:off+31)  = typecast(obj.user_int              ,'int8'); off=off+32;
-            bytes(off:off+31)  = typecast(obj.user_float            ,'int8');
+        function nacq = getNumber(obj)
+            nacq = length(obj.version);
         end
         
-        % The flag methods
-        function val = isFlagSet(obj,flagstring)
-            flagbit = ismrmrd.FlagBit(getfield(ismrmrd.ImageFlags,flagstring));
-            val = flagbit.isSet(obj.flags);
-        end
+        function hdr = select(obj, range)
+            % Return a copy of a range of image headers
+            
+            % create an empty image header
+            M = length(range);
+            hdr = ismrmrd.ImageHeader(M);
+            
+            % Fill
+            hdr.version = obj.version(range);
+            hdr.flags = obj.flags(range);
+            hdr.measurement_uid = obj.measurement_uid(range);
+            hdr.matrix_size = obj.matrix_size(:,range);
+            hdr.field_of_view = obj.field_of_view(:,range);
+            hdr.channels = obj.channels(:,range);
+            hdr.position = obj.position(:,range);
+            hdr.read_dir = obj.read_dir(:,range);
+            hdr.phase_dir = obj.phase_dir(:,range);
+            hdr.slice_dir = obj.slice_dir(:,range);
+            hdr.patient_table_position = obj.patient_table_position(:,range);
+            hdr.average = obj.average(range);
+            hdr.slice = obj.slice(range);
+            hdr.contrast = obj.contrast(range);
+            hdr.phase = obj.phase(range);
+            hdr.repetition = obj.repetition(range);
+            hdr.set = obj.set(range);
+            hdr.acquisition_time_stamp = obj.acquisition_time_stamp(range);
+            hdr.physiology_time_stamp = obj.physiology_time_stamp(:,range);
+            hdr.image_data_type = obj.image_data_type(range);
+            hdr.image_type = obj.image_type(range);
+            hdr.image_index = obj.image_index(range);
+            hdr.image_series_index = obj.image_series_index(range);
+            hdr.user_int = obj.user_int(:,range);
+            hdr.user_float = obj.user_float(:,range);
+
+        end        
         
-        function obj = setFlag(obj,flagstring)
-            flagbit = ismrmrd.FlagBit(getfield(ismrmrd.ImageFlags,flagstring));
-            obj.flags = bitor(obj.flags, flagbit.bitmask);
+        function extend(obj,N)
+            % Extend with blank header
+
+            range = obj.getNumber + (1:N);            
+            obj.version(1,range)                  = zeros(1,N,'uint16');
+            obj.flags(1,range)                    = zeros(1,N,'uint64');
+            obj.measurement_uid(1,range)          = zeros(1,N,'uint32');
+            obj.matrix_size(1:3,range)            = zeros(3,N,'uint16');
+            obj.field_of_view(1:3,range)          = zeros(3,N,'single');
+            obj.channels(1,range)                 = zeros(1,N,'uint16');
+            obj.position(1:3,range)               = zeros(3,N,'single');
+            obj.read_dir(1:3,range)               = zeros(3,N,'single');
+            obj.phase_dir(1:3,range)              = zeros(3,N,'single');
+            obj.slice_dir(1:3,range)              = zeros(3,N,'single');
+            obj.patient_table_position(1:3,range) = zeros(3,N,'single');
+            obj.average(1,range)                  = zeros(1,N,'uint16');
+            obj.slice(1,range)                    = zeros(1,N,'uint16');
+            obj.contrast(1,range)                 = zeros(1,N,'uint16');
+            obj.phase(1,range)                    = zeros(1,N,'uint16');
+            obj.repetition(1,range)               = zeros(1,N,'uint16');
+            obj.set(1,range)                      = zeros(1,N,'uint16');
+            obj.acquisition_time_stamp(1,range)   = zeros(1,N,'uint32');
+            obj.physiology_time_stamp(1:3,range)  = zeros(3,N,'uint32');
+            obj.image_data_type(1,range)          = zeros(1,N,'uint16');
+            obj.image_type(1,range)               = zeros(1,N,'uint16');
+            obj.image_index(1,range)              = zeros(1,N,'uint16');
+            obj.image_series_index(1,range)       = zeros(1,N,'uint16');
+            obj.user_int(1:8,range)               = zeros(8,N,'int32');
+            obj.user_float(1:8,range)             = zeros(8,N,'single');
         end
         
-        % Set methods
-        function obj = set.version(obj,v)
-            obj.version = uint16(v);
+        function append(obj, head)
+            Nstart = obj.getNumber + 1;
+            Nend   = obj.getNumber + length(head.version);
+            Nrange = Nstart:Nend;
+            obj.version(Nrange) = hdr.version;
+            obj.flags(Nrange) = hdr.flags;
+            obj.measurement_uid(Nrange) = hdr.measurement_uid;
+            obj.matrix_size(:,Nrange) = hdr.matrix_size;
+            obj.field_of_view(:,Nrange) = hdr.field_of_view;
+            obj.channels(Nrange) = hdr.channels;
+            obj.position(:,Nrange) = hdr.position;
+            obj.read_dir(:,Nrange) = hdr.read_dir;
+            obj.phase_dir(:,Nrange) = hdr.phase_dir;
+            obj.slice_dir(:,Nrange) = hdr.slice_dir;
+            obj.patient_table_position(:,Nrange) = hdr.patient_table_position;
+            obj.average(Nrange) = hdr.average;
+            obj.slice(Nrange) = hdr.slice;
+            obj.contrast(Nrange) = hdr.contrast;
+            obj.phase(Nrange) = hdr.phase;
+            obj.repetition(Nrange) = hdr.repetition;
+            obj.set(Nrange) = hdr.set;
+            obj.acquisition_time_stamp(Nrange) = hdr.acquisition_time_stamp;
+            obj.physiology_time_stamp(:,Nrange) = hdr.physiology_time_stamp;
+            obj.image_data_type(Nrange) = hdr.image_data_type;
+            obj.image_type(Nrange) = hdr.image_type;
+            obj.image_index(Nrange) = hdr.image_index;
+            obj.image_series_index(Nrange) = hdr.image_series_index;
+            obj.user_int(:,Nrange) = hdr.user_int;
+            obj.user_float(:,Nrange) = hdr.user_float;            
+            
         end
-        
-        function obj = set.flags(obj,v)
-            obj.flags = uint64(v);
+
+        function fromStruct(obj, hdr)
+            %warning! no error checking
+            obj.version = hdr.version;
+            obj.flags = hdr.flags;
+            obj.measurement_uid = hdr.measurement_uid;
+            obj.matrix_size = hdr.matrix_size;
+            obj.field_of_view = hdr.field_of_view;
+            obj.channels = hdr.channels;
+            obj.position = hdr.position;
+            obj.read_dir = hdr.read_dir;
+            obj.phase_dir = hdr.phase_dir;
+            obj.slice_dir = hdr.slice_dir;
+            obj.patient_table_position = hdr.patient_table_position;
+            obj.average = hdr.average;
+            obj.slice = hdr.slice;
+            obj.contrast = hdr.contrast;
+            obj.phase = hdr.phase;
+            obj.repetition = hdr.repetition;
+            obj.set = hdr.set;
+            obj.acquisition_time_stamp = hdr.acquisition_time_stamp;
+            obj.physiology_time_stamp = hdr.physiology_time_stamp;
+            obj.image_data_type = hdr.image_data_type;
+            obj.image_type = hdr.image_type;
+            obj.image_index = hdr.image_index;
+            obj.image_series_index = hdr.image_series_index;
+            obj.user_int = hdr.user_int;
+            obj.user_float = hdr.user_float;
         end
-        
-        function obj = set.measurement_uid(obj,v)
-            obj.measurement_uid = uint32(v);
+
+        function hdr = toStruct(obj)
+            %warning! no error checking
+            hdr = struct();
+            hdr.version = obj.version;
+            hdr.flags = obj.flags;
+            hdr.measurement_uid = obj.measurement_uid;
+            hdr.matrix_size = obj.matrix_size;
+            hdr.field_of_view = obj.field_of_view;
+            hdr.channels = obj.channels;
+            hdr.position = obj.position;
+            hdr.read_dir = obj.read_dir;
+            hdr.phase_dir = obj.phase_dir;
+            hdr.slice_dir = obj.slice_dir;
+            hdr.patient_table_position = obj.patient_table_position;
+            hdr.average = obj.average;
+            hdr.slice = obj.slice;
+            hdr.contrast = obj.contrast;
+            hdr.phase = obj.phase;
+            hdr.repetition = obj.repetition;
+            hdr.set = obj.set;
+            hdr.acquisition_time_stamp = obj.acquisition_time_stamp;
+            hdr.physiology_time_stamp = obj.physiology_time_stamp;
+            hdr.image_data_type = obj.image_data_type;
+            hdr.image_type = obj.image_type;
+            hdr.image_index = obj.image_index;
+            hdr.image_series_index = obj.image_series_index;
+            hdr.user_int = obj.user_int;
+            hdr.user_float = obj.user_float;            
         end
         
-        function obj = set.matrix_size(obj,v)
-            if (length(v)~=3)
-                error('ImageHeader.matrix_size must have 3 elements')
+        function fromBytes(obj, bytearray)
+
+            % TODO: physiology_time_stamp should be 3. So size will change
+            % from 214 to 194;
+            if size(bytearray,1) ~= 214
+                error('Wrong number of bytes for AcquisitionHeader.')
             end
-            obj.matrix_size = uint16(v);
+            N = size(bytearray,2);
+            for p = 1:N
+                obj.version(p)                  = typecast(bytes(1:2,p),     'uint16');
+                obj.flags(p)                    = typecast(bytes(3:10,p),    'uint64');
+                obj.measurement_uid(p)          = typecast(bytes(11:14,p),   'uint32');
+                obj.matrix_size(:,p)            = typecast(bytes(15:20,p),   'uint16');
+                obj.field_of_view(:,p)          = typecast(bytes(21:32,p),   'single');
+                obj.channels(p)                 = typecast(bytes(33:34,p),   'uint16');
+                obj.position(:,p)               = typecast(bytes(35:46,p),   'single');
+                obj.read_dir(:,p)               = typecast(bytes(47:58,p),   'single');
+                obj.phase_dir(:,p)              = typecast(bytes(59:70,p),   'single');
+                obj.slice_dir(:,p)              = typecast(bytes(71:82,p),   'single');
+                obj.patient_table_position(:,p) = typecast(bytes(83:94,p),   'single');
+                obj.average(p)                  = typecast(bytes(95:96,p),   'uint16');
+                obj.slice(p)                    = typecast(bytes(97:98,p),   'uint16');
+                obj.contrast(p)                 = typecast(bytes(99:100,p),  'uint16');
+                obj.phase(p)                    = typecast(bytes(101:102,p), 'uint16');
+                obj.repetition(p)               = typecast(bytes(103:104,p), 'uint16');
+                obj.set(p)                      = typecast(bytes(105:106,p), 'uint16');
+                obj.acquisition_time_stamp(p)   = typecast(bytes(107:110,p), 'uint32');
+                obj.physiology_time_stamp(:,p)  = typecast(bytes(111:122,p), 'uint32');
+                                    ... %   TODO: the C header has a bug.  3 is correct                
+                obj.image_data_type(p)          = typecast(bytes(143:144,p), 'uint16');
+                obj.image_type(p)               = typecast(bytes(145:146,p), 'uint16');
+                obj.image_index(p)              = typecast(bytes(147:148,p), 'uint16');
+                obj.image_series_index(p)       = typecast(bytes(149:150,p), 'uint16');
+                obj.user_int(:,p)               = typecast(bytes(151:182,p), 'uint32');
+                obj.user_float(:,p)             = typecast(bytes(183:214,p), 'single');
+            end              
         end
         
-        function obj = set.field_of_view(obj,v)
-            if (length(v)~=3)
-                error('ImageHeader.field_of_view must have 3 elements')
+        function bytes = toBytes(obj)
+            % Convert to an ISMRMRD AcquisitionHeader struct to a byte array.
+
+            N = obj.getNumber;
+            
+            % TODO: physiology_time_stamp should be 3.
+            %bytes = zeros(194,N,'int8');
+            bytes = zeros(214,N,'int8');
+            for p = 1:N
+                off = 1;
+                bytes(off:off+1,p)   = typecast(obj.version(p)                 ,'int8'); off=off+2;
+                bytes(off:off+7,p)   = typecast(obj.flags(p)                   ,'int8'); off=off+8;
+                bytes(off:off+3,p)   = typecast(obj.measurement_uid(p)         ,'int8'); off=off+4;
+                bytes(off:off+5,p)   = typecast(obj.matrix_size(:,p)           ,'int8'); off=off+6;
+                bytes(off:off+11,p)  = typecast(obj.field_of_view(:,p)         ,'int8'); off=off+12;
+                bytes(off:off+1,p)   = typecast(obj.channels(p)                ,'int8'); off=off+2;
+                bytes(off:off+11,p)  = typecast(obj.position(:,p)              ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.read_dir(:,p)              ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.phase_dir(:,p)             ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.slice_dir(:,p)             ,'int8'); off=off+12;
+                bytes(off:off+11,p)  = typecast(obj.patient_table_position(:,p),'int8'); off=off+12;
+                bytes(off:off+1,p)   = typecast(obj.average(p)                 ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.slice(p)                   ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.contrast(p)                ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.phase(p)                   ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.repetition(p)              ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.set(p)                     ,'int8'); off=off+2;
+                bytes(off:off+3,p)   = typecast(obj.acquisition_time_stamp(p)  ,'int8'); off=off+4;
+                % TODO: physiology_time_stamp should be 3.
+                % but the C struct has a bug, so convert to padding.
+                bytes(off:off+11,p)  = typecast(obj.physiology_time_stamp(:,p) ,'int8'); off=off+12;
+                off = off+20; % Discard 5*uint32;
+                bytes(off:off+1,p)   = typecast(obj.image_data_type(p)         ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.image_type(p)              ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.image_index(p)             ,'int8'); off=off+2;
+                bytes(off:off+1,p)   = typecast(obj.image_series_index(p)      ,'int8'); off=off+2;
+                bytes(off:off+31,p)  = typecast(obj.user_int(:,p)              ,'int8'); off=off+32;
+                bytes(off:off+31,p)  = typecast(obj.user_float(:,p)            ,'int8');
             end
-            obj.field_of_view = single(v);
         end
         
-        function obj = set.channels(obj,v)
-            obj.channels = uint16(v);
-        end
-        
-        function obj = set.position(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.position must have 3 elements')
+        function ret = flagIsSet(obj, flag, range)
+            if nargin < 3
+                range = 1:obj.getNumber;
             end
-            obj.position = single(v);
-        end
-        
-        function obj = set.read_dir(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.read_dir must have 3 elements')
+            if isa(flag, 'char')
+                b = obj.FLAGS.(flag);
+            elseif (flag>0)
+                b = uint64(flag);
+            else
+                error('Flag is of the wrong type.'); 
             end
-            obj.read_dir = single(v);
-        end
-        
-        function obj = set.phase_dir(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.phase_dir must have 3 elements')
+            bitmask = bitshift(uint64(1),(b-1));
+            ret = zeros(size(range));
+            for p = 1:length(range)
+                ret(p) = (bitand(obj.flags(range(p)), bitmask)>0);
             end
-            obj.phase_dir = single(v);
         end
         
-        function obj = set.slice_dir(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.slice_dir must have 3 elements')
+        function flagSet(obj, flag, range)
+            if nargin < 3
+                range = 1:obj.getNumber;
             end
-            obj.slice_dir = single(v);
-        end
-        
-        function obj = set.patient_table_position(obj,v)
-            if (length(v)~=3)
-                error('AcquisitionHeader.patient_table_position must have 3 elements')
+            if isa(flag, 'char')
+                b = obj.FLAGS.(flag);
+            elseif (flag>0)
+                b = uint64(flag);
+            else
+                error('Flag is of the wrong type.'); 
             end
-            obj.patient_table_position = single(v);
-        end
-        
-        function obj = set.average(obj,v)
-            obj.average = uint16(v);
-        end
-        
-        function obj = set.slice(obj,v)
-            obj.slice = uint16(v);
-        end
-        
-        function obj = set.contrast(obj,v)
-            obj.contrast = uint16(v);
-        end
-        
-        function obj = set.phase(obj,v)
-            obj.phase = uint16(v);
-        end
-        
-        function obj = set.repetition(obj,v)
-            obj.repetition = uint16(v);
-        end
-        
-        function obj = set.set(obj,v)
-            obj.set = uint16(v);
-        end
-        
-        function obj = set.acquisition_time_stamp(obj,v)
-            obj.acquisition_time_stamp = uint32(v);
-        end
-        
-        function obj = set.physiology_time_stamp(obj,v)
-            if (length(v)~=8)
-                error('AcquisitionHeader.physiology_time_stamp must have 8 elements')
+            bitmask = bitshift(uint64(1),(b-1));
+
+            alreadyset = obj.flagIsSet(flag,range);
+            for p = 1:length(range)
+                if ~alreadyset(p)
+                    obj.flags(range(p)) = obj.flags(range(p)) + bitmask;
+                end
             end
-            obj.physiology_time_stamp = uint32(v);
-        end
-        
-        function obj = set.image_data_type(obj,v)
-            obj.image_data_type = uint16(v);
         end
         
-        function obj = set.image_type(obj,v)
-            obj.image_type = uint16(v);
-        end
-        
-        function obj = set.image_index(obj,v)
-            obj.image_index = uint16(v);
-        end
-        function obj = set.image_series_index(obj,v)
-            obj.image_series_index = uint16(v);
-        end
-        
-        function obj = set.user_int(obj,v)
-            if (length(v)~=8)
-                error('AcquisitionHeader.user_int must have 8 elements')
+        function flagClear(obj, flag, range)
+            if nargin < 3
+                range = 1:obj.getNumber;
             end
-            obj.user_int = int32(v);
-        end
-        
-        function obj = set.user_float(obj,v)
-            if (length(v)~=8)
-                error('AcquisitionHeader.user_float must have 8 elements')
+            
+            if isa(flag, 'char')
+                b = obj.FLAGS.(flag);
+            elseif (flag>0)
+                b = uint64(flag);
+            else
+                error('Flag is of the wrong type.'); 
+            end
+            bitmask = bitshift(uint64(1),(b-1));
+            
+            alreadyset = obj.flagIsSet(flag,range);
+            for p = 1:length(range)
+                if alreadyset(p)
+                    obj.flags(range(p)) = obj.flags(range(p)) - bitmask;
+                end
             end
-            obj.user_float = single(v);
+                
+            
         end
         
     end
diff --git a/matlab/+ismrmrd/ImageType.m b/matlab/+ismrmrd/ImageType.m
deleted file mode 100644
index 7e1cd59..0000000
--- a/matlab/+ismrmrd/ImageType.m
+++ /dev/null
@@ -1,9 +0,0 @@
-classdef ImageType
-    properties(Constant)
-        TYPE_MAGNITUDE = 1,
-        TYPE_PHASE = 2,
-        TYPE_REAL = 3,
-        TYPE_IMAG = 4,
-        TYPE_COMPLEX = 5
-    end
-end
diff --git a/matlab/+ismrmrd/old/file.m b/matlab/+ismrmrd/IsmrmrdDataset.m
similarity index 64%
rename from matlab/+ismrmrd/old/file.m
rename to matlab/+ismrmrd/IsmrmrdDataset.m
index ff71db1..d38fbae 100644
--- a/matlab/+ismrmrd/old/file.m
+++ b/matlab/+ismrmrd/IsmrmrdDataset.m
@@ -1,5 +1,4 @@
-% File
-classdef file
+classdef IsmrmrdDataset
 
     properties
         fid = -1;
@@ -7,12 +6,18 @@ classdef file
         datapath = '';
         xmlpath = '';
         xmlhdr = [];
+        htypes = [];
     end
-    
+
     methods
-        
-        function obj = file(filename,groupname)
-            
+
+        function obj = IsmrmrdDataset(filename,groupname)
+            % add the ismrmrd jar to the javaclasspath
+            ismrmrd.util.includejar();
+
+            % Set the hdf types
+            obj.htypes = ismrmrd.util.hdf5_datatypes;
+                      
             % If the file exists, open it for read/write
             % otherwise, create it
             if exist(filename,'file')
@@ -22,10 +27,10 @@ classdef file
                 obj.fid = H5F.create(filename,'H5F_ACC_TRUNC',fcpl,'H5P_DEFAULT');
                 H5P.close(fcpl);
             end
-            
+
             % Set the filename
             obj.filename = filename;
-            
+
             % Set the group name
             %   default is dataset
             if nargin == 1
@@ -35,34 +40,39 @@ classdef file
             grouppath = ['/' groupname];
             obj.xmlpath   = ['/' groupname '/xml'];
             obj.datapath  = ['/' groupname '/data'];
-            
+
             % Check if the group exists
             lapl_id=H5P.create('H5P_LINK_ACCESS');
             if (H5L.exists(obj.fid,grouppath,lapl_id) == 0)
-                % group does not exist, create it and set a default header
+                % group does not exist, create it
                 group_id = H5G.create(obj.fid, grouppath, 0);
                 H5G.close(group_id);
                 % create a default xml header object
-                obj.xmlhdr = ismrmrd.XMLHeader();
+                %obj.xmlhdr = ismrmrd.XMLHeader();
+                obj.xmlhdr = org.ismrm.ismrmrd.IsmrmrdHeader();
             else
                 % group exists, read the xml header
-                % and create a new convert it to an xml header object
-                obj.xmlhdr = ismrmrd.XMLHeader().stringToHeader(obj.readxml());
+                %obj.xmlhdr = ismrmrd.XMLHeader().stringToHeader(obj.readxml());
+                obj.xmlhdr = org.ismrm.ismrmrd.XMLString.StringToIsmrmrdHeader(obj.readxml());
             end
             H5P.close(lapl_id);
-        
+
         end
-        
+
         function obj = close(obj)
             % synchronize the xml header
-            xmlstring = ismrmrd.XMLHeader.headerToString(obj.xmlhdr);
-            obj.writexml(xmlstring);
+            obj.writexml(obj.xmlstring());
             % close the file
             H5F.close(obj.fid);
         end
+
+        function xmlstring = xmlstring(obj)
+            % convert xmlhdr to a string
+            %xmlstring = ismrmrd.XMLHeader.headerToString(obj.xmlhdr);
+            xmlstring = org.ismrm.ismrmrd.XMLString.IsmrmrdHeaderToString(obj.xmlhdr);
+        end
         
         function xmlstring = readxml(obj)
-            
             % Check if the XML header exists
             % TODO: set it's value to the default
             lapl_id=H5P.create('H5P_LINK_ACCESS');
@@ -73,13 +83,13 @@ classdef file
 
             % Open
             xml_id = H5D.open(obj.fid, obj.xmlpath);
-            
+
             % Get the type
             xml_dtype = H5D.get_type(xml_id);
-            
+
             % Read the data
             hdr = H5D.read(xml_id, xml_dtype, 'H5S_ALL', 'H5S_ALL', 'H5P_DEFAULT');
-            
+
             % Output depends on whether or not the stored string was variale length
             if (H5T.is_variable_str(xml_dtype))
                 xmlstring = hdr{1};
@@ -89,17 +99,19 @@ classdef file
 
             % Close the XML
             H5T.close(xml_dtype);
-            H5D.close (xml_id); 
+            H5D.close (xml_id);
         end
-        
+
         function writexml(obj,xmlstring)
             % No validation is performed.  You're on your own.
+            % make sure it's a char
+            xmlstring = char(xmlstring);
             
             % TODO: add error checking on the write and return a status
             % TODO: if the matlab variable length string bug is resolved
             % then we should change this logic to just modify the length
             % and overwrite.
-            
+
             % Check if the XML header exists
             %   if it does not exist, create it
             %   if it exists, modify the size appropriately
@@ -109,7 +121,7 @@ classdef file
                 H5L.delete(obj.fid, obj.xmlpath,'H5P_DEFAULT');
             end
             H5P.close(lapl_id);
-            
+
             % Set variable length string type
             xml_dtype = H5T.copy('H5T_C_S1');
             % Matlab is having trouble writing variable length strings
@@ -121,18 +133,22 @@ classdef file
             xml_id = H5D.create (obj.fid, obj.xmlpath, xml_dtype, ....
                                  xml_space_id, 'H5P_DEFAULT');
             H5S.close(xml_space_id);
-            
+
             % Write the data
             H5D.write(xml_id, xml_dtype, ...
                       'H5S_ALL', 'H5S_ALL', 'H5P_DEFAULT', xmlstring);
-            
+
             % Close the XML
             H5D.close(xml_id);
-            
         end
-        
+
         function nacq = getNumberOfAcquisitions(obj)
-            
+
+            % Check if the Data exists
+            lapl_id=H5P.create('H5P_LINK_ACCESS');
+            if (H5L.exists(obj.fid, obj.datapath, lapl_id) == 0)
+                error([obj.datapath ' does not exist in the HDF5 dataset.']);
+            end
             dset = H5D.open(obj.fid, obj.datapath);
             space = H5D.get_space(dset);
             H5S.get_simple_extent_dims(space);
@@ -143,64 +159,86 @@ classdef file
 
         end
 
-        function acq = readAcquisition(obj, nacq)
+        function block = readAcquisition(obj, start, stop)
+            if nargin == 1
+                % Read all the acquisitions
+                start = 1;
+                stop = -1;
+            elseif nargin == 2
+                % Read a single acquisition
+                stop = start;
+            end
+
+            % Check if the Data exists
+            lapl=H5P.create('H5P_LINK_ACCESS');
+            if (H5L.exists(obj.fid, obj.datapath, lapl) == 0)
+                error([obj.datapath ' does not exist in the HDF5 dataset.']);
+            end
 
             % Open the data
-            dset_id = H5D.open(obj.fid, obj.datapath);
+            dset = H5D.open(obj.fid, obj.datapath);
 
             % Open the data space
-            file_space_id = H5D.get_space(dset_id);
+            space = H5D.get_space(dset);
+            
+            % Get the size
+            H5S.get_simple_extent_dims(space);
+            [~,dims,~] = H5S.get_simple_extent_dims(space);
+            nacq = dims(1);
 
-            % Initialize the return object
-            acq = ismrmrd.Acquisition;
-        
             % Create a mem_space for reading
-            dims = [1 1];
-            mem_space_id = H5S.create_simple(2,dims,[]);
-
-            % Read the desired acquisition
-            offset = [nacq-1 0];
-            H5S.select_hyperslab(file_space_id,'H5S_SELECT_SET',offset,[1 1],[1 1],[1 1]);
-            d = H5D.read(dset_id, ismrmrd.hdf5_datatypes.getType_Acquisition, ...
-                            mem_space_id, file_space_id, 'H5P_DEFAULT');
-
-            % Set the structure bits
-            acq.head = d.head(1);
-            acq.traj = d.traj{1};
-            t = d.data{1};
-            acq.data = t(1:2:end) + 1j*t(2:2:end);
-            
+            if (stop >= start)
+                offset = [start-1 0];
+                dims = [stop-start+1 1];
+                mem_space = H5S.create_simple(2,dims,[]);
+            else
+                offset = [0 0];
+                dims = [nacq 1];
+                mem_space = H5S.create_simple(2,dims,[]);
+            end
+
+            % Read the desired acquisitions            
+            H5S.select_hyperslab(space,'H5S_SELECT_SET',offset,[1 1],[1 1],dims);
+            d = H5D.read(dset, obj.htypes.T_Acquisition, ...
+                         mem_space, space, 'H5P_DEFAULT');
+                     
+            % Pack'em
+            block = ismrmrd.Acquisition(d.head, d.traj, d.data);
+
             % Clean up
-            H5S.close(mem_space_id);
-            H5S.close(file_space_id);
-            H5D.close(dset_id);
+            H5S.close(mem_space);
+            H5S.close(space);
+            H5D.close(dset);
         end
-                
+
         function appendAcquisition(obj, acq)
             % Append an acquisition
-            
+
             % TODO: Check the type of the input
             
+            % The number of acquisitions that we are going to append
+            N = acq.getNumber();
+            
             % Check if the Data exists
             %   if it does not exist, create it
-            %   if it does exist increase it's size by one
+            %   if it does exist increase it's size
             lapl_id=H5P.create('H5P_LINK_ACCESS');
             if (H5L.exists(obj.fid, obj.datapath, lapl_id) == 0)
                 % Data does not exist
                 %   create with rank 2, unlimited, and set the chunk size
-                dims    = [1 1];
+                dims    = [N 1];
                 maxdims = [H5ML.get_constant_value('H5S_UNLIMITED') 1];
                 file_space_id = H5S.create_simple(2, dims, maxdims);
-                
+
                 dcpl = H5P.create('H5P_DATASET_CREATE');
                 chunk = [1 1];
                 H5P.set_chunk (dcpl, chunk);
                 data_id = H5D.create(obj.fid, obj.datapath, ...
-                                     ismrmrd.hdf5_datatypes.getType_Acquisition, ...
+                                     obj.htypes.T_Acquisition, ...
                                      file_space_id, dcpl);
                 H5P.close(dcpl);
                 H5S.close(file_space_id);
-                
+
             else
                 % Open the data
                 data_id = H5D.open(obj.fid, obj.datapath);
@@ -208,41 +246,35 @@ classdef file
                 % Open the data space
                 file_space_id = H5D.get_space(data_id);
 
-                % Get the size, increment by one
+                % Get the size, increment by N
                 H5S.get_simple_extent_dims(file_space_id);
                 [~,dims,~] = H5S.get_simple_extent_dims(file_space_id);
-                dims = [dims(1)+1, 1];
+                dims = [dims(1)+N, 1];
                 H5D.set_extent (data_id, dims);
                 H5S.close(file_space_id);
 
             end
             H5P.close(lapl_id);
-            
-            % Get the file space (room for one more acq)
+
+            % Get the file space
             file_space_id = H5D.get_space(data_id);
             [~,dims,~] = H5S.get_simple_extent_dims(file_space_id);
-            
-            % Select the last block
-            offset = [dims(1)-1 0];
-            H5S.select_hyperslab(file_space_id,'H5S_SELECT_SET',offset,[],[],[]);
-            
+
+            % Select the last N block
+            offset = [dims(1)-N 0];
+            H5S.select_hyperslab(file_space_id,'H5S_SELECT_SET',offset,[1 1],[1 1],[N 1]);
+
             % Mem space
-            mem_space_id = H5S.create_simple(2,[1 1],[]);
+            mem_space_id = H5S.create_simple(2,[N 1],[]);
 
             % Pack the acquisition into the correct struct for writing
-            swarn = warning('query','MATLAB:structOnObject');
-            warning('off', 'MATLAB:structOnObject')
-            d.head(1) = struct(acq.head);
-            d.head(1).idx = struct(acq.head.idx);
-            warning(swarn.state, 'MATLAB:structOnObject')            
-            d.traj{1} = acq.traj;
-            t = zeros(2*length(acq.data),1,'single');
-            t(1:2:end) = real(acq.data);
-            t(2:2:end) = imag(acq.data);
-            d.data{1} = t;
+            d = struct();
+            d.head = acq.head.toStruct();
+            d.traj = acq.traj;
+            d.data = acq.dataToFloat();
             
             % Write
-            H5D.write(data_id, ismrmrd.hdf5_datatypes.getType_Acquisition(), ...
+            H5D.write(data_id, obj.htypes.T_Acquisition, ...
                       mem_space_id, file_space_id, 'H5P_DEFAULT', d);
 
             % Clean up
@@ -250,7 +282,7 @@ classdef file
             H5S.close(file_space_id);
             H5D.close(data_id);
         end
-        
+
     end
-    
+
 end
diff --git a/matlab/+ismrmrd/XMLHeader.m b/matlab/+ismrmrd/XMLHeader.m
deleted file mode 100644
index eca3ebc..0000000
--- a/matlab/+ismrmrd/XMLHeader.m
+++ /dev/null
@@ -1,33 +0,0 @@
-classdef XMLHeader
-
-    methods
-
-        function obj = XMLHeader(xmlstr)
-
-            obj.factory = org.ismrm.ismrmrd.xmlhdr.ObjectFactory(); 
-        end
-
-        function hdr = fromString(obj,xmlstring)
-            import javax.xml.bind.*
-            jc = JAXBContext.newInstance('org.ismrm.ismrmrd.xmlhdr', obj.factory.getClass().getClassLoader());
-            u  = jc.createUnmarshaller();
-            jstr = java.lang.String(xmlstring);
-            hdr = u.unmarshal(java.io.ByteArrayInputStream(jstr.getBytes()));
-
-        end
-
-        function xmlstring = toString(obj)
-            import javax.xml.bind.*
-            jc = JAXBContext.newInstance('org.ismrm.ismrmrd.xmlhdr', obj.factory.getClass().getClassLoader());
-            m  = jc.createMarshaller();
-            m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, 'http://www.ismrm.org/ISMRMD ismrmrd.xsd');
-
-            strbuff = java.io.StringWriter();
-            m.marshal(hdr, strbuff);
-            xmlstring = strbuff.toString();
-
-        end
-
-    end
-
-end
diff --git a/matlab/+ismrmrd/old/Acquisition.m b/matlab/+ismrmrd/old/Acquisition.m
deleted file mode 100644
index e9e4fe3..0000000
--- a/matlab/+ismrmrd/old/Acquisition.m
+++ /dev/null
@@ -1,49 +0,0 @@
-% Acquisition
-classdef Acquisition
-    
-    % Properties
-    properties
-
-        head = ismrmrd.AcquisitionHeader;
-        traj = single([]);
-        data = single([]);
-
-    end % Properties
-    
-    % Methods
-    methods
-        
-        function obj = set.head(obj,v)
-            if isa(v,'ismrmrd.AcquisitionHeader')
-                obj.head = v;
-            else
-                % not of the correct type, hope it's a struct 
-                % and try to copy one element at a time
-                u = fieldnames(obj.head);
-                for p = 1:length(u)
-                    obj.head = setfield(obj.head,u{p},getfield(v,u{p}));
-                end
-            end
-        end
-        
-        function obj = set.traj(obj,v)
-            obj.traj = single(v);
-        end
-        
-        function obj = set.data(obj,v)
-            obj.data = single(v);        
-        end
-
-        function b = isFlagSet(obj,flag)
-            bitflag = ismrmrd.FlagBit(flag);
-            b = bitflag.isSet(obj.head.flag);
-        end
-        
-        function obj = setFlag(obj,flag)
-            bitflag = ismrmrd.FlagBit(flag);            
-            obj.head.flag = bitor(obj.head.flag, bitflag.bitmask);
-        end
-        
-    end % Methods
-    
-end
\ No newline at end of file
diff --git a/matlab/CMakeLists.txt b/matlab/CMakeLists.txt
new file mode 100644
index 0000000..2b92ab0
--- /dev/null
+++ b/matlab/CMakeLists.txt
@@ -0,0 +1,72 @@
+find_package(Java)
+
+if (NOT JAVA_FOUND)
+    message(STATUS "Java (xjc) Not Found - Not generating XML bindings")
+else (NOT JAVA_FOUND)
+
+    set(ISMRMRD_SCHEMA ${CMAKE_SOURCE_DIR}/schema/ismrmrd.xsd)
+    set(ISMRMRD_JAR "${CMAKE_CURRENT_BINARY_DIR}/ismrmrd-matlab.jar")
+    set(ISMRMRD_PACKAGE "org/ismrm/ismrmrd")
+    set(ISMRMRD_PACKAGE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${ISMRMRD_PACKAGE}")
+
+    set(XML_STRING "XMLString")
+    set(XML_STRING_JAVA "XMLString.java")
+
+    set(XJC_CONFIG "cfg.jxb")
+    file (COPY ${XJC_CONFIG} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+
+    file (MAKE_DIRECTORY ${ISMRMRD_PACKAGE_PATH})
+    file (COPY ${XML_STRING_JAVA} DESTINATION ${ISMRMRD_PACKAGE_PATH})
+
+    foreach (class
+        ${XML_STRING}
+        AccelerationFactorType
+        ExperimentalConditionsType
+        MeasurementInformationType
+        TrajectoryDescriptionType
+        AcquisitionSystemInformationType
+        FieldOfViewMm
+        ObjectFactory
+        TrajectoryType
+        CalibrationModeType
+        InterleavingDimensionType
+        ParallelImagingType
+        UserParameterBase64Type
+        DicomParametersType
+        IsmrmrdHeader
+        ReferencedImageSequence
+        UserParameterDoubleType
+        Encoding
+        LimitType
+        SequenceParametersType
+        UserParameterLongType
+        EncodingLimitsType
+        MRImageModule
+        StudyInformationType
+        UserParameters
+        EncodingSpaceType
+        MatrixSize
+        SubjectInformationType
+        package-info
+    )
+        list (APPEND ISMRMRD_XJC_SOURCES "${ISMRMRD_PACKAGE}/${class}.java")
+        list (APPEND ISMRMRD_XJC_CLASSES "${ISMRMRD_PACKAGE}/${class}.class")
+    endforeach()
+
+    add_custom_command(
+        OUTPUT ${ISMRMRD_JAR}
+        COMMAND ${Java_XJC_EXECUTABLE} -quiet -b ${XJC_CONFIG} ${ISMRMRD_SCHEMA}
+        COMMAND ${Java_JAVAC_EXECUTABLE} ${ISMRMRD_XJC_SOURCES}
+        COMMAND ${Java_JAR_EXECUTABLE} cf ${ISMRMRD_JAR} ${ISMRMRD_XJC_CLASSES}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        COMMENT "Generating ISMRMRD XML bindings..." VERBATIM
+        DEPENDS ${ISMRMRD_SCHEMA} ${XML_STRING_JAVA}
+    )
+
+    # make a fake target called 'xxx.jar' that will be built
+    # when you type make and depends on the file 'xxx.jar'
+    add_custom_target(ismrmrd-matlab-jar ALL DEPENDS ${ISMRMRD_JAR})
+endif(NOT JAVA_FOUND)
+
+INSTALL(DIRECTORY +ismrmrd DESTINATION matlab)
+INSTALL(FILES ${ISMRMRD_JAR} DESTINATION matlab/+ismrmrd/+util)
diff --git a/matlab/XMLString.java b/matlab/XMLString.java
new file mode 100644
index 0000000..39127ca
--- /dev/null
+++ b/matlab/XMLString.java
@@ -0,0 +1,42 @@
+package org.ismrm.ismrmrd;
+
+import javax.xml.bind.*;
+import javax.xml.namespace.QName;
+import javax.xml.transform.stream.*;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+
+public class XMLString {
+    public static IsmrmrdHeader StringToIsmrmrdHeader(String xmlstring) throws javax.xml.bind.JAXBException
+    {
+        JAXBContext jaxbContext = JAXBContext.newInstance(IsmrmrdHeader.class);
+
+        Unmarshaller unmarshaller  = jaxbContext.createUnmarshaller();
+
+        StringReader reader = new StringReader(xmlstring);
+
+        JAXBElement<IsmrmrdHeader> root = unmarshaller.unmarshal(new StreamSource(reader), IsmrmrdHeader.class);
+
+        return root.getValue();
+    }
+
+    public static String IsmrmrdHeaderToString(IsmrmrdHeader header) throws javax.xml.bind.JAXBException
+    {
+        JAXBContext jaxbContext = JAXBContext.newInstance(IsmrmrdHeader.class);
+
+        Marshaller marshaller = jaxbContext.createMarshaller();
+
+        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.ismrm.org/ISMRMRD ismrmrd.xsd");
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+        StringWriter writer = new StringWriter();
+
+        QName qname = new QName("http://www.ismrm.org/ISMRMRD", "ismrmrdHeader");
+        JAXBElement<IsmrmrdHeader> root = new JAXBElement(qname, IsmrmrdHeader.class, header);
+
+        marshaller.marshal(root, writer);
+
+        return writer.toString();
+    }
+}
diff --git a/matlab/cfg.jxb b/matlab/cfg.jxb
new file mode 100644
index 0000000..696f66d
--- /dev/null
+++ b/matlab/cfg.jxb
@@ -0,0 +1,10 @@
+<jxb:bindings version="1.0"
+  xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+  xmlns:xs="http://www.w3.org/2001/XMLSchema"
+  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
+  jxb:extensionBindingPrefixes="xjc">
+    <jxb:bindings>
+        <jxb:globalBindings localScoping="toplevel">
+        </jxb:globalBindings>
+    </jxb:bindings>
+</jxb:bindings>
diff --git a/schema/ismrmrd.xsd b/schema/ismrmrd.xsd
index c020eec..4be1512 100644
--- a/schema/ismrmrd.xsd
+++ b/schema/ismrmrd.xsd
@@ -1,40 +1,22 @@
 <?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">
 
-  <xs:element name="ismrmrdHeader">
-    <xs:complexType>
+    <xs:element name="ismrmrdHeader" type="ismrmrdHeader"/>
+
+    <xs:complexType name="ismrmrdHeader">
       <xs:sequence>
 	<xs:element maxOccurs="1" minOccurs="0" name="subjectInformation" type="subjectInformationType"/>
 	<xs:element maxOccurs="1" minOccurs="0" name="studyInformation" type="studyInformationType"/>
 	<xs:element maxOccurs="1" minOccurs="0" name="measurementInformation" type="measurementInformationType"/>
 	<xs:element maxOccurs="1" minOccurs="0" name="acquisitionSystemInformation" type="acquisitionSystemInformationType"/>
 	<xs:element maxOccurs="1" minOccurs="1" name="experimentalConditions" type="experimentalConditionsType"/>
-	<xs:element maxOccurs="unbounded" minOccurs="1" name="encoding">
-	  <xs:complexType>
-	    <xs:all>
-	      <xs:element maxOccurs="1" minOccurs="1" name="encodedSpace" type="encodingSpaceType"/>
-	      <xs:element maxOccurs="1" minOccurs="1" name="reconSpace" type="encodingSpaceType"/>
-	      <xs:element maxOccurs="1" minOccurs="1" name="encodingLimits" type="encodingLimitsType"/>
-	      <xs:element maxOccurs="1" minOccurs="1" name="trajectory" type="trajectoryType"/>
-	      <xs:element maxOccurs="1" minOccurs="0" name="trajectoryDescription" type="trajectoryDescriptionType"/>
-	    </xs:all>
-	  </xs:complexType>
-	</xs:element>
+        <xs:element maxOccurs="unbounded" minOccurs="1" name="encoding" type="encoding"/>
 	<xs:element maxOccurs="1" minOccurs="0" name="parallelImaging" type="parallelImagingType"/>
 	<xs:element maxOccurs="1" minOccurs="0" name="sequenceParameters" type="sequenceParametersType"/>
         <xs:element maxOccurs="1" minOccurs="0" name="dicomParameters" type="dicomParametersType"/>
-	<xs:element maxOccurs="1" minOccurs="0" name="userParameters">
-	  <xs:complexType>
-	    <xs:sequence>
-	      <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterLong" type="userParameterLongType"/>
-	      <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterDouble" type="userParameterDoubleType"/>
-	      <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterBase64" type="userParameterBase64Type"/>
-	    </xs:sequence>
-	  </xs:complexType>
-	</xs:element>
+        <xs:element maxOccurs="1" minOccurs="0" name="userParameters" type="userParameters"/>
       </xs:sequence>
     </xs:complexType>
-  </xs:element>
 
   <xs:complexType name="subjectInformationType">
     <xs:all>
@@ -63,9 +45,27 @@
     </xs:all>
   </xs:complexType>
 
-  <xs:complexType name="experimentalConditionsType">
+  <xs:complexType name="measurementInformationType">
     <xs:all>
-      <xs:element name="H1resonanceFrequency_Hz" type="xs:long"/>
+      <xs:element minOccurs="1" name="seriesDate" type="xs:date"/>
+      <xs:element minOccurs="1" name="seriesTime" type="xs:time"/>
+      <xs:element minOccurs="1" name="patientPosition">
+        <xs:simpleType>
+          <xs:restriction base="xs:string">
+            <xs:enumeration value="HFP"/>
+            <xs:enumeration value="HFS"/>
+            <xs:enumeration value="HFDR"/>
+            <xs:enumeration value="HFDL"/>
+            <xs:enumeration value="FFP"/>
+            <xs:enumeration value="FFS"/>
+            <xs:enumeration value="FFDR"/>
+            <xs:enumeration value="FFDL"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:element>
+      <xs:element minOccurs="0" name="initialSeriesNumber" type="xs:long"/>
+      <xs:element minOccurs="0" name="protocolName" type="xs:string"/>
+      <xs:element minOccurs="0" name="seriesDescription" type="xs:string"/>
     </xs:all>
   </xs:complexType>
 
@@ -81,29 +81,45 @@
     </xs:all>
   </xs:complexType>
 
+  <xs:complexType name="experimentalConditionsType">
+    <xs:all>
+      <xs:element name="H1resonanceFrequency_Hz" type="xs:long"/>
+    </xs:all>
+  </xs:complexType>
+
+  <xs:complexType name="encoding">
+    <xs:all>
+      <xs:element maxOccurs="1" minOccurs="1" name="encodedSpace" type="encodingSpaceType"/>
+      <xs:element maxOccurs="1" minOccurs="1" name="reconSpace" type="encodingSpaceType"/>
+      <xs:element maxOccurs="1" minOccurs="1" name="encodingLimits" type="encodingLimitsType"/>
+      <xs:element maxOccurs="1" minOccurs="1" name="trajectory" type="trajectoryType"/>
+      <xs:element maxOccurs="1" minOccurs="0" name="trajectoryDescription" type="trajectoryDescriptionType"/>
+    </xs:all>
+  </xs:complexType>
+
   <xs:complexType name="encodingSpaceType">
     <xs:all>
-      <xs:element name="matrixSize">
-	<xs:complexType>
-	  <xs:sequence>
-	    <xs:element default="1" maxOccurs="1" minOccurs="1" name="x" type="xs:unsignedShort"/>
-	    <xs:element default="1" maxOccurs="1" minOccurs="1" name="y" type="xs:unsignedShort"/>
-	    <xs:element default="1" maxOccurs="1" minOccurs="1" name="z" type="xs:unsignedShort"/>
-	  </xs:sequence>
-	</xs:complexType>
-      </xs:element>
-      <xs:element name="fieldOfView_mm">
-	<xs:complexType>
-	  <xs:sequence>
-	    <xs:element maxOccurs="1" minOccurs="1" name="x" type="xs:float"/>
-	    <xs:element maxOccurs="1" minOccurs="1" name="y" type="xs:float"/>
-	    <xs:element maxOccurs="1" minOccurs="1" name="z" type="xs:float"/>
-	  </xs:sequence>
-	</xs:complexType>
-      </xs:element>
+      <xs:element maxOccurs="1" minOccurs="1" name="matrixSize" type="matrixSize"/>
+      <xs:element maxOccurs="1" minOccurs="1" name="fieldOfView_mm" type="fieldOfView_mm"/>
     </xs:all>
   </xs:complexType>
 
+  <xs:complexType name="matrixSize">
+    <xs:sequence>
+      <xs:element default="1" maxOccurs="1" minOccurs="1" name="x" type="xs:unsignedShort"/>
+      <xs:element default="1" maxOccurs="1" minOccurs="1" name="y" type="xs:unsignedShort"/>
+      <xs:element default="1" maxOccurs="1" minOccurs="1" name="z" type="xs:unsignedShort"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="fieldOfView_mm">
+    <xs:sequence>
+      <xs:element maxOccurs="1" minOccurs="1" name="x" type="xs:float"/>
+      <xs:element maxOccurs="1" minOccurs="1" name="y" type="xs:float"/>
+      <xs:element maxOccurs="1" minOccurs="1" name="z" type="xs:float"/>
+    </xs:sequence>
+  </xs:complexType>
+
   <xs:complexType name="limitType">
     <xs:all>
       <xs:element default="0" name="minimum" type="xs:unsignedShort"/>
@@ -148,11 +164,11 @@
   </xs:complexType>
 
   <xs:complexType name="sequenceParametersType">
-  	<xs:sequence>
-  		<xs:element minOccurs="1" maxOccurs="unbounded" type="xs:float" name="TR"/>
-  		<xs:element minOccurs="1" maxOccurs="unbounded" type="xs:float" name="TE"/>
-  		<xs:element minOccurs="0" maxOccurs="unbounded" type="xs:float" name="TI"/>
-  	</xs:sequence>
+    <xs:sequence>
+      <xs:element minOccurs="1" maxOccurs="unbounded" type="xs:float" name="TR"/>
+      <xs:element minOccurs="1" maxOccurs="unbounded" type="xs:float" name="TE"/>
+      <xs:element minOccurs="0" maxOccurs="unbounded" type="xs:float" name="TI"/>
+    </xs:sequence>
   </xs:complexType>
 
   <xs:complexType name="userParameterLongType">
@@ -176,68 +192,49 @@
     </xs:all>
   </xs:complexType>
 
-  <xs:complexType name="measurementInformationType">
+  <xs:complexType name="dicomParametersType">
     <xs:all>
-      <xs:element minOccurs="1" name="seriesDate" type="xs:date"/>
-      <xs:element minOccurs="1" name="seriesTime" type="xs:time"/>
-      <xs:element minOccurs="1" name="patientPosition">
+      <xs:element minOccurs="1" name="studyInstanceUID" type="xs:string"/>
+      <xs:element minOccurs="0" name="seriesInstanceUIDRoot" type="xs:string"/>
+      <xs:element minOccurs="0" name="frameOfReferenceUID" type="xs:string"/>
+      <xs:element minOccurs="0" name="referencedImageSequence" type="referencedImageSequence"/>
+      <xs:element minOccurs="0" name="MRImageModule" type="MRImageModule"/>
+    </xs:all>
+  </xs:complexType>
+
+  <xs:complexType name="referencedImageSequence">
+    <xs:sequence>
+      <xs:element minOccurs="0" maxOccurs="unbounded" name="referencedSOPInstanceUID" type="xs:string"/>
+    </xs:sequence>
+  </xs:complexType>
+      
+  <xs:complexType name="MRImageModule">
+    <xs:all>
+      <xs:element minOccurs="0" name="imageType" type="xs:string"/>
+      <xs:element minOccurs="0" name="scanningSequence" type="xs:string"/>
+      <xs:element minOccurs="0" name="sequenceVariant" type="xs:string"/>
+      <xs:element minOccurs="0" name="scanOptions" type="xs:string"/>
+      <xs:element minOccurs="0" name="mrAcquisitionType" type="xs:string"/>
+      <xs:element minOccurs="0" name="echoTrainLength" type="xs:long"/>
+      <xs:element minOccurs="0" name="triggerTime" type="xs:float"/>
+      <xs:element minOccurs="0" name="flipAngle_deg" type="xs:long"/>
+      <xs:element minOccurs="0" name="freqEncodingDirection">
         <xs:simpleType>
           <xs:restriction base="xs:string">
-            <xs:enumeration value="HFP"/>
-            <xs:enumeration value="HFS"/>
-            <xs:enumeration value="HFDR"/>
-            <xs:enumeration value="HFDL"/>
-            <xs:enumeration value="FFP"/>
-            <xs:enumeration value="FFS"/>
-            <xs:enumeration value="FFDR"/>
-            <xs:enumeration value="FFDL"/>
+            <xs:enumeration value="ROW"/>
+            <xs:enumeration value="COL"/>
           </xs:restriction>
         </xs:simpleType>
       </xs:element>
-      <xs:element minOccurs="0" name="initialSeriesNumber" type="xs:long"/>
-      <xs:element minOccurs="0" name="protocolName" type="xs:string"/>
-      <xs:element minOccurs="0" name="seriesDescription" type="xs:string"/>
     </xs:all>
   </xs:complexType>
 
-  <xs:complexType name="dicomParametersType">
-    <xs:all>
-      <xs:element minOccurs="1" name="studyInstanceUID" type="xs:string"/>
-      <xs:element minOccurs="0" name="seriesInstanceUIDRoot" type="xs:string"/>
-      <xs:element minOccurs="0" name="frameOfReferenceUID" type="xs:string"/>
-
-      <xs:element minOccurs="0" name="referencedImageSequence">
-        <xs:complexType>
-          <xs:sequence>
-            <xs:element minOccurs="0" maxOccurs="unbounded" name="referencedSOPInstanceUID" type="xs:string"/>
-          </xs:sequence>
-        </xs:complexType>
-      </xs:element>
-
-      <xs:element minOccurs="0" name="MRImageModule">
-        <xs:complexType>
-          <xs:all>
-            <xs:element minOccurs="0" name="imageType" type="xs:string"/>
-            <xs:element minOccurs="0" name="scanningSequence" type="xs:string"/>
-            <xs:element minOccurs="0" name="sequenceVariant" type="xs:string"/>
-            <xs:element minOccurs="0" name="scanOptions" type="xs:string"/>
-            <xs:element minOccurs="0" name="mrAcquisitionType" type="xs:string"/>
-            <xs:element minOccurs="0" name="echoTrainLength" type="xs:long"/>
-            <xs:element minOccurs="0" name="triggerTime" type="xs:float"/>
-            <xs:element minOccurs="0" name="flipAngle_deg" type="xs:long"/>
-            <xs:element minOccurs="0" name="freqEncodingDirection">
-              <xs:simpleType>
-                <xs:restriction base="xs:string">
-                  <xs:enumeration value="ROW"/>
-                  <xs:enumeration value="COL"/>
-                </xs:restriction>
-              </xs:simpleType>
-            </xs:element>
-          </xs:all>
-        </xs:complexType>
-      </xs:element>
-
-    </xs:all>
+  <xs:complexType name="userParameters">
+    <xs:sequence>
+      <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterLong" type="userParameterLongType"/>
+      <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterDouble" type="userParameterDoubleType"/>
+      <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterBase64" type="userParameterBase64Type"/>
+    </xs:sequence>
   </xs:complexType>
 
   <xs:complexType name="accelerationFactorType">

-- 
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