[med-svn] [ismrmrd] 01/01: Imported Upstream version 1.3.1
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Fri Sep 18 08:36:04 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch upstream
in repository ismrmrd.
commit 5d43b530530cfc906d262379c506d4277ef5bbf1
Author: Ghislain Antony Vaillant <ghisvail at gmail.com>
Date: Fri Sep 18 09:34:54 2015 +0100
Imported Upstream version 1.3.1
---
.travis.yml | 17 +++
CMakeLists.txt | 86 ++++++------
README.md | 9 +-
cmake/FindJava.cmake | 212 ------------------------------
cmake/FindNumPy.cmake | 101 --------------
cmake/cpack_options.cmake.in | 12 +-
cmake/ismrmrd_cpack.cmake | 40 +++---
examples/c/CMakeLists.txt | 26 +++-
examples/c/README.md | 13 ++
examples/c/README.txt | 11 --
examples/c/main.c | 20 ++-
examples/data/.gitignore | 1 -
examples/data/README.txt | 17 ---
examples/matlab/todo.txt | 1 -
examples/python/ismrmrd_create_dataset.py | 174 ------------------------
examples/python/ismrmrd_recon_dataset.py | 132 -------------------
include/ismrmrd/ismrmrd.h | 4 +-
include/ismrmrd/xml.h | 10 +-
include/version.in | 1 +
libsrc/dataset.c | 41 +++---
libsrc/dataset.cpp | 20 +++
libsrc/ismrmrd.c | 9 +-
libsrc/ismrmrd.cpp | 29 +++-
libsrc/xml.cpp | 68 +++++++---
matlab/+ismrmrd/+xml/deserialize.m | 5 +-
matlab/+ismrmrd/+xml/serialize.m | 2 +
schema/ismrmrd.xsd | 6 +-
tests/CMakeLists.txt | 21 +++
tests/test_acquisitions.cpp | 172 ++++++++++++++++++++++++
tests/test_channels.cpp | 76 +++++++++++
tests/test_flags.cpp | 65 +++++++++
tests/test_images.cpp | 169 ++++++++++++++++++++++++
tests/test_ismrmrd.h | 4 +
tests/test_main.cpp | 26 ++++
tests/test_ndarray.cpp | 71 ++++++++++
tests/test_quaternions.cpp | 60 +++++++++
utilities/CMakeLists.txt | 106 +++++++--------
utilities/ismrmrd_info.cpp | 6 +-
utilities/recon_cartesian_2d.cpp | 95 +++++++------
39 files changed, 1056 insertions(+), 882 deletions(-)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..c5219cc
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: cpp
+
+compiler:
+ - gcc
+ - clang
+
+before_install:
+ - sudo apt-get update
+install:
+ - sudo apt-get install libboost-all-dev libhdf5-serial-dev h5utils doxygen
+
+before_script:
+ - mkdir build
+ - cd build
+ - cmake ..
+
+script: make && make check
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a8c27f2..0616fe8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,10 +50,10 @@ endif (WIN32)
#the flexible header. The micro number changes when there are small changes
#in the utility libraries, that don't affect the data format itself.
set(ISMRMRD_VERSION_MAJOR 1)
-set(ISMRMRD_VERSION_MINOR 2)
-set(ISMRMRD_VERSION_PATCH 3)
+set(ISMRMRD_VERSION_MINOR 3)
+set(ISMRMRD_VERSION_PATCH 1)
-set(ISMRMRD_XML_SCHEMA_SHA1 "99a63f4e8cf08ffc268f5ee8b8c8b2a1edf69412")
+set(ISMRMRD_XML_SCHEMA_SHA1 "9b899c6ad806bc2388c70461d6e5affe5cc6d750")
#Remove line breaks and white space that does not change the meaning of the schema
file(STRINGS ${CMAKE_SOURCE_DIR}/schema/ismrmrd.xsd SCHEMA_STRINGS) #Read all strings from file
@@ -91,6 +91,19 @@ endif()
set(ISMRMRD_VERSION_STRING ${ISMRMRD_VERSION_MAJOR}.${ISMRMRD_VERSION_MINOR}.${ISMRMRD_VERSION_PATCH})
set(ISMRMRD_SOVERSION ${ISMRMRD_VERSION_MAJOR}.${ISMRMRD_VERSION_MINOR})
+# Find HDF5 for dataset support
+find_package(HDF5 1.8 COMPONENTS C)
+
+if (HDF5_FOUND)
+ set (ISMRMRD_DATASET_SUPPORT true)
+ set (ISMRMRD_DATASET_SOURCES libsrc/dataset.c libsrc/dataset.cpp)
+ set (ISMRMRD_DATASET_INCLUDE_DIR ${HDF5_C_INCLUDE_DIR})
+ set (ISMRMRD_DATASET_LIBRARIES ${HDF5_LIBRARIES})
+else (HDF5_FOUND)
+ set (ISMRMRD_DATASET_SUPPORT false)
+ message (WARNING "HDF5 not found. Dataset and file support unavailable!")
+endif (HDF5_FOUND)
+
# Generate the version.h header file
find_package(Git)
if (GIT_FOUND)
@@ -111,43 +124,35 @@ install(FILES ${CMAKE_BINARY_DIR}/include/ismrmrd/version.h DESTINATION include/
# remember to add ${CMAKE_BINARY_DIR}/include to the include path
# --- VERSIONING (end) ----
-
-# --- Main Library (begin) ----
-# required packages for main library
-find_package(HDF5 1.8 COMPONENTS C REQUIRED)
+# --- Main Library (begin) ----
# in windows, install the HDF5 dependencies
-if (WIN32)
- if (ISMRMRD_INSTALL_DEPENDENCIES)
- if ( HDF5_FOUND )
- if(DEFINED ENV{HDF5_ROOT})
- set(HDF5_BIN_DIR $ENV{HDF5_ROOT}/bin)
- else (DEFINED ENV{HDF5_ROOT})
- set(HDF5_BIN_DIR ${HDF5_C_INCLUDE_DIR}/../bin)
- endif (DEFINED ENV{HDF5_ROOT})
- message("Install hdf5 libraries from ${HDF5_BIN_DIR} ")
- install( DIRECTORY ${HDF5_BIN_DIR} DESTINATION bin/.. FILES_MATCHING PATTERN "*.dll" )
- endif (HDF5_FOUND)
- endif (ISMRMRD_INSTALL_DEPENDENCIES)
-endif (WIN32)
+if (HDF5_FOUND AND WIN32 AND ISMRMRD_INSTALL_DEPENDENCIES)
+ if(DEFINED ENV{HDF5_ROOT})
+ set(HDF5_BIN_DIR $ENV{HDF5_ROOT}/bin)
+ else (DEFINED ENV{HDF5_ROOT})
+ set(HDF5_BIN_DIR ${HDF5_C_INCLUDE_DIR}/../bin)
+ endif (DEFINED ENV{HDF5_ROOT})
+ message("Install hdf5 libraries from ${HDF5_BIN_DIR} ")
+ install( DIRECTORY ${HDF5_BIN_DIR} DESTINATION bin/.. FILES_MATCHING PATTERN "*.dll" )
+endif (HDF5_FOUND AND WIN32 AND ISMRMRD_INSTALL_DEPENDENCIES)
# include directories for main library
set(ISMRMRD_TARGET_INCLUDE_DIRS
include
${CMAKE_BINARY_DIR}/include
- ${HDF5_C_INCLUDE_DIR}
+ ${ISMRMRD_DATASET_INCLUDE_DIR}
)
set(ISMRMRD_TARGET_SOURCES
libsrc/ismrmrd.c
libsrc/ismrmrd.cpp
- libsrc/dataset.c
- libsrc/dataset.cpp
libsrc/xml.cpp
libsrc/meta.cpp
+ ${ISMRMRD_DATASET_SOURCES}
)
-set(ISMRMRD_TARGET_LINK_LIBS ${HDF5_LIBRARIES})
+set(ISMRMRD_TARGET_LINK_LIBS ${ISMRMRD_DATASET_LIBRARIES})
# optional handling of system-installed pugixml
if(USE_SYSTEM_PUGIXML)
@@ -183,40 +188,35 @@ install(TARGETS ismrmrd DESTINATION lib)
install(DIRECTORY include/ismrmrd DESTINATION include)
# install the schema file
-install(FILES schema/ismrmrd.xsd
- DESTINATION share/ismrmrd/schema)
+install(FILES schema/ismrmrd.xsd DESTINATION share/ismrmrd/schema)
# install the cmake modules
-install(FILES
- cmake/FindIsmrmrd.cmake
- cmake/FindFFTW3.cmake
- cmake/FindNumPy.cmake
-DESTINATION
- share/ismrmrd/cmake
-)
+install(FILES cmake/FindIsmrmrd.cmake cmake/FindFFTW3.cmake DESTINATION share/ismrmrd/cmake)
# --- Main Library (end) ----
-# turn on testing
-enable_testing()
-
# process subdirectories
add_subdirectory(doc)
-add_subdirectory(examples/c)
+
add_subdirectory(utilities)
+if (HDF5_FOUND)
+ add_subdirectory(examples/c)
+endif (HDF5_FOUND)
+
+# TODO: make this work on Windows
+if (NOT WIN32)
+ add_subdirectory(tests)
+endif (NOT WIN32)
# install the matlab api
install(DIRECTORY matlab DESTINATION share/ismrmrd)
-# TODO build and install the python bindings
-
# Create package
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
include(${ISMRMRD_CMAKE_DIR}/ismrmrd_cpack.cmake)
if(CPACK_GENERATOR)
message(STATUS "Found CPack generators: ${CPACK_GENERATOR}")
- configure_file("${ISMRMRD_CMAKE_DIR}/cpack_options.cmake.in"
- ${ISMRMRD_CPACK_CFG_FILE} @ONLY)
+ configure_file("${ISMRMRD_CMAKE_DIR}/cpack_options.cmake.in" ${ISMRMRD_CPACK_CFG_FILE} @ONLY)
set(CPACK_PROJECT_CONFIG_FILE ${ISMRMRD_CPACK_CFG_FILE})
- include (CPack)
-endif()
+ include(CPack)
+endif(CPACK_GENERATOR)
diff --git a/README.md b/README.md
index 1f2be2d..2e1a516 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+[![Build Status](https://travis-ci.org/ismrmrd/ismrmrd.svg?branch=master)](https://travis-ci.org/ismrmrd/ismrmrd)
+
ISMRM Raw Data Format (ISMRMRD)
===============================
@@ -12,7 +14,7 @@ To download the source code, clone the git archive:
API Documentation can be found at https://ismrmrd.github.io/api/.
-You will need CMake, HDF5, Boost and optionally Doxygen and FFTW to build the C/C++ code. Please see the ISMRMRD documentation for specific installation instructions for [Linux](https://ismrmrd.github.io/index.html#linux-installation), [Mac OS X](https://ismrmrd.github.io/index.html#mac-osx-installation), and [Windows](https://ismrmrd.github.io/index.html#windows-installation).
+You will need CMake, HDF5, and optionally Boost and FFTW to build the C/C++ code. To generate the API documentation you will need Doxygen. Please see the ISMRMRD documentation for specific installation instructions for [Linux](https://ismrmrd.github.io/index.html#linux-installation), [Mac OS X](https://ismrmrd.github.io/index.html#mac-osx-installation), and [Windows](https://ismrmrd.github.io/index.html#windows-installation).
Overview
---------
@@ -26,3 +28,8 @@ A raw data set consist mainly of 2 sections:
1. Raw data section. This section contains all the acquired data in the experiment. Each data item is preceded by a C-struct with encoding numbers, etc. Following this data header is a channel header and data for each acquired channel. The raw data headers are defined in a C/C++ header file (ismrmrd.h). Please see the [C header](https://github.com/ismrmrd/ismrmrd/blob/master/include/ismrmrd/ismrmrd.h) and the [documentation](https://ismrmrd.github.io/index.html#fixed-data-structures) f [...]
In addition to these sections, the ISMRMRD format also specifies an image header for storing reconstructed images and the accompanying C/C++ library provides a convenient way of writing such images into HDF5 files along with generic arrays for storing less well defined data structures, e.g. coil sensitivity maps or other calibration data.
+
+Other Resources
+---------------
+
+- [Python implementation](https://www.github.com/ismrmrd/ismrmrd-python)
diff --git a/cmake/FindJava.cmake b/cmake/FindJava.cmake
deleted file mode 100644
index 4d6f888..0000000
--- a/cmake/FindJava.cmake
+++ /dev/null
@@ -1,212 +0,0 @@
-# - 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
deleted file mode 100644
index 6feeb73..0000000
--- a/cmake/FindNumPy.cmake
+++ /dev/null
@@ -1,101 +0,0 @@
-# - 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/cpack_options.cmake.in b/cmake/cpack_options.cmake.in
index cd82556..6a8f5ef 100644
--- a/cmake/cpack_options.cmake.in
+++ b/cmake/cpack_options.cmake.in
@@ -8,7 +8,7 @@ set(CPACK_PACKAGE_VERSION_MAJOR "@ISMRMRD_VERSION_MAJOR@")
set(CPACK_PACKAGE_VERSION_MINOR "@ISMRMRD_VERSION_MINOR@")
set(CPACK_PACKAGE_VERSION_PATCH "@ISMRMRD_VERSION_PATCH@")
set(CPACK_PACKAGE_NAME "@PROJECT_NAME@")
-set(CPACK_PACKAGE_VENDOR "https://sourceforge.net/p/ismrmrd")
+set(CPACK_PACKAGE_VENDOR "http://ismrmrd.github.io/")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ISMRM Raw Data Format (ISMRMRD)")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "@PROJECT_NAME_LOWER@")
set(CPACK_RESOURCE_FILE_LICENSE "@CMAKE_SOURCE_DIR@/LICENSE")
@@ -18,19 +18,13 @@ set(CPACK_PACKAGE_MAINTAINER "Michael S. Hansen <michael.hansen at nih.gov>")
set(CPACK_PACKAGE_CONTACT "Michael S. Hansen <michael.hansen at nih.gov>")
# DEB specific
-set(CPACK_DEBIAN_PACKAGE_DEPENDS "@DEBIAN_PACKAGE_DEPENDS@")
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
-set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Implementation of the ISMRMRD format.")
-# RPM specific
-# TODO: set(CPACK_RPM_PACKAGE_REQUIRES "@RPM_PACKAGE_DEPENDS@")
-# TODO: set(CPACK_RPM_PACKAGE_DESCRIPTION "Implementation of the ISMRMRD format.")
-
# NSIS specific
-set(CPACK_NSIS_HELP_LINK "http:\\\\\\\\ismrmrd.sourceforge.net")
-set(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\ismrmrd.sourceforge.net")
+set(CPACK_NSIS_HELP_LINK "http://ismrmrd.github.io")
+set(CPACK_NSIS_URL_INFO_ABOUT "http://ismrmrd.github.io")
set(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_NSIS_DISPLAY_NAME "ismrmrd")
diff --git a/cmake/ismrmrd_cpack.cmake b/cmake/ismrmrd_cpack.cmake
index eee956c..94ad624 100644
--- a/cmake/ismrmrd_cpack.cmake
+++ b/cmake/ismrmrd_cpack.cmake
@@ -8,31 +8,33 @@ if(UNIX)
if(EXISTS ${DPKG_PROGRAM})
list(APPEND CPACK_GENERATOR "DEB")
endif(EXISTS ${DPKG_PROGRAM})
- # TODO: RPM
- #find_program(RPMBUILD_PROGRAM rpmbuild)
- #if(EXISTS ${RPMBUILD_PROGRAM})
- # list(APPEND CPACK_GENERATOR "RPM")
- #endif(EXISTS ${RPMBUILD_PROGRAM})
endif(UNIX)
-if(WIN32)
- # NSLS
- list(APPEND CPACK_GENERATOR "NSIS")
-endif(WIN32)
+# Enable/Disable automatic search for dependencies:
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
-# TODO: list(APPEND CPACK_SOURCE_GENERATOR "TGZ")
-# TODO: list(APPEND CPACK_SOURCE_GENERATOR "ZIP")
-list(APPEND CPACK_SOURCE_IGNORE_FILES ";.git;.gitignore;todo.txt;_clang-format;build/")
+# Enable/Disable component install for CPack generator DEB
+set(CPACK_DEB_COMPONENT_INSTALL OFF)
+set(CPACK_DEB_PACKAGE_COMPONENT OFF)
-# set dependencies explicitly
-include(InstallRequiredSystemLibraries)
-set(DEBIAN_PACKAGE_DEPENDS "libhdf5-7, libfftw3-3, libboost-program-options-dev")
-# TODO: set(RPM_PACKAGE_DEPENDS "hdf5-devel")
+# Set dependencies explicitly
+set(CPACK_DEBIAN_PACKAGE_DEPENDS "libhdf5-7, libfftw3-3, libboost-program-options-dev")
-# where the package metadata are
+# Where the package metadata are
set(ISMRMRD_CPACK_CFG_FILE "${PROJECT_BINARY_DIR}/cpack_options.cmake")
-# Where the package to be installed
-#set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CMAKE_INSTALL_PREFIX})
+# Where the package to be installed
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
message("CPACK_PACKAGING_INSTALL_PREFIX: " ${CPACK_PACKAGING_INSTALL_PREFIX})
+
+if(WIN32)
+ # NSLS
+ list(APPEND CPACK_GENERATOR "NSIS")
+endif(WIN32)
+
+list(APPEND CPACK_SOURCE_GENERATOR "TGZ")
+list(APPEND CPACK_SOURCE_GENERATOR "ZIP")
+list(APPEND CPACK_SOURCE_IGNORE_FILES ";.git;.gitignore;todo.txt;_clang-format;build/")
+
+# set dependencies explicitly
+include(InstallRequiredSystemLibraries)
diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt
index 3ab0884..8988f17 100644
--- a/examples/c/CMakeLists.txt
+++ b/examples/c/CMakeLists.txt
@@ -1,5 +1,23 @@
-include_directories(${CMAKE_SOURCE_DIR}/include)
+cmake_minimum_required(VERSION 2.8)
+project(ISMRMRD-C-EXAMPLE)
-add_executable(ismrmrd_c_demo main.c)
-target_link_libraries(ismrmrd_c_demo ismrmrd)
-install(TARGETS ismrmrd_c_demo DESTINATION bin)
+# if building this example as a standalone project
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ if(NOT DEFINED ENV{ISMRMRD_HOME})
+ message(FATAL_ERROR "ISMRMRD_HOME environment variable must be defined")
+ endif(NOT DEFINED ENV{ISMRMRD_HOME})
+
+ list(APPEND CMAKE_MODULE_PATH "$ENV{ISMRMRD_HOME}/share/ismrmrd/cmake")
+
+ find_package(Ismrmrd REQUIRED)
+
+# otherwise, building it as part of ISMRMRD itself
+else(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(ISMRMRD_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include")
+ set(ISMRMRD_LIBRARIES ismrmrd)
+endif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+
+include_directories(${ISMRMRD_INCLUDE_DIR})
+add_executable(ismrmrd_c_example main.c)
+target_link_libraries(ismrmrd_c_example ${ISMRMRD_LIBRARIES})
+install(TARGETS ismrmrd_c_example DESTINATION bin)
diff --git a/examples/c/README.md b/examples/c/README.md
new file mode 100644
index 0000000..a20d781
--- /dev/null
+++ b/examples/c/README.md
@@ -0,0 +1,13 @@
+This is an example of a simple C project that is built on ISMRMRD.
+
+Instructions for building:
+
+1. Install ISMRMRD and CMake
+2. Define the environment variable ISMRMRD_HOME,
+ e.g. `export ISMRMRD_HOME=/usr/local/ismrmrd`
+3. Compile the example:
+
+ mkdir build
+ cmake ..
+ make
+ ./ismrmrd_c_example
diff --git a/examples/c/README.txt b/examples/c/README.txt
deleted file mode 100644
index e430630..0000000
--- a/examples/c/README.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is an example of a simple C project that is built on ISMRMRD.
-
-Instructions for building:
-1. Install ISMRMRD
-2. Define the environment variable ISMRMRD_HOME,
- e.g. ISMRMRD_HOME=/usr/local/ismrmrd
-3. In a directory of your choosing:
- mkdir buildcdemo
- cmake ${ISMRMRD_HOME}/examples/c
- make
- ./ismrmrd_c_demo
\ No newline at end of file
diff --git a/examples/c/main.c b/examples/c/main.c
index 6bb5d07..a2f265e 100644
--- a/examples/c/main.c
+++ b/examples/c/main.c
@@ -45,12 +45,9 @@ int main(void)
ismrmrd_write_header(&dataset1, xmlhdr);
/* Append some acquisitions */
- /* must initialize an acquisition before you can use it */
- ismrmrd_init_acquisition(&acq);
nacq_write = 5;
for (n=0; n < nacq_write; n++) {
- /* must free an acquisition before you can reinitialize it */
- ismrmrd_init_acquisition(&acq);
+ /* must initialize an acquisition before you can use it */
ismrmrd_init_acquisition(&acq);
acq.head.number_of_samples = 128;
acq.head.active_channels = 4;
@@ -76,6 +73,7 @@ int main(void)
ismrmrd_set_flag(&(acq.head.flags), ISMRMRD_ACQ_LAST_IN_SLICE);
}
ismrmrd_append_acquisition(&dataset1, &acq);
+ ismrmrd_cleanup_acquisition(&acq);
}
/* Close the dataset */
@@ -91,6 +89,7 @@ int main(void)
/* Read the header */
xmlstring = ismrmrd_read_header(&dataset2);
printf("Header: %s\n", xmlstring);
+ free(xmlstring);
/* Get the number of acquisitions */
nacq_read = ismrmrd_get_number_of_acquisitions(&dataset2);
@@ -131,6 +130,8 @@ int main(void)
#else
printf("Data 3: %f\t 2: %f\n", creal(acq3.data[4]), creal(acq2.data[4]));
#endif
+ ismrmrd_cleanup_acquisition(&acq2);
+ ismrmrd_cleanup_acquisition(&acq3);
/* Create and store an image */
ismrmrd_init_image(&im);
@@ -152,6 +153,7 @@ int main(void)
((float*)im.data)[loc] = 2.0;
}
ismrmrd_append_image(&dataset2, "testimages", &im);
+ ismrmrd_cleanup_image(&im);
numim = ismrmrd_get_number_of_images(&dataset2, "testimages");
printf("Number of images stored = %d\n", numim);
@@ -160,6 +162,7 @@ int main(void)
ismrmrd_read_image(&dataset2, "testimages", 1, &im2);
printf("Image 1 attribute string = %s\n", im2.attribute_string);
printf("Image 1 at position 10 has value = %f\n", ((float*)im2.data)[10]);
+ ismrmrd_cleanup_image(&im2);
/* Create and store an array */
ismrmrd_init_ndarray(&arr);
@@ -174,19 +177,14 @@ int main(void)
}
ismrmrd_append_array(&dataset2, "testarray", &arr);
printf("Number of arrays stored = %d\n", ismrmrd_get_number_of_arrays(&dataset2, "testarray"));
+ ismrmrd_cleanup_ndarray(&arr);
/* Read it back in */
ismrmrd_init_ndarray(&arr2);
ismrmrd_read_array(&dataset2, "testarray", 0, &arr2);
printf("Array 2 at position 10 has value = %f\n", ((float*)arr2.data)[10]);
+ ismrmrd_cleanup_ndarray(&arr2);
- /* Clean up */
- /* This frees the internal memory of the acquisitions */
- ismrmrd_cleanup_acquisition(&acq);
- ismrmrd_cleanup_acquisition(&acq2);
- ismrmrd_cleanup_acquisition(&acq3);
- free(xmlstring);
-
/* Close the dataset */
ismrmrd_close_dataset(&dataset2);
diff --git a/examples/data/.gitignore b/examples/data/.gitignore
deleted file mode 100644
index 424e4bc..0000000
--- a/examples/data/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.h5
\ No newline at end of file
diff --git a/examples/data/README.txt b/examples/data/README.txt
deleted file mode 100644
index 92962b7..0000000
--- a/examples/data/README.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-ISMRM Raw Data Example files
------------------------------
-
-
-
-Please download the example data files from:
-
-https://sourceforge.net/projects/ismrmrd/files/data/
-
-On Linux command line, simply type:
-
-wget https://sourceforge.net/projects/ismrmrd/files/data/3D_partial_fourier.h5
-wget https://sourceforge.net/projects/ismrmrd/files/data/simple_gre.h5
-wget https://sourceforge.net/projects/ismrmrd/files/data/simple_spiral.h5
-
-
-
diff --git a/examples/matlab/todo.txt b/examples/matlab/todo.txt
deleted file mode 100644
index 50b1078..0000000
--- a/examples/matlab/todo.txt
+++ /dev/null
@@ -1 +0,0 @@
-Put Michaels spiral and gridder example back.
diff --git a/examples/python/ismrmrd_create_dataset.py b/examples/python/ismrmrd_create_dataset.py
deleted file mode 100644
index 0ac2939..0000000
--- a/examples/python/ismrmrd_create_dataset.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# coding: utf-8
-import os
-import ismrmrd
-import numpy as np
-import matplotlib.pyplot as plt
-
-
-filename = 'testdata.h5'
-if os.path.isfile(filename):
- os.remove(filename)
-# Create an empty ISMRMRD dataset
-dset = ismrmrd.Dataset(filename, "dataset")
-
-# Synthesize the object
-nX, nY = 256, 256
-rho = np.zeros((nX, nY))
-x0, x1 = nX / 4, 3 * nX / 4
-y0, y1 = nY / 4, 3 * nY / 4
-rho[x0:x1, y0:y1] = 1
-
-plt.imshow(rho)
-
-# Synthesize some coil sensitivities
-X, Y = np.meshgrid(np.arange(nX) / nX / 2.0, np.arange(nY) / nY / 2.0)
-C = np.zeros((nX, nY, 4), dtype=np.complex64)
-C[:,:,0] = np.exp(-((X - 0.5) ** 2 + Y ** 2) + 1j * (X - 0.5))
-C[:,:,1] = np.exp(-((X + 0.5) ** 2 + Y ** 2) - 1j * (X + 0.5))
-C[:,:,2] = np.exp(-(X ** 2 + (Y - 0.5) ** 2) + 1j * (Y - 0.5))
-C[:,:,3] = np.exp(-(X ** 2 + (Y + 0.5) ** 2) - 1j * (Y + 0.5))
-ncoils = np.size(C, 2)
-
-# Synthesize the k-space data
-nreps = 5
-noiselevel = 0.05
-K = np.zeros((nX, nY, ncoils, nreps), dtype=np.complex64)
-for rep in range(nreps):
- for coil in range(ncoils):
- noise = noiselevel * (np.random.randn(nX, nY) + 1j * np.random.randn(nX, nY))
- K[:,:,coil,rep] = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(C[:,:,coil] * rho + noise)))
-
-rep0 = np.sqrt(np.sum(np.abs(K) ** 2, 2))
-plt.imshow(rep0[:,:,0])
-
-
-for rep in range(nreps):
- for line in range(nY):
- # Generate header
- head = ismrmrd.AcquisitionHeader()
- counter = ismrmrd.EncodingCounters()
- head.version = 1
- head.number_of_samples = nX
- head.center_sample = nX / 2
- head.active_channels = ncoils
- head.read_dir = [1., 0., 0.]
- head.phase_dir = [0., 1., 0.]
- head.slice_dir = [0., 0., 1.]
- head.scan_counter = rep * nY + line
- counter.kspace_encode_step_1 = line
- counter.repetition = rep
- head.idx = counter
- # Note: the correct API for setting Acquisition flags looks like this:
- # acq.setFlag(ismrmrd.FlagBit(ismrmrd.ACQ_FIRST_IN_ENCODE_STEP1))
- # but using this API would require using only ugly "acq.setXXX" methods
- # since the call to "acq.setHead()" below overwrites the Acquisition's header
- head.flags = 0
- if line == 0:
- head.flags |= 1 << ismrmrd.ACQ_LAST_IN_ENCODE_STEP1
- head.flags |= 1 << ismrmrd.ACQ_FIRST_IN_SLICE
- head.flags |= 1 << ismrmrd.ACQ_FIRST_IN_REPETITION
- elif line == nY - 1:
- head.flags |= 1 << ismrmrd.ACQ_LAST_IN_ENCODE_STEP1
- head.flags |= 1 << ismrmrd.ACQ_LAST_IN_SLICE
- head.flags |= 1 << ismrmrd.ACQ_LAST_IN_REPETITION
-
- # Generate k-space data
- data = (np.array([c.real for c in np.array(K[:,line,:,rep])]) +
- 1j * np.array([c.imag for c in np.array(K[:,line,:,rep])]))
-
- # Construct acquisition object from header
- acq = ismrmrd.Acquisition(head=head)
-
- # Fill in the internal data array
- acq.data = data
-
- # Append to HDF5 dataset
- dset.append_acquisition(acq)
-
-# Fill the XML header
-try:
- import ismrmrd_xsd
- HAS_XSD = True
-except ImportError:
- HAS_XSD = False
-
-if HAS_XSD:
- header = ismrmrd_xsd.ismrmrdHeader()
-
- # Experimental Conditions
- exp = ismrmrd_xsd.experimentalConditionsType()
- exp.H1resonanceFrequency_Hz = 128000000
- header.experimentalConditions = exp
-
- # Acquisition System Information
- sys = ismrmrd_xsd.acquisitionSystemInformationType()
- sys.receiverChannels = ncoils
- header.acquisitionSystemInformation = sys
-
- # Encoding
- encoding = ismrmrd_xsd.encoding()
- encoding.trajectory = ismrmrd_xsd.trajectoryType.cartesian
-
- # Encoded Space
- fov = ismrmrd_xsd.fieldOfView_mm()
- fov.x = 256
- fov.y = 256
- fov.z = 5
-
- matrix = ismrmrd_xsd.matrixSize()
- matrix.x = np.size(K, 0)
- matrix.y = np.size(K, 1)
- matrix.z = 1
-
- space = ismrmrd_xsd.encodingSpaceType()
- space.matrixSize = matrix
- space.fieldOfView_mm = fov
-
- # Set encoded and recon space (same)
- encoding.encodedSpace = space
- encoding.reconSpace = space
-
- # Encoding limits
- limits = ismrmrd_xsd.encodingLimitsType()
-
- limits0 = ismrmrd_xsd.limitType()
- limits0.minimum = 0
- limits0.center = np.size(K, 0) / 2
- limits0.maximum = np.size(K, 0) - 1
- limits.kspaceEncodingStep0 = limits0
-
- limits1 = ismrmrd_xsd.limitType()
- limits1.minimum = 0
- limits1.center = np.size(K, 1) / 2
- limits1.maximum = np.size(K, 1) - 1
- limits.kspaceEncodingStep1 = limits1
-
- limits_rep = ismrmrd_xsd.limitType()
- limits_rep.minimum = 0
- limits_rep.center = nreps / 2
- limits_rep.maximum = nreps - 1
- limits.repetition = limits_rep
-
- limits_slice = ismrmrd_xsd.limitType()
- limits_slice.minimum = 0
- limits_slice.center = 0
- limits_slice.maximum = 0
- limits.slice = limits_slice
-
- limits_rest = ismrmrd_xsd.limitType()
- limits_rest.minimum = 0
- limits_rest.center = 0
- limits_rest.maximum = 0
- limits.average = limits_rest
- limits.contrast = limits_rest
- limits.kspaceEncodingStep2 = limits_rest
- limits.phase = limits_rest
- limits.segment = limits_rest
- limits.set = limits_rest
-
- encoding.encodingLimits = limits
- header.encoding.append(encoding)
-
- dset.write_header(header.toxml('utf-8'))
-
-dset.close()
diff --git a/examples/python/ismrmrd_recon_dataset.py b/examples/python/ismrmrd_recon_dataset.py
deleted file mode 100644
index a0ccd49..0000000
--- a/examples/python/ismrmrd_recon_dataset.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# coding: utf-8
-
-import os
-import ismrmrd
-import ismrmrd_xsd
-import numpy as np
-from numpy.fft import ifft, fftshift
-import matplotlib.pyplot as plt
-
-# Load file
-filename = 'testdata.h5'
-if not os.path.isfile(filename):
- print("%s is not a valid file" % filename)
- raise SystemExit
-dset = ismrmrd.Dataset(filename, 'dataset', create_if_needed=False)
-
-header = ismrmrd_xsd.CreateFromDocument(dset.read_header())
-enc = header.encoding[0]
-
-# Matrix size
-eNx = enc.encodedSpace.matrixSize.x
-eNy = enc.encodedSpace.matrixSize.y
-eNz = enc.encodedSpace.matrixSize.z
-rNx = enc.reconSpace.matrixSize.x
-rNy = enc.reconSpace.matrixSize.y
-rNz = enc.reconSpace.matrixSize.z
-
-# Field of View
-eFOVx = enc.encodedSpace.fieldOfView_mm.x
-eFOVy = enc.encodedSpace.fieldOfView_mm.y
-eFOVz = enc.encodedSpace.fieldOfView_mm.z
-rFOVx = enc.reconSpace.fieldOfView_mm.x
-rFOVy = enc.reconSpace.fieldOfView_mm.y
-rFOVz = enc.reconSpace.fieldOfView_mm.z
-
-# Number of Slices, Reps, Contrasts, etc.
-ncoils = header.acquisitionSystemInformation.receiverChannels
-if enc.encodingLimits.slice != None:
- nslices = enc.encodingLimits.slice.maximum + 1
-else:
- nslices = 1
-
-if enc.encodingLimits.repetition != None:
- nreps = enc.encodingLimits.repetition.maximum + 1
-else:
- nreps = 1
-
-if enc.encodingLimits.contrast != None:
- ncontrasts = enc.encodingLimits.contrast.maximum + 1
-else:
- ncontrasts = 1
-
-
-all_data = np.zeros((nreps, ncontrasts, nslices, ncoils, eNz, eNy, eNx), dtype=np.complex64)
-for acqnum in range(dset.number_of_acquisitions):
- acq = dset.read_acquisition(acqnum)
-
- # TODO: Currently ignoring noise scans
- if acq.head.flags & ismrmrd.ACQ_IS_NOISE_MEASUREMENT:
- continue
-
- rep = acq.head.idx.repetition
- contrast = acq.head.idx.contrast
- slice = acq.head.idx.slice
- y = acq.head.idx.kspace_encode_step_1
- z = acq.head.idx.kspace_encode_step_2
- all_data[rep, contrast, slice, :, z, y, :] = acq.data
-
-#fig = plt.figure()
-#h, w = nreps * ncontrasts, eNz * nslices
-#i = 0
-#for rep in range(nreps):
-# for contrast in range(ncontrasts):
-# for slice in range(nslices):
-# for z in range(eNz):
-# K = all_data[rep,contrast,slice,:,z,:,:]
-# comb = np.sqrt(np.squeeze(np.sum(np.abs(K) ** 2, 2)))
-# a = fig.add_subplot(h, w, i)
-# plt.imshow(comb)
-# i += 1
-#fig.set_size_inches(16, 16)
-
-images = []
-for rep in range(nreps):
- for contrast in range(ncontrasts):
- for slice in range(nslices):
- K = all_data[rep,contrast,slice,:,:,:,:]
- K = fftshift(ifft(fftshift(K, axes=3), axis=3), axes=3)
-
- # chop if needed
- if eNx != rNx:
- i0 = (eNx - rNx) / 2
- i1 = (eNx - rNx) / 2 + rNx
- im = K[:,:,:,i0:i1]
- else:
- im = K
-
- im = fftshift(ifft(fftshift(im, axes=2), axis=2), axes=2)
- if np.size(im, 1) > 1:
- im = fftshift(ifft(fftshift(im, axes=1), axis=1), axes=1)
-
- im = np.squeeze(np.sqrt(np.sum(np.abs(im) ** 2, 0)))
- images.append(im)
-
-l = len(images)
-fig = plt.figure()
-for n, im in enumerate(images):
- a = fig.add_subplot(1, 5, n)
- plt.imshow(im)
-fig.set_size_inches(16, 4)
-
-## # grab the first acquisition for extra info
-## acqh = dset.read_acquisition(0).head
-
-## for n, img in enumerate(images):
-## hdr = ismrmrd.ImageHeader()
-## hdr.acquisition_time_stamp = acqh.acquisition_time_stamp
-## hdr.flags = 0
-## hdr.measurement_uid = acqh.measurement_uid
-## hdr.phase_dir = acqh.phase_dir
-## hdr.physiology_time_stamp = acqh.physiology_time_stamp
-## hdr.position = acqh.position
-## hdr.read_dir = acqh.read_dir
-## hdr.slice_dir = acqh.slice_dir
-## hdr.channels = 1
-## hdr.image_data_type = ismrmrd.DATA_FLOAT
-## hdr.image_type = ismrmrd.TYPE_MAGNITUDE
-## hdr.image_index = n
-## hdr.slice = n
-
-## dset.appendImageHeader(hdr, "image_%d.hdr" % n)
-## dset.appendArray(img, "image_%d.img" % n)
diff --git a/include/ismrmrd/ismrmrd.h b/include/ismrmrd/ismrmrd.h
index 24bfeab..a4539b0 100644
--- a/include/ismrmrd/ismrmrd.h
+++ b/include/ismrmrd/ismrmrd.h
@@ -755,8 +755,10 @@ public:
void setHead(const ImageHeader& head);
// Attribute string
- void getAttributeString(std::string &atrr) const;
+ void getAttributeString(std::string &attr) const;
+ const char *getAttributeString() const;
void setAttributeString(const std::string &attr);
+ void setAttributeString(const char *attr);
size_t getAttributeStringLength() const;
// Data
diff --git a/include/ismrmrd/xml.h b/include/ismrmrd/xml.h
index 5695532..1e4b782 100644
--- a/include/ismrmrd/xml.h
+++ b/include/ismrmrd/xml.h
@@ -302,10 +302,12 @@ namespace ISMRMRD
struct SequenceParameters
{
- std::vector<float> TR;
- std::vector<float> TE;
- std::vector<float> TI;
- std::vector<float> flipAngle_deg;
+ Optional<std::vector<float> > TR;
+ Optional<std::vector<float> > TE;
+ Optional<std::vector<float> > TI;
+ Optional<std::vector<float> > flipAngle_deg;
+ Optional<std::string> sequence_type;
+ Optional<std::vector<float> > echo_spacing;
};
struct IsmrmrdHeader
diff --git a/include/version.in b/include/version.in
index 5239d4f..43378ae 100644
--- a/include/version.in
+++ b/include/version.in
@@ -6,5 +6,6 @@
#define ISMRMRD_VERSION_PATCH @ISMRMRD_VERSION_PATCH@
#define ISMRMRD_XMLHDR_VERSION @ISMRMRD_VERSION_MINOR@
#define ISMRMRD_GIT_SHA1_HASH "@ISMRMRD_GIT_SHA1@"
+#define ISMRMRD_DATASET_SUPPORT @ISMRMRD_DATASET_SUPPORT@
#endif /* ISMRMRD_VERSION_H */
diff --git a/libsrc/dataset.c b/libsrc/dataset.c
index b1ee935..1379e4d 100644
--- a/libsrc/dataset.c
+++ b/libsrc/dataset.c
@@ -419,6 +419,7 @@ static hid_t get_hdf5type_image_attribute_string(void) {
hid_t datatype = H5Tcopy(H5T_C_S1);
herr_t h5status = H5Tset_size(datatype, H5T_VARIABLE);
if (h5status < 0) {
+ H5Ewalk2(H5E_DEFAULT, H5E_WALK_UPWARD, walk_hdf5_errors, NULL);
ISMRMRD_PUSH_ERR(ISMRMRD_FILEERROR, "Failed get image attribute string data type");
}
return datatype;
@@ -738,6 +739,8 @@ static int get_array_properties(const ISMRMRD_Dataset *dset, const char *path,
dims[n] = hdfdims[rank-n-1];
}
+ free(hdfdims);
+
/* clean up */
h5status = H5Tclose(hdf5type);
if (h5status < 0) {
@@ -858,7 +861,7 @@ int ismrmrd_init_dataset(ISMRMRD_Dataset *dset, const char *filename,
dset->filename = (char *) malloc(strlen(filename) + 1);
if (dset->filename == NULL) {
- return ISMRMRD_PUSH_ERR(ISMRMRD_MEMORYERROR, "Failed to malloc dataset groupname");
+ return ISMRMRD_PUSH_ERR(ISMRMRD_MEMORYERROR, "Failed to malloc dataset filename");
}
strcpy(dset->filename, filename);
@@ -889,9 +892,16 @@ int ismrmrd_open_dataset(ISMRMRD_Dataset *dset, const bool create_if_needed) {
dset->fileid = fileid;
}
else if (create_if_needed == false) {
- H5Ewalk2(H5E_DEFAULT, H5E_WALK_UPWARD, walk_hdf5_errors, NULL);
- /* Some sort of error opening the file - Maybe it doesn't exist? */
- return ISMRMRD_PUSH_ERR(ISMRMRD_FILEERROR, "Failed to open file.");
+ /*Try opening the file as read-only*/
+ fileid = H5Fopen(dset->filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ if (fileid > 0) {
+ dset->fileid = fileid;
+ }
+ else{
+ H5Ewalk2(H5E_DEFAULT, H5E_WALK_UPWARD, walk_hdf5_errors, NULL);
+ /* Some sort of error opening the file - Maybe it doesn't exist? */
+ return ISMRMRD_PUSH_ERR(ISMRMRD_FILEERROR, "Failed to open file.");
+ }
}
else {
/* Try creating a new file using the default properties. */
@@ -1027,26 +1037,16 @@ char * ismrmrd_read_header(const ISMRMRD_Dataset *dset) {
goto cleanup_path;
}
- void *buff[1] = { NULL };
dataset = H5Dopen2(dset->fileid, path, H5P_DEFAULT);
datatype = get_hdf5type_xmlheader();
/* Read it into a 1D buffer*/
- h5status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buff);
- if (h5status < 0 || buff[0] == NULL) {
+ h5status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &xmlstring);
+ if (h5status < 0 || xmlstring == NULL) {
H5Ewalk2(H5E_DEFAULT, H5E_WALK_UPWARD, walk_hdf5_errors, NULL);
ISMRMRD_PUSH_ERR(ISMRMRD_FILEERROR, "Failed to read header.");
goto cleanup_path;
}
- /* Unpack */
- xmlstring = (char *) malloc(strlen(buff[0])+1);
- if (NULL == xmlstring) {
- ISMRMRD_PUSH_ERR(ISMRMRD_MEMORYERROR, "Failed to malloc xmlstring");
- goto cleanup_path;
- } else {
- memcpy(xmlstring, buff[0], strlen(buff[0])+1);
- }
-
/* Clean up */
h5status = H5Tclose(datatype);
if (h5status < 0) {
@@ -1157,6 +1157,7 @@ int ismrmrd_read_acquisition(const ISMRMRD_Dataset *dset, uint32_t index, ISMRMR
memcpy(acq->data, hdf5acq.data.p, ismrmrd_size_of_acquisition_data(acq));
/* clean up */
+ free(path);
free(hdf5acq.traj.p);
free(hdf5acq.data.p);
@@ -1266,7 +1267,7 @@ int ismrmrd_read_image(const ISMRMRD_Dataset *dset, const char *varname,
int status;
hid_t datatype;
- char *path, *headerpath, *attrpath, *datapath;
+ char *path, *headerpath, *attrpath, *datapath, *attr_string;
uint32_t numims;
if (dset==NULL) {
@@ -1305,13 +1306,17 @@ int ismrmrd_read_image(const ISMRMRD_Dataset *dset, const char *varname,
/* Handle the attribute string */
attrpath = append_to_path(dset, path, "attributes");
datatype = get_hdf5type_image_attribute_string();
- status = read_element(dset, attrpath, (void *) &im->attribute_string, datatype, index);
+ status = read_element(dset, attrpath, (void *) &attr_string, datatype, index);
if (status != ISMRMRD_NOERROR) {
return ISMRMRD_PUSH_ERR(ISMRMRD_FILEERROR, "Failed to read image attribute string.");
}
free(attrpath);
H5Tclose(datatype);
+ /* copy the attribute string read from the file into the Image */
+ memcpy(im->attribute_string, attr_string, ismrmrd_size_of_image_attribute_string(im));
+ free(attr_string);
+
/* Handle the data */
datapath = append_to_path(dset, path, "data");
datatype = get_hdf5type_ndarray(im->head.data_type);
diff --git a/libsrc/dataset.cpp b/libsrc/dataset.cpp
index e679f99..a87bdfc 100644
--- a/libsrc/dataset.cpp
+++ b/libsrc/dataset.cpp
@@ -111,6 +111,16 @@ template <typename T> void Dataset::readImage(const std::string &var, uint32_t i
}
}
+// Specific instantiations
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<uint16_t> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<int16_t> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<uint32_t> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<int32_t> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<float> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<double> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<complex_float_t> &im);
+template EXPORTISMRMRD void Dataset::readImage(const std::string &var, uint32_t index, Image<complex_double_t> &im);
+
uint32_t Dataset::getNumberOfImages(const std::string &var)
{
uint32_t num = ismrmrd_get_number_of_images(&dset_, var.c_str());
@@ -152,6 +162,16 @@ template <typename T> void Dataset::readNDArray(const std::string &var, uint32_t
}
}
+// Specific instantiations
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<uint16_t> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<int16_t> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<uint32_t> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<int32_t> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<float> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<double> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<complex_float_t> &arr);
+template EXPORTISMRMRD void Dataset::readNDArray(const std::string &var, uint32_t index, NDArray<complex_double_t> &arr);
+
uint32_t Dataset::getNumberOfNDArrays(const std::string &var)
{
uint32_t num = ismrmrd_get_number_of_arrays(&dset_, var.c_str());
diff --git a/libsrc/ismrmrd.c b/libsrc/ismrmrd.c
index 3d687d4..3fba17c 100644
--- a/libsrc/ismrmrd.c
+++ b/libsrc/ismrmrd.c
@@ -268,10 +268,13 @@ int ismrmrd_make_consistent_image(ISMRMRD_Image *im) {
attr_size = ismrmrd_size_of_image_attribute_string(im);
if (attr_size > 0) {
- im->attribute_string = (char *)realloc(im->attribute_string, attr_size);
+ // Allocate space plus a null-terminating character
+ im->attribute_string = (char *)realloc(im->attribute_string, attr_size + sizeof(*im->attribute_string));
if (im->attribute_string == NULL) {
return ISMRMRD_PUSH_ERR(ISMRMRD_MEMORYERROR, "Failed to realloc image attribute string");
}
+ // Set the null terminating character
+ im->attribute_string[im->head.attribute_string_len] = '\0';
}
data_size = ismrmrd_size_of_image_data(im);
@@ -528,8 +531,8 @@ int ismrmrd_set_channel_on(uint64_t channel_mask[ISMRMRD_CHANNEL_MASKS], const u
if (channel_mask==NULL) {
return ISMRMRD_PUSH_ERR(ISMRMRD_RUNTIMEERROR, "Pointer to channel_mask should not be NULL.");
}
- bitmask = 1 << (chan % ISMRMRD_CHANNEL_MASKS);
- offset = chan / ISMRMRD_CHANNEL_MASKS;
+ bitmask = 1 << (chan % 64);
+ offset = chan / 64;
channel_mask[offset] |= bitmask;
return ISMRMRD_NOERROR;
}
diff --git a/libsrc/ismrmrd.cpp b/libsrc/ismrmrd.cpp
index baa6dd1..d33c1b1 100644
--- a/libsrc/ismrmrd.cpp
+++ b/libsrc/ismrmrd.cpp
@@ -931,19 +931,34 @@ template <typename T> void Image<T>::getAttributeString(std::string &attr) const
attr.assign("");
}
+template <typename T> const char *Image<T>::getAttributeString() const
+{
+ return im.attribute_string;
+}
+
template <typename T> void Image<T>::setAttributeString(const std::string &attr)
{
- size_t length = attr.length();
- im.head.attribute_string_len = static_cast<uint32_t>(length);
+ this->setAttributeString(attr.c_str());
+}
- // Add null terminating character
- length++;
+template <typename T> void Image<T>::setAttributeString(const char *attr)
+{
+ // Get the string length
+ size_t length = strlen(attr);
- im.attribute_string = (char *)realloc(im.attribute_string, length);
- if (NULL==im.attribute_string) {
+ // Allocate space plus a null terminator and check for success
+ char *newPointer = (char *)realloc(im.attribute_string, (length+1) * sizeof(*im.attribute_string));
+ if (NULL==newPointer) {
throw std::runtime_error(build_exception_string());
}
- strncpy(im.attribute_string, attr.c_str(), length);
+
+ // Make changes only if reallocation was successful
+ im.attribute_string = newPointer;
+ im.head.attribute_string_len = static_cast<uint32_t>(length);
+
+ // Set the null terminator and copy the string
+ im.attribute_string[length] = '\0';
+ strncpy(im.attribute_string, attr, length);
}
template <typename T> size_t Image<T>::getAttributeStringLength() const
diff --git a/libsrc/xml.cpp b/libsrc/xml.cpp
index 5e6a3d7..fde4e2b 100644
--- a/libsrc/xml.cpp
+++ b/libsrc/xml.cpp
@@ -222,7 +222,7 @@ namespace ISMRMRD
throw std::runtime_error("experimentalConditions not defined in ismrmrdHeader");
} else {
ExperimentalConditions e;
- e.H1resonanceFrequency_Hz = std::atoi(experimentalConditions.child_value("H1resonanceFrequency_Hz"));
+ e.H1resonanceFrequency_Hz = std::atol(experimentalConditions.child_value("H1resonanceFrequency_Hz"));
h.experimentalConditions = e;
}
@@ -396,10 +396,24 @@ namespace ISMRMRD
if (sequenceParameters) {
SequenceParameters p;
- p.TR = parse_vector_float(sequenceParameters,"TR");
- p.TE = parse_vector_float(sequenceParameters,"TE");
- p.TI = parse_vector_float(sequenceParameters,"TI");
- p.flipAngle_deg = parse_vector_float(sequenceParameters, "flipAngle_deg");
+
+ std::vector<float> r;
+ r = parse_vector_float(sequenceParameters, "TR");
+ if (!r.empty()) p.TR = r;
+
+ r = parse_vector_float(sequenceParameters, "TE");
+ if (!r.empty()) p.TE = r;
+
+ r = parse_vector_float(sequenceParameters, "TI");
+ if (!r.empty()) p.TI = r;
+
+ r = parse_vector_float(sequenceParameters, "flipAngle_deg");
+ if (!r.empty()) p.flipAngle_deg = r;
+
+ p.sequence_type = parse_optional_string(sequenceParameters, "sequence_type");
+
+ r = parse_vector_float(sequenceParameters, "echo_spacing");
+ if (!r.empty()) p.echo_spacing = r;
h.sequenceParameters = p;
}
@@ -655,24 +669,42 @@ namespace ISMRMRD
if (h.sequenceParameters) {
n1 = root.append_child("sequenceParameters");
- if (!h.sequenceParameters->TR.size()) {
- throw std::runtime_error("TR section of sequenceParameters does not contain any values");
- }
- if (!h.sequenceParameters->TE.size()) {
- throw std::runtime_error("TE section of sequenceParameters does not contain any values");
+
+ if (h.sequenceParameters->TR.is_present())
+ {
+ for (size_t i = 0; i < h.sequenceParameters->TR->size(); i++) {
+ append_node(n1, "TR", h.sequenceParameters->TR->operator[](i));
+ }
}
- for (size_t i = 0; i < h.sequenceParameters->TR.size(); i++) {
- append_node(n1,"TR",h.sequenceParameters->TR[i]);
+ if (h.sequenceParameters->TE.is_present())
+ {
+ for (size_t i = 0; i < h.sequenceParameters->TE->size(); i++) {
+ append_node(n1, "TE", h.sequenceParameters->TE->operator[](i));
+ }
}
- for (size_t i = 0; i < h.sequenceParameters->TE.size(); i++) {
- append_node(n1,"TE",h.sequenceParameters->TE[i]);
+
+ if (h.sequenceParameters->TI.is_present())
+ {
+ for (size_t i = 0; i < h.sequenceParameters->TI->size(); i++) {
+ append_node(n1, "TI", h.sequenceParameters->TI->operator[](i));
+ }
}
- for (size_t i = 0; i < h.sequenceParameters->TI.size(); i++) {
- append_node(n1,"TI",h.sequenceParameters->TI[i]);
+
+ if (h.sequenceParameters->flipAngle_deg.is_present())
+ {
+ for (size_t i = 0; i < h.sequenceParameters->flipAngle_deg->size(); i++) {
+ append_node(n1, "flipAngle_deg", h.sequenceParameters->flipAngle_deg->operator[](i));
+ }
}
- for (size_t i = 0; i < h.sequenceParameters->flipAngle_deg.size(); i++) {
- append_node(n1,"flipAngle_deg",h.sequenceParameters->flipAngle_deg[i]);
+
+ append_optional_node(n2, "sequence_type", h.sequenceParameters->sequence_type);
+
+ if (h.sequenceParameters->echo_spacing.is_present())
+ {
+ for (size_t i = 0; i < h.sequenceParameters->echo_spacing->size(); i++) {
+ append_node(n1, "echo_spacing", h.sequenceParameters->echo_spacing->operator[](i));
+ }
}
}
diff --git a/matlab/+ismrmrd/+xml/deserialize.m b/matlab/+ismrmrd/+xml/deserialize.m
index d0b5b96..7aabf82 100644
--- a/matlab/+ismrmrd/+xml/deserialize.m
+++ b/matlab/+ismrmrd/+xml/deserialize.m
@@ -202,6 +202,8 @@ function status = isNumericalType(name)
'TE', ...
'TI', ...
'flipAngle_deg', ...
+ 'sequence_type', ...
+ 'echo_spacing', ...
'x', 'y', 'z', ...
'minimum', 'maximum', 'center'};
@@ -233,7 +235,8 @@ function status = isStringType(name)
'trajectory', ...
'coilName', ...
'calibrationMode',...
- 'interleavingDimension'};
+ 'interleavingDimension',...
+ 'sequence_type'};
status = ismember(name, headerStringTypes);
end
diff --git a/matlab/+ismrmrd/+xml/serialize.m b/matlab/+ismrmrd/+xml/serialize.m
index 7eb5740..874752f 100644
--- a/matlab/+ismrmrd/+xml/serialize.m
+++ b/matlab/+ismrmrd/+xml/serialize.m
@@ -175,6 +175,8 @@ if isfield(header,'sequenceParameters')
append_optional(docNode,n1,sequenceParameters,'TE', at num2str);
append_optional(docNode,n1,sequenceParameters,'TI', at num2str);
append_optional(docNode,n1,sequenceParameters,'flipAngle_deg', at num2str);
+ append_optional(docNode,n1,sequenceParameters,'sequence_type');
+ append_optional(docNode,n1,sequenceParameters,'echo_spacing', at num2str);
docRootNode.appendChild(n1);
end
diff --git a/schema/ismrmrd.xsd b/schema/ismrmrd.xsd
index 9553980..02168e4 100644
--- a/schema/ismrmrd.xsd
+++ b/schema/ismrmrd.xsd
@@ -187,10 +187,12 @@
<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="TR"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" type="xs:float" name="TE"/>
<xs:element minOccurs="0" maxOccurs="unbounded" type="xs:float" name="TI"/>
<xs:element minOccurs="0" maxOccurs="unbounded" type="xs:float" name="flipAngle_deg"/>
+ <xs:element minOccurs="0" maxOccurs="1" type="xs:string" name="sequence_type"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" type="xs:float" name="echo_spacing"/>
</xs:sequence>
</xs:complexType>
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..5d8d2c0
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,21 @@
+find_package(Boost 1.43 COMPONENTS unit_test_framework)
+
+if (NOT Boost_UNIT_TEST_FRAMEWORK_FOUND)
+ message("Boost Unit Test Framework not found. Not compiling tests")
+ return()
+endif (NOT Boost_UNIT_TEST_FRAMEWORK_FOUND)
+
+include_directories(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include ${Boost_INCLUDE_DIR})
+
+add_executable(test_ismrmrd
+ test_main.cpp
+ test_acquisitions.cpp
+ test_images.cpp
+ test_ndarray.cpp
+ test_flags.cpp
+ test_channels.cpp
+ test_quaternions.cpp)
+
+target_link_libraries(test_ismrmrd ismrmrd ${Boost_LIBRARIES})
+
+add_custom_target(check COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_ismrmrd DEPENDS test_ismrmrd)
diff --git a/tests/test_acquisitions.cpp b/tests/test_acquisitions.cpp
new file mode 100644
index 0000000..7cc5532
--- /dev/null
+++ b/tests/test_acquisitions.cpp
@@ -0,0 +1,172 @@
+#include "ismrmrd/ismrmrd.h"
+#include "ismrmrd/version.h"
+#include <boost/test/unit_test.hpp>
+
+using namespace ISMRMRD;
+
+BOOST_AUTO_TEST_SUITE(AcquisitionsTest)
+
+static void check_header(ISMRMRD_AcquisitionHeader* chead);
+
+BOOST_AUTO_TEST_CASE(test_acquisition_header)
+{
+ ISMRMRD_AcquisitionHeader chead;
+
+ // Check that header is of expected size
+ size_t expected_size = 9 * sizeof(uint16_t) +
+ (3 + ISMRMRD_PHYS_STAMPS) * sizeof(uint32_t) +
+ ISMRMRD_USER_INTS * sizeof(int32_t) +
+ (1 + ISMRMRD_CHANNEL_MASKS) * sizeof(uint64_t) +
+ ((2 * ISMRMRD_POSITION_LENGTH) + (3 * ISMRMRD_DIRECTION_LENGTH) +
+ 1 + ISMRMRD_USER_FLOATS) * sizeof(float) +
+ (9 + ISMRMRD_USER_INTS) * sizeof(uint16_t);
+ BOOST_CHECK_EQUAL(sizeof(chead), expected_size);
+
+ // Check that header is initialized properly
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition_header(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition_header(&chead), ISMRMRD_NOERROR);
+ check_header(&chead);
+}
+
+BOOST_AUTO_TEST_CASE(test_acquisition_init_cleanup)
+{
+ ISMRMRD_Acquisition acq;
+
+ // Check initialization of acquisition
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition(&acq), ISMRMRD_NOERROR);
+ BOOST_CHECK(!acq.traj);
+ BOOST_CHECK(!acq.data);
+
+ // Check cleanup of acquisition
+ BOOST_CHECK_EQUAL(ismrmrd_cleanup_acquisition(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_cleanup_acquisition(&acq), ISMRMRD_NOERROR);
+ BOOST_CHECK(!acq.traj);
+ BOOST_CHECK(!acq.data);
+}
+
+BOOST_AUTO_TEST_CASE(test_acquisition_create_free)
+{
+ ISMRMRD_Acquisition* cacqp = NULL;
+
+ // Check creation of new acquisition
+ BOOST_CHECK(cacqp = ismrmrd_create_acquisition());
+ // Check that it's initialized
+ check_header(&cacqp->head);
+ BOOST_CHECK(!cacqp->traj);
+ BOOST_CHECK(!cacqp->data);
+
+ // Check cleanup
+ BOOST_CHECK_EQUAL(ismrmrd_free_acquisition(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_free_acquisition(cacqp), ISMRMRD_NOERROR);
+ BOOST_CHECK(!cacqp->traj);
+ BOOST_CHECK(!cacqp->data);
+}
+
+BOOST_AUTO_TEST_CASE(test_acquisition_copy)
+{
+ // Weak check of acquisition copying
+ ISMRMRD_Acquisition csrc, cdst;
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition(&csrc), ISMRMRD_NOERROR);
+ // TODO: it is necessary to call init_acquisition on the destination acquisition
+ // before copying, in case its traj or data are non-NULL!
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition(&cdst), ISMRMRD_NOERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_acquisition(&cdst, NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_acquisition(NULL, &csrc), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_acquisition(NULL, NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_acquisition(&cdst, &csrc), ISMRMRD_NOERROR);
+ check_header(&cdst.head);
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_acquisition_data(&cdst), 0);
+ BOOST_CHECK(!cdst.traj);
+ BOOST_CHECK(!cdst.data);
+}
+
+BOOST_AUTO_TEST_CASE(test_acquisition_make_consistent)
+{
+ ISMRMRD_Acquisition acq;
+ BOOST_CHECK_EQUAL(ismrmrd_init_acquisition(&acq), ISMRMRD_NOERROR);
+
+ BOOST_CHECK_EQUAL(ismrmrd_make_consistent_acquisition(NULL), ISMRMRD_RUNTIMEERROR);
+
+ uint16_t nsamples = 512;
+ uint16_t nchannels = 8;
+ uint16_t ntrajd = 2;
+ acq.head.number_of_samples = nsamples;
+ acq.head.active_channels = nchannels;
+ acq.head.trajectory_dimensions = ntrajd;
+
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_acquisition_traj(&acq), nsamples * ntrajd * sizeof(*acq.traj));
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_acquisition_data(&acq), nsamples * nchannels * sizeof(*acq.data));
+ BOOST_CHECK_EQUAL(ismrmrd_make_consistent_acquisition(&acq), ISMRMRD_NOERROR);
+
+ BOOST_CHECK_EQUAL(acq.head.available_channels, nchannels);
+ // check that traj and data were allocated
+ BOOST_CHECK(acq.traj);
+ BOOST_CHECK(acq.data);
+
+ ismrmrd_cleanup_acquisition(&acq);
+}
+
+static void check_header(ISMRMRD_AcquisitionHeader* chead)
+{
+ BOOST_CHECK_EQUAL(chead->version, ISMRMRD_VERSION_MAJOR);
+ BOOST_CHECK_EQUAL(chead->number_of_samples, 0);
+ BOOST_CHECK_EQUAL(chead->available_channels, 1);
+ BOOST_CHECK_EQUAL(chead->active_channels, 1);
+ BOOST_CHECK_EQUAL(chead->flags, 0);
+ BOOST_CHECK_EQUAL(chead->measurement_uid, 0);
+ BOOST_CHECK_EQUAL(chead->scan_counter, 0);
+ BOOST_CHECK_EQUAL(chead->acquisition_time_stamp, 0);
+ for (int idx = 0; idx < ISMRMRD_PHYS_STAMPS; idx++) {
+ BOOST_CHECK_EQUAL(chead->physiology_time_stamp[idx], 0);
+ }
+
+ for (int idx = 0; idx < ISMRMRD_CHANNEL_MASKS; idx++) {
+ BOOST_CHECK_EQUAL(chead->channel_mask[idx], 0);
+ }
+ BOOST_CHECK_EQUAL(chead->discard_pre, 0);
+ BOOST_CHECK_EQUAL(chead->discard_post, 0);
+ BOOST_CHECK_EQUAL(chead->center_sample, 0);
+ BOOST_CHECK_EQUAL(chead->encoding_space_ref, 0);
+ BOOST_CHECK_EQUAL(chead->trajectory_dimensions, 0);
+ BOOST_CHECK_EQUAL(chead->sample_time_us, 0);
+ for (int idx = 0; idx < ISMRMRD_POSITION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->position[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_DIRECTION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->read_dir[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_DIRECTION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->phase_dir[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_DIRECTION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->slice_dir[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_POSITION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->patient_table_position[idx], 0);
+ }
+
+ // EncodingCounters
+ BOOST_CHECK_EQUAL(chead->idx.kspace_encode_step_1, 0);
+ BOOST_CHECK_EQUAL(chead->idx.kspace_encode_step_2, 0);
+ BOOST_CHECK_EQUAL(chead->idx.average, 0);
+ BOOST_CHECK_EQUAL(chead->idx.slice, 0);
+ BOOST_CHECK_EQUAL(chead->idx.contrast, 0);
+ BOOST_CHECK_EQUAL(chead->idx.phase, 0);
+ BOOST_CHECK_EQUAL(chead->idx.repetition, 0);
+ BOOST_CHECK_EQUAL(chead->idx.set, 0);
+ BOOST_CHECK_EQUAL(chead->idx.segment, 0);
+
+ for (int idx = 0; idx < ISMRMRD_USER_INTS; idx++) {
+ BOOST_CHECK_EQUAL(chead->idx.user[idx], 0);
+ }
+
+ for (int idx = 0; idx < ISMRMRD_USER_INTS; idx++) {
+ BOOST_CHECK_EQUAL(chead->user_int[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_USER_FLOATS; idx++) {
+ BOOST_CHECK_EQUAL(chead->user_float[idx], 0);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test_channels.cpp b/tests/test_channels.cpp
new file mode 100644
index 0000000..54a1c8a
--- /dev/null
+++ b/tests/test_channels.cpp
@@ -0,0 +1,76 @@
+#include "ismrmrd/ismrmrd.h"
+#include "ismrmrd/version.h"
+#include <boost/test/unit_test.hpp>
+
+using namespace ISMRMRD;
+
+BOOST_AUTO_TEST_SUITE(ChannelTest)
+
+void fill_channels(uint64_t mask[ISMRMRD_CHANNEL_MASKS])
+{
+ for (int i = 0; i < ISMRMRD_CHANNEL_MASKS; i++) {
+ mask[i] = 0xFFFFFFFFFFFFFFFF;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_is_channel_on)
+{
+ uint64_t channel_mask[ISMRMRD_CHANNEL_MASKS] = {0};
+
+ // TODO: this returns and ISMRMRD_RUNTIMEERROR, which casts to "true"
+ /* BOOST_CHECK_EQUAL(ismrmrd_is_channel_on(NULL, 0), false); */
+
+ for (int chan = 0; chan < 64 * ISMRMRD_CHANNEL_MASKS; chan++) {
+ BOOST_CHECK_EQUAL(ismrmrd_is_channel_on(channel_mask, chan), false);
+ }
+
+ fill_channels(channel_mask);
+ for (int chan = 0; chan < 64 * ISMRMRD_CHANNEL_MASKS; chan++) {
+ BOOST_CHECK_EQUAL(ismrmrd_is_channel_on(channel_mask, chan), true);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_set_channel_on)
+{
+ uint64_t channel_mask[ISMRMRD_CHANNEL_MASKS] = {0};
+
+ BOOST_CHECK_EQUAL(ismrmrd_set_channel_on(NULL, 0), ISMRMRD_RUNTIMEERROR);
+
+ for (int chan = 0; chan < 64 * ISMRMRD_CHANNEL_MASKS; chan++) {
+ BOOST_CHECK_EQUAL(ismrmrd_set_channel_on(channel_mask, chan), ISMRMRD_NOERROR);
+ uint64_t bitmask = 1 << (chan % 64);
+ size_t offset = chan / 64;
+ BOOST_REQUIRE((channel_mask[offset] & bitmask) != 0);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_set_channel_off)
+{
+ uint64_t channel_mask[ISMRMRD_CHANNEL_MASKS] = {0};
+ fill_channels(channel_mask);
+
+ BOOST_CHECK_EQUAL(ismrmrd_set_channel_off(NULL, 0), ISMRMRD_RUNTIMEERROR);
+
+ for (int chan = 0; chan < 64 * ISMRMRD_CHANNEL_MASKS; chan++) {
+ BOOST_CHECK_EQUAL(ismrmrd_set_channel_off(channel_mask, chan), ISMRMRD_NOERROR);
+
+ uint64_t bitmask = 1 << (chan % 64);
+ size_t offset = chan / 64;
+ BOOST_REQUIRE((channel_mask[offset] & bitmask) == 0);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_set_all_channels_off)
+{
+ uint64_t channel_mask[ISMRMRD_CHANNEL_MASKS] = {0};
+ fill_channels(channel_mask);
+
+ BOOST_CHECK_EQUAL(ismrmrd_set_all_channels_off(NULL), ISMRMRD_RUNTIMEERROR);
+
+ BOOST_CHECK_EQUAL(ismrmrd_set_all_channels_off(channel_mask), ISMRMRD_NOERROR);
+ for (int idx = 0; idx < ISMRMRD_CHANNEL_MASKS; idx++) {
+ BOOST_REQUIRE(channel_mask[idx] == 0);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test_flags.cpp b/tests/test_flags.cpp
new file mode 100644
index 0000000..7402f0a
--- /dev/null
+++ b/tests/test_flags.cpp
@@ -0,0 +1,65 @@
+#include "ismrmrd/ismrmrd.h"
+#include "ismrmrd/version.h"
+#include <boost/test/unit_test.hpp>
+
+using namespace ISMRMRD;
+
+BOOST_AUTO_TEST_SUITE(FlagTest)
+
+BOOST_AUTO_TEST_CASE(test_is_flag_set)
+{
+ uint64_t flags = 0;
+
+ for (int f = 1; f <= 64; f++) {
+ BOOST_CHECK_EQUAL(ismrmrd_is_flag_set(flags, f), false);
+ }
+
+ for (int f = 1; f <= 64; f++) {
+ flags |= (1 << (f - 1));
+ BOOST_CHECK_EQUAL(ismrmrd_is_flag_set(flags, f), true);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_set_flag)
+{
+ uint64_t flags = 0;
+
+ BOOST_CHECK_EQUAL(ismrmrd_set_flag(NULL, ISMRMRD_ACQ_USER8), ISMRMRD_RUNTIMEERROR);
+
+ for (int f = 1; f <= 64; f++) {
+ BOOST_CHECK_EQUAL(ismrmrd_set_flag(&flags, f), ISMRMRD_NOERROR);
+ BOOST_REQUIRE((flags & (1 << (f - 1))) != 0);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_set_flags)
+{
+ uint64_t flags = 0;
+
+ BOOST_CHECK_EQUAL(ismrmrd_set_flags(NULL, 0xFFFFFFFFFFFFFFFF), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_set_flags(&flags, 0xFFFFFFFFFFFFFFFF), ISMRMRD_NOERROR);
+
+ BOOST_CHECK_EQUAL(flags, 0xFFFFFFFFFFFFFFFF);
+}
+
+BOOST_AUTO_TEST_CASE(test_clear_flag)
+{
+ uint64_t flags = 0xFFFFFFFFFFFFFFFF;
+
+ BOOST_CHECK_EQUAL(ismrmrd_clear_flag(NULL, ISMRMRD_IMAGE_USER8), ISMRMRD_RUNTIMEERROR);
+ for (int f = 1; f <= 64; f++) {
+ BOOST_CHECK_EQUAL(ismrmrd_clear_flag(&flags, f), ISMRMRD_NOERROR);
+ BOOST_REQUIRE((flags & (1 << (f - 1))) == 0);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_clear_all_flags)
+{
+ uint64_t flags = 0xFFFFFFFFFFFFFFFF;
+
+ BOOST_CHECK_EQUAL(ismrmrd_clear_all_flags(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_clear_all_flags(&flags), ISMRMRD_NOERROR);
+ BOOST_CHECK_EQUAL(flags, 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test_images.cpp b/tests/test_images.cpp
new file mode 100644
index 0000000..374c603
--- /dev/null
+++ b/tests/test_images.cpp
@@ -0,0 +1,169 @@
+#include "ismrmrd/ismrmrd.h"
+#include "ismrmrd/version.h"
+#include <boost/test/unit_test.hpp>
+
+using namespace ISMRMRD;
+
+BOOST_AUTO_TEST_SUITE(ImagesTest)
+
+static void check_header(ISMRMRD_ImageHeader* chead);
+
+BOOST_AUTO_TEST_CASE(test_image_header)
+{
+ ISMRMRD_ImageHeader chead;
+
+ // Check that header is of expected size
+ size_t expected_size = 15 * sizeof(uint16_t) +
+ (3 + ISMRMRD_PHYS_STAMPS) * sizeof(uint32_t) +
+ ISMRMRD_USER_INTS * sizeof(int32_t) +
+ 1 * sizeof(uint64_t) +
+ ((2 * ISMRMRD_POSITION_LENGTH) + (3 * ISMRMRD_DIRECTION_LENGTH) +
+ 3 + ISMRMRD_USER_FLOATS) * sizeof(float);
+ BOOST_CHECK_EQUAL(sizeof(chead), expected_size);
+
+ // Check that header is initialized properly
+ BOOST_CHECK_EQUAL(ismrmrd_init_image_header(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_init_image_header(&chead), ISMRMRD_NOERROR);
+ check_header(&chead);
+}
+
+BOOST_AUTO_TEST_CASE(test_image_init_cleanup)
+{
+ ISMRMRD_Image cimg;
+
+ // Check initialization of image
+ BOOST_CHECK_EQUAL(ismrmrd_init_image(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_init_image(&cimg), ISMRMRD_NOERROR);
+ check_header(&cimg.head);
+ BOOST_CHECK(!cimg.attribute_string);
+ BOOST_CHECK(!cimg.data);
+
+ // Check cleanup of image
+ BOOST_CHECK_EQUAL(ismrmrd_cleanup_image(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_cleanup_image(&cimg), ISMRMRD_NOERROR);
+ BOOST_CHECK(!cimg.attribute_string);
+ BOOST_CHECK(!cimg.data);
+}
+
+BOOST_AUTO_TEST_CASE(test_image_create_free)
+{
+ ISMRMRD_Image* cimgp = NULL;
+
+ // Check creation of new image
+ BOOST_CHECK(cimgp = ismrmrd_create_image());
+ // Check that it's initialized
+ check_header(&cimgp->head);
+ BOOST_CHECK(!cimgp->attribute_string);
+ BOOST_CHECK(!cimgp->data);
+
+ // Check cleanup
+ BOOST_CHECK_EQUAL(ismrmrd_free_image(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_free_image(cimgp), ISMRMRD_NOERROR);
+ BOOST_CHECK(!cimgp->attribute_string);
+ BOOST_CHECK(!cimgp->data);
+}
+
+BOOST_AUTO_TEST_CASE(test_image_copy)
+{
+ // Weak check of image copying
+ ISMRMRD_Image csrc, cdst;
+ BOOST_CHECK_EQUAL(ismrmrd_init_image(&csrc), ISMRMRD_NOERROR);
+ // TODO: it is necessary to call init_image on the destination image
+ // before copying, in case its attribute_string or data are non-NULL!
+ BOOST_CHECK_EQUAL(ismrmrd_init_image(&cdst), ISMRMRD_NOERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_image(&cdst, NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_image(NULL, &csrc), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_image(NULL, NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_image(&cdst, &csrc), ISMRMRD_NOERROR);
+ check_header(&cdst.head);
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_image_attribute_string(&cdst), 0);
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_image_data(&cdst), 0);
+ BOOST_CHECK(!cdst.attribute_string);
+ BOOST_CHECK(!cdst.data);
+}
+
+BOOST_AUTO_TEST_CASE(test_image_make_consistent)
+{
+ ISMRMRD_Image img;
+ BOOST_CHECK_EQUAL(ismrmrd_init_image(&img), ISMRMRD_NOERROR);
+
+ BOOST_CHECK_EQUAL(ismrmrd_make_consistent_image(NULL), ISMRMRD_RUNTIMEERROR);
+
+ uint16_t matrix_size[] = {128, 128, 1};
+ uint16_t nchannels = 8;
+ uint16_t dtype = ISMRMRD_FLOAT;
+ uint16_t attrlen = 65;
+ img.head.matrix_size[0] = matrix_size[0];
+ img.head.matrix_size[1] = matrix_size[1];
+ img.head.matrix_size[2] = matrix_size[2];
+ img.head.channels = nchannels;
+ img.head.data_type = dtype;
+ img.head.attribute_string_len = attrlen;
+
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_image_data(&img),
+ matrix_size[0] * matrix_size[1] * matrix_size[2] *
+ nchannels * ismrmrd_sizeof_data_type(dtype));
+ BOOST_CHECK_EQUAL(ismrmrd_size_of_image_attribute_string(&img),
+ attrlen * sizeof(*img.attribute_string));
+ BOOST_CHECK_EQUAL(ismrmrd_make_consistent_image(&img), ISMRMRD_NOERROR);
+
+ // check that data and attribute_string were allocated
+ BOOST_CHECK(img.data);
+ BOOST_CHECK(img.attribute_string);
+
+ ismrmrd_cleanup_image(&img);
+}
+
+static void check_header(ISMRMRD_ImageHeader* chead)
+{
+ BOOST_CHECK_EQUAL(chead->version, ISMRMRD_VERSION_MAJOR);
+ BOOST_CHECK_EQUAL(chead->matrix_size[0], 0);
+ BOOST_CHECK_EQUAL(chead->matrix_size[1], 1);
+ BOOST_CHECK_EQUAL(chead->matrix_size[2], 1);
+ BOOST_CHECK_EQUAL(chead->channels, 1);
+
+ BOOST_CHECK_EQUAL(chead->data_type, 0);
+ BOOST_CHECK_EQUAL(chead->flags, 0);
+ BOOST_CHECK_EQUAL(chead->measurement_uid, 0);
+ for (int idx = 0; idx < 3; idx++) {
+ BOOST_CHECK_EQUAL(chead->field_of_view[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_POSITION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->position[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_DIRECTION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->read_dir[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_DIRECTION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->phase_dir[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_DIRECTION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->slice_dir[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_POSITION_LENGTH; idx++) {
+ BOOST_CHECK_EQUAL(chead->patient_table_position[idx], 0);
+ }
+ BOOST_CHECK_EQUAL(chead->average, 0);
+ BOOST_CHECK_EQUAL(chead->slice, 0);
+ BOOST_CHECK_EQUAL(chead->contrast, 0);
+ BOOST_CHECK_EQUAL(chead->phase, 0);
+ BOOST_CHECK_EQUAL(chead->repetition, 0);
+ BOOST_CHECK_EQUAL(chead->set, 0);
+ BOOST_CHECK_EQUAL(chead->acquisition_time_stamp, 0);
+ for (int idx = 0; idx < ISMRMRD_PHYS_STAMPS; idx++) {
+ BOOST_CHECK_EQUAL(chead->physiology_time_stamp[idx], 0);
+ }
+ BOOST_CHECK_EQUAL(chead->image_type, 0);
+ BOOST_CHECK_EQUAL(chead->image_index, 0);
+ BOOST_CHECK_EQUAL(chead->image_series_index, 0);
+
+ for (int idx = 0; idx < ISMRMRD_USER_INTS; idx++) {
+ BOOST_CHECK_EQUAL(chead->user_int[idx], 0);
+ }
+ for (int idx = 0; idx < ISMRMRD_USER_FLOATS; idx++) {
+ BOOST_CHECK_EQUAL(chead->user_float[idx], 0);
+ }
+ BOOST_CHECK_EQUAL(chead->attribute_string_len, 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test_ismrmrd.h b/tests/test_ismrmrd.h
new file mode 100644
index 0000000..ece311f
--- /dev/null
+++ b/tests/test_ismrmrd.h
@@ -0,0 +1,4 @@
+#pragma once
+
+void silent_error_handler(const char *file, int line,
+ const char *function, int code, const char *msg);
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
new file mode 100644
index 0000000..4b1809d
--- /dev/null
+++ b/tests/test_main.cpp
@@ -0,0 +1,26 @@
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE "ISMRMRD Unit Tests"
+#include <boost/test/unit_test.hpp>
+
+#include "ismrmrd/ismrmrd.h"
+using namespace ISMRMRD;
+
+void silent_error_handler(const char *file, int line,
+ const char *function, int code, const char *msg)
+{
+}
+
+struct GlobalConfig {
+ // global setup
+ GlobalConfig()
+ {
+ // enable more verbose testing output
+ boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_test_units);
+ // silence ISMRMRD errors on stdout
+ ismrmrd_set_error_handler(silent_error_handler);
+ }
+ // global teardown
+ ~GlobalConfig() { }
+};
+
+BOOST_GLOBAL_FIXTURE(GlobalConfig);
diff --git a/tests/test_ndarray.cpp b/tests/test_ndarray.cpp
new file mode 100644
index 0000000..abea4ab
--- /dev/null
+++ b/tests/test_ndarray.cpp
@@ -0,0 +1,71 @@
+#include "ismrmrd/ismrmrd.h"
+#include "ismrmrd/version.h"
+#include <boost/test/unit_test.hpp>
+
+using namespace ISMRMRD;
+
+BOOST_AUTO_TEST_SUITE(NDArrayTest)
+
+BOOST_AUTO_TEST_CASE(test_ndarray_init_cleanup)
+{
+ ISMRMRD_NDArray carr;
+
+ // Check initialization of ndarray
+ BOOST_CHECK_EQUAL(ismrmrd_init_ndarray(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_init_ndarray(&carr), ISMRMRD_NOERROR);
+ BOOST_CHECK_EQUAL(carr.version, ISMRMRD_VERSION_MAJOR);
+ BOOST_CHECK_EQUAL(carr.data_type, 0); // TODO: enumerate ISMRMRD_NO_DATATYPE
+ BOOST_CHECK_EQUAL(carr.ndim, 0);
+ for (int idx = 0; idx < ISMRMRD_NDARRAY_MAXDIM; idx++) {
+ BOOST_CHECK_EQUAL(carr.dims[idx], 0);
+ }
+ BOOST_CHECK(!carr.data);
+
+ // Check cleanup of ndarray
+ BOOST_CHECK_EQUAL(ismrmrd_cleanup_ndarray(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_cleanup_ndarray(&carr), ISMRMRD_NOERROR);
+ BOOST_CHECK(!carr.data);
+}
+
+BOOST_AUTO_TEST_CASE(test_ndarray_create_free)
+{
+ ISMRMRD_NDArray* carrp = NULL;
+
+ // Check creation of new ndarray
+ BOOST_CHECK(carrp = ismrmrd_create_ndarray());
+ BOOST_CHECK_EQUAL(carrp->version, ISMRMRD_VERSION_MAJOR);
+ BOOST_CHECK_EQUAL(carrp->data_type, 0); // TODO: enumerate ISMRMRD_NO_DATATYPE
+ BOOST_CHECK_EQUAL(carrp->ndim, 0);
+ for (int idx = 0; idx < ISMRMRD_NDARRAY_MAXDIM; idx++) {
+ BOOST_CHECK_EQUAL(carrp->dims[idx], 0);
+ }
+ BOOST_CHECK(!carrp->data);
+
+ // Check cleanup
+ BOOST_CHECK_EQUAL(ismrmrd_free_ndarray(NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_free_ndarray(carrp), ISMRMRD_NOERROR);
+ BOOST_CHECK(!carrp->data);
+}
+
+BOOST_AUTO_TEST_CASE(test_ndarray_copy)
+{
+ // Weak check of ndarray copying
+ ISMRMRD_NDArray csrc, cdst;
+ BOOST_CHECK_EQUAL(ismrmrd_init_ndarray(&csrc), ISMRMRD_NOERROR);
+ // NOTE: it is necessary to call init_ndarray on the destination ndarray
+ // before copying, in case its data is non-NULL!
+ BOOST_CHECK_EQUAL(ismrmrd_init_ndarray(&cdst), ISMRMRD_NOERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_ndarray(&cdst, NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_ndarray(NULL, &csrc), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_ndarray(NULL, NULL), ISMRMRD_RUNTIMEERROR);
+ BOOST_CHECK_EQUAL(ismrmrd_copy_ndarray(&cdst, &csrc), ISMRMRD_NOERROR);
+ BOOST_CHECK_EQUAL(cdst.version, ISMRMRD_VERSION_MAJOR);
+ BOOST_CHECK_EQUAL(cdst.data_type, 0); // TODO: enumerate ISMRMRD_NO_DATATYPE
+ BOOST_CHECK_EQUAL(cdst.ndim, 0);
+ for (int idx = 0; idx < ISMRMRD_NDARRAY_MAXDIM; idx++) {
+ BOOST_CHECK_EQUAL(cdst.dims[idx], 0);
+ }
+ BOOST_CHECK(!cdst.data);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test_quaternions.cpp b/tests/test_quaternions.cpp
new file mode 100644
index 0000000..f73ef36
--- /dev/null
+++ b/tests/test_quaternions.cpp
@@ -0,0 +1,60 @@
+#include "ismrmrd/ismrmrd.h"
+#include <boost/test/unit_test.hpp>
+
+using namespace ISMRMRD;
+
+BOOST_AUTO_TEST_SUITE(QuaternionTest)
+
+BOOST_AUTO_TEST_CASE(test_directions_to_quaternion)
+{
+ float read_dir[3] = {1.0, 0, 0};
+ float phase_dir[3] = {0, 1.0, 0};
+ float slice_dir[3] = {0, 0, 1.0};
+ float quaternion[4];
+
+ /* convert the direction vectors to a quaternion and verify */
+ ismrmrd_directions_to_quaternion(read_dir, phase_dir, slice_dir, quaternion);
+
+ BOOST_CHECK_EQUAL(quaternion[0], 0.0);
+ BOOST_CHECK_EQUAL(quaternion[1], 0.0);
+ BOOST_CHECK_EQUAL(quaternion[2], 0.0);
+ BOOST_CHECK_EQUAL(quaternion[3], 1.0);
+}
+
+BOOST_AUTO_TEST_CASE(test_quaternion_to_directions)
+{
+ float read_dir[3];
+ float phase_dir[3];
+ float slice_dir[3];
+ float quaternion[4] = {0.0, 0.0, 0.0, 1.0};
+
+ /* convert the quaternion back to direction cosines and verify */
+ ismrmrd_quaternion_to_directions(quaternion, read_dir, phase_dir, slice_dir);
+ BOOST_CHECK_EQUAL(read_dir[0], 1.0);
+ BOOST_CHECK_EQUAL(read_dir[1], 0.0);
+ BOOST_CHECK_EQUAL(read_dir[2], 0.0);
+ BOOST_CHECK_EQUAL(phase_dir[0], 0.0);
+ BOOST_CHECK_EQUAL(phase_dir[1], 1.0);
+ BOOST_CHECK_EQUAL(phase_dir[2], 0.0);
+ BOOST_CHECK_EQUAL(slice_dir[0], 0.0);
+ BOOST_CHECK_EQUAL(slice_dir[1], 0.0);
+ BOOST_CHECK_EQUAL(slice_dir[2], 1.0);
+}
+
+BOOST_AUTO_TEST_CASE(test_sign_of_directions)
+{
+ float read_dir[3] = {1.0, 0, 0};
+ float phase_dir[3] = {0, 1.0, 0};
+ float slice_dir[3] = {0, 0, 1.0};
+
+ /* check that determinant is > 0 */
+ BOOST_REQUIRE(ismrmrd_sign_of_directions(read_dir, phase_dir, slice_dir) > 0);
+
+ /* flip sign of third column and check that determinant is < 0 */
+ slice_dir[0] = -slice_dir[0];
+ slice_dir[1] = -slice_dir[1];
+ slice_dir[2] = -slice_dir[2];
+ BOOST_REQUIRE(ismrmrd_sign_of_directions(read_dir, phase_dir, slice_dir) < 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt
index 2257dec..73dc095 100644
--- a/utilities/CMakeLists.txt
+++ b/utilities/CMakeLists.txt
@@ -8,66 +8,68 @@ add_executable(ismrmrd_info ismrmrd_info.cpp)
target_link_libraries(ismrmrd_info ismrmrd)
install(TARGETS ismrmrd_info DESTINATION bin)
-add_executable(ismrmrd_read_timing_test read_timing_test.cpp)
-target_link_libraries(ismrmrd_read_timing_test ismrmrd)
-install(TARGETS ismrmrd_read_timing_test DESTINATION bin)
-
if (NOT WIN32)
- add_executable(ismrmrd_test_xml
- ismrmrd_test_xml.cpp
+ add_executable(ismrmrd_test_xml
+ ismrmrd_test_xml.cpp
${CMAKE_SOURCE_DIR}/libsrc/pugixml.cpp )
target_link_libraries(ismrmrd_test_xml ismrmrd)
install(TARGETS ismrmrd_test_xml DESTINATION bin)
endif(NOT WIN32)
-find_package(Boost 1.43 COMPONENTS program_options)
-find_package(FFTW3 COMPONENTS single)
+if (HDF5_FOUND)
+ add_executable(ismrmrd_read_timing_test read_timing_test.cpp)
+ target_link_libraries(ismrmrd_read_timing_test ismrmrd)
+ install(TARGETS ismrmrd_read_timing_test DESTINATION bin)
+
+ find_package(Boost 1.43 COMPONENTS program_options)
+ find_package(FFTW3 COMPONENTS single)
+
+ if(FFTW3_FOUND AND Boost_FOUND)
+ message("FFTW3 and Boost Found... building utilities")
-if(FFTW3_FOUND AND Boost_FOUND)
- message("FFTW3 and Boost Found, building utilities")
-
- if(WIN32)
- link_directories(${Boost_LIBRARY_DIRS})
- endif(WIN32)
+ if(WIN32)
+ link_directories(${Boost_LIBRARY_DIRS})
+ endif(WIN32)
- include_directories(
- ${CMAKE_SOURCE_DIR/include}
- ${Boost_INCLUDE_DIR}
- ${FFTW3_INCLUDE_DIR})
+ include_directories(
+ ${CMAKE_SOURCE_DIR/include}
+ ${Boost_INCLUDE_DIR}
+ ${FFTW3_INCLUDE_DIR})
- # Shepp-Logan phantom
- add_executable(ismrmrd_generate_cartesian_shepp_logan
- generate_cartesian_shepp_logan.cpp
- ismrmrd_phantom.cpp)
- if(WIN32)
- target_link_libraries( ismrmrd_generate_cartesian_shepp_logan
- ismrmrd
- ${FFTW3_LIBRARIES})
- else(WIN32)
- target_link_libraries( ismrmrd_generate_cartesian_shepp_logan
- ismrmrd
- ${Boost_PROGRAM_OPTIONS_LIBRARY}
- ${FFTW3_LIBRARIES})
- endif(WIN32)
- install(TARGETS ismrmrd_generate_cartesian_shepp_logan
- DESTINATION bin)
+ # Shepp-Logan phantom
+ add_executable(ismrmrd_generate_cartesian_shepp_logan
+ generate_cartesian_shepp_logan.cpp
+ ismrmrd_phantom.cpp)
+ if(WIN32)
+ target_link_libraries( ismrmrd_generate_cartesian_shepp_logan
+ ismrmrd
+ ${FFTW3_LIBRARIES})
+ else(WIN32)
+ target_link_libraries( ismrmrd_generate_cartesian_shepp_logan
+ ismrmrd
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${FFTW3_LIBRARIES})
+ endif(WIN32)
+ install(TARGETS ismrmrd_generate_cartesian_shepp_logan DESTINATION bin)
- # Shepp-Logan phantom
- add_executable(ismrmrd_recon_cartesian_2d
- recon_cartesian_2d.cpp)
- if(WIN32)
- target_link_libraries( ismrmrd_recon_cartesian_2d
- ismrmrd
- ${FFTW3_LIBRARIES})
- else(WIN32)
- target_link_libraries( ismrmrd_recon_cartesian_2d
- ismrmrd
- ${Boost_PROGRAM_OPTIONS_LIBRARY}
- ${FFTW3_LIBRARIES})
- endif(WIN32)
- install(TARGETS ismrmrd_recon_cartesian_2d
- DESTINATION bin)
+ # Shepp-Logan phantom
+ add_executable(ismrmrd_recon_cartesian_2d
+ recon_cartesian_2d.cpp)
+ if(WIN32)
+ target_link_libraries( ismrmrd_recon_cartesian_2d
+ ismrmrd
+ ${FFTW3_LIBRARIES})
+ else(WIN32)
+ target_link_libraries( ismrmrd_recon_cartesian_2d
+ ismrmrd
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${FFTW3_LIBRARIES})
+ endif(WIN32)
+ install(TARGETS ismrmrd_recon_cartesian_2d DESTINATION bin)
-else(FFTW3_FOUND AND Boost_FOUND)
- message("FFTW3 or Boost NOT Found, cannot build utilities")
-endif(FFTW3_FOUND AND Boost_FOUND)
+ else(FFTW3_FOUND AND Boost_FOUND)
+ message("FFTW3 or Boost NOT Found, cannot build utilities")
+ endif(FFTW3_FOUND AND Boost_FOUND)
+else (HDF5_FOUND)
+ message("HDF5 NOT Found, cannot build utilities")
+endif (HDF5_FOUND)
diff --git a/utilities/ismrmrd_info.cpp b/utilities/ismrmrd_info.cpp
index 77a94ef..e869b8c 100644
--- a/utilities/ismrmrd_info.cpp
+++ b/utilities/ismrmrd_info.cpp
@@ -4,7 +4,9 @@
int main(int argc, char** argv)
{
std::cout << "ISMRMRD VERSION INFO: " << std::endl;
- std::cout << " -- version " << ISMRMRD_VERSION_MAJOR << "." << ISMRMRD_VERSION_MINOR << "." << ISMRMRD_VERSION_PATCH << std::endl;
- std::cout << " -- SHA1 " << ISMRMRD_GIT_SHA1_HASH << std::endl;
+ std::cout << " -- Version: " << ISMRMRD_VERSION_MAJOR << "." <<
+ ISMRMRD_VERSION_MINOR << "." << ISMRMRD_VERSION_PATCH << std::endl;
+ std::cout << " -- SHA1: " << ISMRMRD_GIT_SHA1_HASH << std::endl;
+ std::cout << " -- Dataset support: " << (ISMRMRD_DATASET_SUPPORT ? "yes" : "no") << std::endl;
return 0;
}
diff --git a/utilities/recon_cartesian_2d.cpp b/utilities/recon_cartesian_2d.cpp
index 3c09b0b..424296f 100644
--- a/utilities/recon_cartesian_2d.cpp
+++ b/utilities/recon_cartesian_2d.cpp
@@ -70,67 +70,86 @@ int main(int argc, char** argv)
ISMRMRD::EncodingSpace e_space = hdr.encoding[0].encodedSpace;
ISMRMRD::EncodingSpace r_space = hdr.encoding[0].reconSpace;
- std::cout << "Encoding Matrix Size : [" << e_space.matrixSize.x << ", " << e_space.matrixSize.y << ", " << e_space.matrixSize.z << "]" << std::endl;
- std::cout << "Reconstruction Matrix Size : [" << r_space.matrixSize.x << ", " << r_space.matrixSize.y << ", " << r_space.matrixSize.z << "]" << std::endl;
- std::cout << "Number of acquisitions : " << d.getNumberOfAcquisitions() << std::endl;
-
if (e_space.matrixSize.z != 1) {
std::cout << "This simple reconstruction application only supports 2D encoding spaces" << std::endl;
return -1;
}
+
+ uint16_t nX = e_space.matrixSize.x;
+ uint16_t nY = e_space.matrixSize.y;
+
+ // The number of channels is optional, so read the first line
+ ISMRMRD::Acquisition acq;
+ d.readAcquisition(0, acq);
+ uint16_t nCoils = acq.active_channels();
+
+ std::cout << "Encoding Matrix Size : [" << e_space.matrixSize.x << ", " << e_space.matrixSize.y << ", " << e_space.matrixSize.z << "]" << std::endl;
+ std::cout << "Reconstruction Matrix Size : [" << r_space.matrixSize.x << ", " << r_space.matrixSize.y << ", " << r_space.matrixSize.z << "]" << std::endl;
+ std::cout << "Number of Channels : " << nCoils << std::endl;
+ std::cout << "Number of acquisitions : " << d.getNumberOfAcquisitions() << std::endl;
//Allocate a buffer for the data
std::vector<size_t> dims;
- dims.push_back(e_space.matrixSize.x);
- dims.push_back(e_space.matrixSize.y);
+ dims.push_back(nX);
+ dims.push_back(nY);
+ dims.push_back(nCoils);
ISMRMRD::NDArray<complex_float_t> buffer(dims);
+ memset(buffer.getDataPtr(), 0, sizeof(complex_float_t)*nX*nY*nCoils);
//Now loop through and copy data
unsigned int number_of_acquisitions = d.getNumberOfAcquisitions();
- ISMRMRD::Acquisition acq;
for (unsigned int i = 0; i < number_of_acquisitions; i++) {
//Read one acquisition at a time
d.readAcquisition(i, acq);
//Copy data, we should probably be more careful here and do more tests....
- //We are not considering multiple channels here.
- unsigned int offset = acq.idx().kspace_encode_step_1*dims[0];
- memcpy(&buffer.getDataPtr()[offset], acq.getDataPtr(),sizeof(complex_float_t)*dims[0]);
- }
-
- //Let's FFT the k-space to image
- fftwf_complex* tmp = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*buffer.getNumberOfElements());
-
- if (!tmp) {
- std::cout << "Error allocating temporary storage for FFTW" << std::endl;
- return -1;
+ for (uint16_t c=0; c<nCoils; c++) {
+ memcpy(&buffer(0,acq.idx().kspace_encode_step_1,c), &acq.data(0, c), sizeof(complex_float_t)*nX);
+ }
}
- //FFTSHIFT
- fftshift(reinterpret_cast<complex_float_t*>(tmp), buffer.getDataPtr(), dims[0], dims[1]);
-
- //Create the FFTW plan
- fftwf_plan p = fftwf_plan_dft_2d(dims[1], dims[0], tmp ,tmp, FFTW_BACKWARD, FFTW_ESTIMATE);
+ // Do the recon one slice at a time
+ for (uint16_t c=0; c<nCoils; c++) {
+
+ //Let's FFT the k-space to image (in-place)
+ fftwf_complex* tmp = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*(nX*nY));
- //Execute the FFT
- fftwf_execute(p);
-
- //FFTSHIFT
- fftshift( buffer.getDataPtr(), reinterpret_cast<std::complex<float>*>(tmp), dims[0], dims[1]);
+ if (!tmp) {
+ std::cout << "Error allocating temporary storage for FFTW" << std::endl;
+ return -1;
+ }
+
+ //Create the FFTW plan
+ fftwf_plan p = fftwf_plan_dft_2d(nY, nX, tmp ,tmp, FFTW_BACKWARD, FFTW_ESTIMATE);
+
+ //FFTSHIFT
+ fftshift(reinterpret_cast<complex_float_t*>(tmp), &buffer(0,0,c), nX, nY);
+
+ //Execute the FFT
+ fftwf_execute(p);
+
+ //FFTSHIFT
+ fftshift( &buffer(0,0,c), reinterpret_cast<std::complex<float>*>(tmp), nX, nY);
+
+ //Clean up.
+ fftwf_destroy_plan(p);
+ fftwf_free(tmp);
- //Clean up.
- fftwf_destroy_plan(p);
- fftwf_free(tmp);
+ }
//Allocate an image
ISMRMRD::Image<float> img_out(r_space.matrixSize.x, r_space.matrixSize.y, 1, 1);
-
+ memset(img_out.getDataPtr(), 0, sizeof(float_t)*r_space.matrixSize.x*r_space.matrixSize.y);
+
//f there is oversampling in the readout direction remove it
- //Take the magnitude
- size_t offset = ((e_space.matrixSize.x - r_space.matrixSize.x)>>1);
- for (unsigned int y = 0; y < r_space.matrixSize.y; y++) {
- for (unsigned int x = 0; x < r_space.matrixSize.x; x++) {
- img_out(x,y) = std::abs(buffer(x+offset, y));
+ //Take the sqrt of the sum of squares
+ uint16_t offset = ((e_space.matrixSize.x - r_space.matrixSize.x)>>1);
+ for (uint16_t y = 0; y < r_space.matrixSize.y; y++) {
+ for (uint16_t x = 0; x < r_space.matrixSize.x; x++) {
+ for (uint16_t c=0; c<nCoils; c++) {
+ img_out(x,y) += (std::abs(buffer(x+offset, y, c)))*(std::abs(buffer(x+offset, y, c)));
+ }
+ img_out(x,y) = std::sqrt(img_out(x,y));
}
}
@@ -141,7 +160,7 @@ int main(int argc, char** argv)
//And so on
//Let's write the reconstructed image into the same data file
- d.appendImage("myimage", img_out);
+ d.appendImage("cpp", img_out);
return 0;
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/ismrmrd.git
More information about the debian-med-commit
mailing list