[ismrmrd] 04/129: Imported Upstream version 0.5.0
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:00:07 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch master
in repository ismrmrd.
commit ea29ddd0f5ce7bf77247f3a0a228fb583a19a829
Author: Ghislain Vaillant <ghisvail at gmail.com>
Date: Mon Mar 3 17:18:42 2014 +0000
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