New upstream version 1.3.3

parent 8e0ebe66
......@@ -12,6 +12,7 @@ install:
before_script:
- mkdir build
- cd build
- cmake --version
- cmake ..
script: make && make check
cmake_minimum_required(VERSION 2.8)
foreach(p
CMP0025 # CMake 3.0 Compiler id for Apple Clang is now ``AppleClang``.
CMP0042 # CMake 3.0 ``MACOSX_RPATH`` is enabled by default.
CMP0046 # CMake 3.0 Error on non-existent dependency in add_dependencies.
CMP0054 # CMake 3.1 Only interpret ``if()`` arguments as variables or keywords when unquoted.
CMP0056 # CMake 3.2 Honor link flags in ``try_compile()`` source-file signature.
CMP0058 # CMake 3.3 Ninja requires custom command byproducts to be explicit.
)
if(POLICY ${p})
cmake_policy(SET ${p} NEW)
endif()
endforeach()
project(ISMRMRD)
# set project specific cmake module path
......@@ -13,15 +25,15 @@ list(APPEND CMAKE_MODULE_PATH ${ISMRMRD_CMAKE_DIR})
# whether to install dependencies
if (WIN32)
OPTION(ISMRMRD_INSTALL_DEPENDENCIES "Install ismrmrd dependencies in windows" Off)
endif (WIN32)
option(ISMRMRD_INSTALL_DEPENDENCIES "Install ismrmrd dependencies in windows" Off)
endif ()
# set the build type to Release if not specified
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Release CACHE STRING
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
endif()
# compiler flags
if (WIN32)
......@@ -35,10 +47,10 @@ if (WIN32)
set(CMAKE_STATIC_LINKER_FLAGS_DEBUG "/debug /INCREMENTAL:NO")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "/debug /INCREMENTAL:NO")
add_definitions(-D__func__=__FUNCTION__)
else (WIN32)
else ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif (WIN32)
endif ()
# --- VERSIONING (begin) ----
#The ISMRMRD convention is to use version numbers with the format:
......@@ -46,21 +58,25 @@ endif (WIN32)
#
#The major number increments when the binary compatibility of
#the fixed memory layout struts (e.g. AcquisitionHeader) is broken.
#The minor number changes when there are changes to the XML schema for
#The minor number changes when there are changes to the XML schema for
#the flexible header. The micro number changes when there are small changes
#in the utility libraries, that don't affect the data format itself.
# For more information see http://semver.org/
set(ISMRMRD_VERSION_MAJOR 1)
set(ISMRMRD_VERSION_MINOR 3)
set(ISMRMRD_VERSION_PATCH 2)
set(ISMRMRD_VERSION_PATCH 3)
set(ISMRMRD_VERSION_STRING ${ISMRMRD_VERSION_MAJOR}.${ISMRMRD_VERSION_MINOR}.${ISMRMRD_VERSION_PATCH})
set(ISMRMRD_SOVERSION ${ISMRMRD_VERSION_MAJOR}.${ISMRMRD_VERSION_MINOR})
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
file(STRINGS ${CMAKE_SOURCE_DIR}/schema/ismrmrd.xsd SCHEMA_STRINGS) #Read all strings from file
string(REPLACE ";" "" SCHEMA_NO_BREAKS ${SCHEMA_STRINGS}) #Concatenate the list of strings
string(REGEX REPLACE ">[ \t]+<" "><" SCHEMA_NO_SPACE ${SCHEMA_NO_BREAKS}) #Remove spaces and tabs
string(STRIP ${SCHEMA_NO_SPACE} SCHEMA_NO_SPACE) #Strip any leading/trailing whitespace
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/ismrmrd_no_white_space.xsd ${SCHEMA_NO_SPACE}) #Write to file
set(ISMRMRD_SCHEMA_DIR ${CMAKE_CURRENT_BINARY_DIR})
file(WRITE ${ISMRMRD_SCHEMA_DIR}/ismrmrd_no_white_space.xsd ${SCHEMA_NO_SPACE}) #Write to file
#Now hash the cleaned up file
file(SHA1 ${CMAKE_CURRENT_BINARY_DIR}/ismrmrd_no_white_space.xsd ISMRMRD_CURRENT_XML_SCHEMA_SHA1)
......@@ -88,8 +104,6 @@ if (NOT (${ISMRMRD_XML_SCHEMA_SHA1} STREQUAL ${ISMRMRD_CURRENT_XML_SCHEMA_SHA1})
message(FATAL_ERROR " FATAL XML VERSION ERROR")
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)
......@@ -99,10 +113,10 @@ if (HDF5_FOUND)
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)
else ()
set (ISMRMRD_DATASET_SUPPORT false)
message (WARNING "HDF5 not found. Dataset and file support unavailable!")
endif (HDF5_FOUND)
endif ()
# Generate the version.h header file
find_package(Git)
......@@ -114,15 +128,16 @@ if (GIT_FOUND)
if (${ISMRMRD_GIT_SHA1_LEN} LESS 40)
message(WARNING "Could not determine SHA-1 hash: ${ISMRMRD_GIT_STDERR}")
set(ISMRMRD_GIT_SHA1 "NA")
endif (${ISMRMRD_GIT_SHA1_LEN} LESS 40)
endif ()
else()
set(ISMRMRD_GIT_SHA1 "NA")
endif()
configure_file(include/version.in ${CMAKE_BINARY_DIR}/include/ismrmrd/version.h)
install(FILES ${CMAKE_BINARY_DIR}/include/ismrmrd/version.h DESTINATION include/ismrmrd)
install(FILES ${CMAKE_BINARY_DIR}/include/ismrmrd/version.h DESTINATION include/ismrmrd COMPONENT Devel)
# note: for the utilities in this project that need ismrmrd/version.h
# remember to add ${CMAKE_BINARY_DIR}/include to the include path
# --- VERSIONING (end) ----
# --- Main Library (begin) ----
......@@ -130,16 +145,16 @@ install(FILES ${CMAKE_BINARY_DIR}/include/ismrmrd/version.h DESTINATION include/
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})
else ()
set(HDF5_BIN_DIR ${HDF5_C_INCLUDE_DIR}/../bin)
endif (DEFINED ENV{HDF5_ROOT})
endif ()
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)
endif ()
# include directories for main library
set(ISMRMRD_TARGET_INCLUDE_DIRS
include
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_BINARY_DIR}/include
${ISMRMRD_DATASET_INCLUDE_DIR}
)
......@@ -161,16 +176,16 @@ if(USE_SYSTEM_PUGIXML)
message("Found system pugixml: ${PugiXML_INCLUDE_DIR} ${PugiXML_LIBRARY}")
list(APPEND ISMRMRD_TARGET_INCLUDE_DIRS ${PugiXML_INCLUDE_DIR})
list(APPEND ISMRMRD_TARGET_LINK_LIBS ${PugiXML_LIBRARY})
else(PugiXML_FOUND)
else()
message(FATAL_ERROR "Pugixml library not found on the system, try without "
"setting USE_SYSTEM_PUGIXML to use the version provided in the source "
"tree.")
endif(PugiXML_FOUND)
endif()
list(APPEND ISMRMRD_TARGET_INCLUDE_DIRS ${PugiXML_INCLUDE_DIR})
list(APPEND ISMRMRD_TARGET_LINK_LIBS ${PugiXML_LIBRARY})
else(USE_SYSTEM_PUGIXML)
else()
list(APPEND ISMRMRD_TARGET_SOURCES libsrc/pugixml.cpp)
endif(USE_SYSTEM_PUGIXML)
endif()
# main library
include_directories(${ISMRMRD_TARGET_INCLUDE_DIRS})
......@@ -180,18 +195,25 @@ set_target_properties(ismrmrd PROPERTIES
SOVERSION ${ISMRMRD_SOVERSION}
)
target_link_libraries(ismrmrd ${ISMRMRD_TARGET_LINK_LIBS})
list(APPEND ISMRMRD_LIBRARIES ismrmrd) # Add to list of libraries to be found
list(APPEND ISMRMRD_LIBRARY_DIRS ${CMAKE_BINARY_DIR} ) # Add to list of directories to find libaries
# install the main library
install(TARGETS ismrmrd DESTINATION lib)
install(TARGETS ismrmrd EXPORT ISMRMRDTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
COMPONENT Devel
)
# install the headers
install(DIRECTORY include/ismrmrd DESTINATION include)
install(DIRECTORY include/ismrmrd DESTINATION include COMPONENT Devel)
# install the schema file
install(FILES schema/ismrmrd.xsd DESTINATION share/ismrmrd/schema)
install(FILES schema/ismrmrd.xsd DESTINATION share/ismrmrd/schema COMPONENT Devel)
# install the cmake modules
install(FILES cmake/FindIsmrmrd.cmake cmake/FindFFTW3.cmake DESTINATION share/ismrmrd/cmake)
install(FILES cmake/FindFFTW3.cmake DESTINATION share/ismrmrd/cmake COMPONENT Devel)
# --- Main Library (end) ----
......@@ -201,15 +223,56 @@ add_subdirectory(doc)
add_subdirectory(utilities)
if (HDF5_FOUND)
add_subdirectory(examples/c)
endif (HDF5_FOUND)
endif ()
# TODO: make this work on Windows
if (NOT WIN32)
add_subdirectory(tests)
endif (NOT WIN32)
endif ()
# install the matlab api
install(DIRECTORY matlab DESTINATION share/ismrmrd)
install(DIRECTORY matlab DESTINATION share/ismrmrd )
#--- Create cmake package for downstream projects
#
##- include(CMakePackageConfigHelpers)
##- write_basic_package_version_file(
##- "${CMAKE_CURRENT_BINARY_DIR}/ISMRMRDConfigVersion.cmake"
##- VERSION ${ISMRMRD_VERSION_STRING}
##- COMPATIBILITY AnyNewerVersion
##- )
##- export(EXPORT ISMRMRDTargets
##- FILE "${CMAKE_CURRENT_BINARY_DIR}/ISMRMRDTargets.cmake"
##- NAMESPACE ISMRMRD
##-)
set(CONFIG_ISMRMRD_SCHEMA_DIR ${ISMRMRD_SCHEMA_DIR})
set(CONFIG_ISMRMRD_TARGET_INCLUDE_DIRS ${ISMRMRD_TARGET_INCLUDE_DIRS})
set(CONFIG_ISMRMRD_LIBRARY_DIRS ${ISMRMRD_LIBRARY_DIRS})
configure_file(cmake/ISMRMRDConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/ISMRMRDConfig.cmake"
@ONLY
)
set(CONFIG_ISMRMRD_SCHEMA_DIR ${CMAKE_INSTALL_PREFIX}/share/ismrmrd/schema)
set(CONFIG_ISMRMRD_TARGET_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include)
set(CONFIG_ISMRMRD_LIBRARY_DIRS ${CMAKE_INSTALL_PREFIX}/lib)
configure_file(cmake/ISMRMRDConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/InstallFiles/ISMRMRDConfig.cmake"
@ONLY
)
set(ConfigPackageLocation lib/cmake/ISMRMRD)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/InstallFiles/ISMRMRDConfig.cmake"
#-- "${CMAKE_CURRENT_BINARY_DIR}/ISMRMRDConfigVersion.cmake"
DESTINATION
${ConfigPackageLocation}
COMPONENT
Devel
)
# Create package
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
......@@ -219,4 +282,4 @@ if(CPACK_GENERATOR)
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(CPACK_GENERATOR)
endif()
......@@ -33,3 +33,26 @@ Other Resources
---------------
- [Python implementation](https://www.github.com/ismrmrd/ismrmrd-python)
External Use of ISMRMRD in other source packages
------------------------------------------------
Build and install ISMRMRD by setting
```
cmake -DCMAKE_INSTALL_PREFIX=<your install directory>
```
To use ISMRMRD for your externally developed projects, add the following to your CMakeLists.txt file:
```
find_package( ISMRMRD REQUIRED )
link_directories( ${ISMRMRD_LIBRARY_DIRS} )
include_directories( ${ISMRMRD_INCLUDE_DIRS} )
target_link_libraries( mytarget ${ISMRMRD_LIBRARIES} )
```
then when configuring your package use set the following cmake variables (command line variant shown):
```
cmake -DISMRMRD_DIR:PATH=<path to build/install tree of ISMRMRD> <path to my source tree>
```
......@@ -52,20 +52,20 @@ foreach(_comp ${_components})
list(APPEND _libraries fftw3l)
elseif(_comp STREQUAL "threads")
set(_use_threads ON)
else(_comp STREQUAL "single")
else()
message(FATAL_ERROR "FindFFTW3: unknown component `${_comp}' specified. "
"Valid components are `single', `double', `long-double', and `threads'.")
endif(_comp STREQUAL "single")
endforeach(_comp ${_components})
endif()
endforeach()
# If using threads, we need to link against threaded libraries as well.
if(_use_threads)
set(_thread_libs)
foreach(_lib ${_libraries})
list(APPEND _thread_libs ${_lib}_threads)
endforeach(_lib ${_libraries})
endforeach()
set(_libraries ${_thread_libs} ${_libraries})
endif(_use_threads)
endif()
# Keep a list of variable names that we need to pass on to
# find_package_handle_standard_args().
......@@ -83,11 +83,11 @@ if (WIN32)
mark_as_advanced(${_LIB}_LIBRARY)
list(APPEND FFTW3_LIBRARIES ${${_LIB}_LIBRARY})
list(APPEND _check_list ${_LIB}_LIBRARY)
endforeach(_lib ${_libraries})
endforeach()
message("FFTW3 WINDOWS libraries: " ${FFTW3_LIBRARIES})
else (WIN32)
else ()
foreach(_lib ${_libraries})
string(TOUPPER ${_lib} _LIB)
......@@ -97,10 +97,10 @@ else (WIN32)
mark_as_advanced(${_LIB}_LIBRARY)
list(APPEND FFTW3_LIBRARIES ${${_LIB}_LIBRARY})
list(APPEND _check_list ${_LIB}_LIBRARY)
endforeach(_lib ${_libraries})
endforeach()
message("FFTW3 UNIX libraries: " ${FFTW3_LIBRARIES})
endif (WIN32)
endif ()
# Search for the header file.
find_path(FFTW3_INCLUDE_DIR fftw3.h
......
# - Find ISMRMRRD
# ISMRMRD_FOUND - true if an ISMRMRD installation is found.
# ISMRMRD_INCLUDE_DIR - where to find ismrmrd.h, etc.
# ISMRMRD_LIBRARIES - libismrmrd.so and libismrmrd_xml.so
# ISMRMRD_SCHEMA_DIR - where to find ismrmrd.xsd
FIND_PATH( ISMRMRD_INCLUDE_DIR ismrmrd/ismrmrd.h
HINTS $ENV{ISMRMRD_HOME} PATHS /usr/local /usr PATH_SUFFIXES include)
FIND_PATH( ISMRMRD_SCHEMA_DIR ismrmrd.xsd
HINTS $ENV{ISMRMRD_HOME} PATHS /usr/local /usr PATH_SUFFIXES share/ismrmrd/schema)
FIND_LIBRARY( ISMRMRD_LIBRARY NAMES ismrmrd
HINTS $ENV{ISMRMRD_HOME} /usr/local /usr PATH_SUFFIXES lib)
SET(ISMRMRD_LIBRARIES ${ISMRMRD_LIBRARY})
INCLUDE( "FindPackageHandleStandardArgs" )
FIND_PACKAGE_HANDLE_STANDARD_ARGS( "Ismrmrd" DEFAULT_MSG ISMRMRD_INCLUDE_DIR ISMRMRD_LIBRARIES ISMRMRD_SCHEMA_DIR)
MARK_AS_ADVANCED( ISMRMRD_INCLUDE_DIR ISMRMRD_LIBRARIES ISMRMRD_SCHEMA_DIR)
#if(ISMRMRD_FOUND)
# message("ISMRMRD found ${ISMRMRD_LIBRARIES}")
#endif(ISMRMRD_FOUND)
#-----------------------------------------------------------------------------
#
# ISMRMRDConfig.cmake - ISMRMRD CMake configuration file for external projects.
#
# This file is configured by ISMRMRD and used by the UseISMRMRD.cmake module
# to load ISMRMRD's settings for an external project.
@ISMRMRD_CONFIG_CODE@
##- include(${CMAKE_CURRENT_LIST_DIR}/ISMRMRDConfigVersion.cmake)
# The ISMRMRD version number
set(ISMRMRD_VERSION_MAJOR "@ISMRMRD_VERSION_MAJOR@")
set(ISMRMRD_VERSION_MINOR "@ISMRMRD_VERSION_MINOR@")
set(ISMRMRD_VERSION_PATCH "@ISMRMRD_VERSION_PATCH@")
# ISMRMRD_SCHEMA_DIR - where to find ismrmrd.xsd
set(ISMRMRD_SCHEMA_DIR @CONFIG_ISMRMRD_SCHEMA_DIR@)
# ISMRMRD_INCLUDE_DIR - where to find ismrmrd.h, etc.
set(ISMRMRD_INCLUDE_DIRS @CONFIG_ISMRMRD_TARGET_INCLUDE_DIRS@)
# ISMRMRD_LIBRARY_DIRS - where to search for libraries
set(ISMRMRD_LIBRARY_DIRS @CONFIG_ISMRMRD_LIBRARY_DIRS@)
# ISMRMRD_LIBRARIES - i.e. ismrmrd
set(ISMRMRD_LIBRARIES @ISMRMRD_LIBRARIES@)
## For backwards compatibility use existing variable name
## Include directories can be lists, and should be plural
## to conform with naming schemes in many other cmake packages
set(ISMRMRD_INCLUDE_DIR @CONFIG_ISMRMRD_TARGET_INCLUDE_DIRS@)
set(ISMRMRD_LIB_DIR @CONFIG_ISMRMRD_LIBRARY_DIRS@)
......@@ -7,8 +7,8 @@ if(UNIX)
find_program(DPKG_PROGRAM dpkg)
if(EXISTS ${DPKG_PROGRAM})
list(APPEND CPACK_GENERATOR "DEB")
endif(EXISTS ${DPKG_PROGRAM})
endif(UNIX)
endif()
endif()
# Enable/Disable automatic search for dependencies:
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
......@@ -30,7 +30,7 @@ message("CPACK_PACKAGING_INSTALL_PREFIX: " ${CPACK_PACKAGING_INSTALL_PREFIX})
if(WIN32)
# NSLS
list(APPEND CPACK_GENERATOR "NSIS")
endif(WIN32)
endif()
list(APPEND CPACK_SOURCE_GENERATOR "TGZ")
list(APPEND CPACK_SOURCE_GENERATOR "ZIP")
......
add_custom_target(doc)
find_package(Doxygen)
if(DOXYGEN_FOUND)
set(API_DOC_DIR ${CMAKE_CURRENT_BINARY_DIR}/html/api)
......@@ -9,9 +10,10 @@ if(DOXYGEN_FOUND)
COMMAND ${CMAKE_COMMAND} -E make_directory ${API_DOC_DIR}
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE}
COMMENT "Generating API documentation using Doxygen" VERBATIM)
else(DOXYGEN_FOUND)
MESSAGE(STATUS "Doxygen not found. Not able to build API documentation")
endif(DOXYGEN_FOUND)
add_dependencies(doc apidoc)
else()
message(STATUS "Doxygen not found. Not able to build API documentation")
endif()
find_program(SPHINXBUILD sphinx-build)
if(SPHINXBUILD)
......@@ -22,17 +24,16 @@ if(SPHINXBUILD)
COMMAND ${SPHINX_MAKEBAT} html
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html/.nojekyll
COMMENT "Generating HTML docs using Sphinx" VERBATIM)
else(WIN32)
else()
set(SPHINX_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/Makefile.sphinx)
configure_file(Makefile.sphinx.in ${SPHINX_MAKEFILE} @ONLY)
add_custom_target(htmldoc
COMMAND make -f ${SPHINX_MAKEFILE} html
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html/.nojekyll
COMMENT "Generating HTML docs using Sphinx" VERBATIM)
endif(WIN32)
else(SPHINXBUILD)
MESSAGE(STATUS "sphinx-build not found. Not able to build HTML project documentation")
endif(SPHINXBUILD)
endif()
add_dependencies(doc htmldoc)
else()
message(STATUS "sphinx-build not found. Not able to build HTML project documentation")
endif()
add_custom_target(doc)
add_dependencies(doc apidoc htmldoc)
......@@ -5,17 +5,17 @@ project(ISMRMRD-C-EXAMPLE)
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})
endif()
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)
else()
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)
endif()
include_directories(${ISMRMRD_INCLUDE_DIR})
add_executable(ismrmrd_c_example main.c)
......
%% Generating a simple ISMRMRD data set to simulate GRAPPA undersampling
% Based on test_create_dataset
%
% This is an example of how to construct a datset from synthetic data
% simulating an under sampled acquisition on a cartesian grid with a
% central fully sampled (ACS) region.
% Data from 4 coils from a single slice object with 6 repetitions.
%
% Reconstruction using the gadgetron configuration file
% Generic_Cartesian_Grappa.xml may require changes to cope with the small
% number of coils:
% <property><name>upstream_coil_compression_thres</name><value>0.00001</value></property>
% <property><name>downstream_coil_compression_thres</name><value>0.0001</value></property>
% <property><name>use_constant_scalingFactor</name><value>false</value></property>
% Output file Name
def_filename = 'testusdatamri.h5';
FilterSpec = '*.h5' ;
DialogTitle = 'Output h5 filename' ;
[FileName,PathName,FilterIndex] = uiputfile(FilterSpec,DialogTitle,def_filename);
filename = fullfile(PathName,FileName) ;
dset = ismrmrd.Dataset(filename);
% Synthesize the object
% nY here corresponds to fully sampled data (256), nYsamp is number of actually
% sampled lines (128 + additional central ACS lines)
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);
% put an MR image in the centre
load mri % loads D - an example 128 128 1 27 dataset
rho(indxstart:indxend,indystart:indyend) = squeeze(double(D(:,:,1,12))) ;
% 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);
if exist('eshow','file')
eshow(C) % displays coil sensitivities
end
% set ACS lines for GRAPPA simulation (fully sampled central k-space
% region)
ACShw = 14 ; % GRAPPA ACS half width i.e. here 28 lines are ACS
Ysamp_u = [1:2:nY] ; % undersampling by every alternate line
Ysamp_ACS = [nY/2-ACShw+1 : nY/2+ACShw] ; % GRAPPA autocalibration lines
Ysamp = union(Ysamp_u, Ysamp_ACS) ; % actually sampled lines
nYsamp = length(Ysamp) ; % number of actually sampled
% Ysamp indexes the actually sampled lines to the encoded k-space line number.
% For example, if there were just regular factor 2 undersampling
% (with no ACS lines), Ysamp would have length 128 and be [1 3 5 ... 255].
% With ACS lines, the elements of Ysamp are separated by 2 near the k-space
% edges, and by 1 in the central ACS region.
% Synthesize the k-space data
nReps = 6 % increased from 4 to 6 to avoid confusion with number of coils.
noiselevel = 0.05;
K = zeros(nX, nYsamp, nCoils, nReps);
for rep = 1:nReps
for coil = 1:nCoils
noise = noiselevel * (randn(nX,nY)+1j*randn(nX,nY));
ksp = fftshift(fft2(fftshift( C(:,:,coil).*rho + noise)));
K(:,:,coil,rep) = ksp(:,Ysamp);
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 nYsamp aquisitions
acqblock = ismrmrd.Acquisition(nYsamp);
% Set the header elements that don't change
acqblock.head.version(:) = 1;
acqblock.head.number_of_samples(:) = nX;
acqblock.head.center_sample(:) = floor(nX/2);
acqblock.head.active_channels(:) = nCoils;
acqblock.head.read_dir = repmat([1 0 0]',[1 nYsamp]);
acqblock.head.phase_dir = repmat([0 1 0]',[1 nYsamp]);
acqblock.head.slice_dir = repmat([0 0 1]',[1 nYsamp]);
% Loop over the acquisitions, set the header, set the data and append
for rep = 1:nReps
for acqno = 1:nYsamp
% Set the header elements that change from acquisition to the next
% c-style counting
acqblock.head.scan_counter(acqno) = (rep-1)*nYsamp + acqno-1;
% Note next entry is k-space encoded line number (not acqno which
% is just the sequential acquisition number)
acqblock.head.idx.kspace_encode_step_1(acqno) = Ysamp(acqno)-1;
acqblock.head.idx.repetition(acqno) = rep - 1;
% Set the flags
acqblock.head.flagClearAll(acqno);
if acqno == 1
acqblock.head.flagSet('ACQ_FIRST_IN_ENCODE_STEP1', acqno);
acqblock.head.flagSet('ACQ_FIRST_IN_SLICE', acqno);
acqblock.head.flagSet('ACQ_FIRST_IN_REPETITION', acqno);
elseif acqno==size(K,2)
acqblock.head.flagSet('ACQ_LAST_IN_ENCODE_STEP1', acqno);
acqblock.head.flagSet('ACQ_LAST_IN_SLICE', acqno);
acqblock.head.flagSet('ACQ_LAST_IN_REPETITION', acqno);
end
if ismember(Ysamp(acqno),Ysamp_ACS)
if ismember(Ysamp(acqno),Ysamp_u)
% both calibration and part of the undersampled pattern
acqblock.head.flagSet('ACQ_IS_PARALLEL_CALIBRATION_AND_IMAGING', acqno)
else
% in ACS block but not part of the regular undersampling
% pattern Ysamp_u
acqblock.head.flagSet('ACQ_IS_PARALLEL_CALIBRATION', acqno) ;
end
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 %
%%%%%%%%%%%%%%%%%%%%%%%%
% We create a matlab struct and then serialize it to xml.
% Look at the xml schema to see what the field names should be
header = [];
% Experimental Conditions (Required)
header.experimentalConditions.H1resonanceFrequency_Hz = 128000000; % 3T
% Acquisition System Information (Optional)
header.acquisitionSystemInformation.systemVendor = 'ISMRMRD Labs';
header.acquisitionSystemInformation.systemModel = 'Virtual Scanner';
header.acquisitionSystemInformation.receiverChannels = nCoils;
% The Encoding (Required)
header.encoding.trajectory = 'cartesian';
header.encoding.encodedSpace.fieldOfView_mm.x = 256;
header.encoding.encodedSpace.fieldOfView_mm.y = 256;
header.encoding.encodedSpace.fieldOfView_mm.z = 5;
header.encoding.encodedSpace.matrixSize.x = size(K,1);
header.encoding.encodedSpace.matrixSize.y = nY;
header.encoding.encodedSpace.matrixSize.z = 1;
% Recon Space
% (in this case same as encoding space)
header.encoding.reconSpace = header.encoding.encodedSpace;
% Encoding Limits
header.encoding.encodingLimits.kspace_encoding_step_0.minimum = 0;
header.encoding.encodingLimits.kspace_encoding_step_0.maximum = size(K,1)-1;
header.encoding.encodingLimits.kspace_encoding_step_0.center = floor(size(K,1)/2);
header.encoding.encodingLimits.kspace_encoding_step_1.minimum = 0;
header.encoding.encodingLimits.kspace_encoding_step_1.maximum = nY-1;
header.encoding.encodingLimits.kspace_encoding_step_1.center = floor(nY/2);
header.encoding.encodingLimits.repetition.minimum = 0;
header.encoding.encodingLimits.repetition.maximum = nReps-1;
header.encoding.encodingLimits.repetition.center = 0;
header.encoding.parallelImaging.accelerationFactor.kspace_encoding_step_1 = 2 ;
header.encoding.parallelImaging.accelerationFactor.kspace_encoding_step_2 = 1 ;
header.encoding.parallelImaging.calibrationMode = 'embedded' ;
% Commented code below appears not necessary - saw this parameter after converting
% a scanner file using siemens_to_ismrmrd
% header.userParameters.userParameterLong.name = 'EmbeddedRefLinesE1' ;
% header.userParameters.userParameterLong.value = ACShw *2 ;
%% Serialize and write to the data set
xmlstring = ismrmrd.xml.serialize(header);
dset.writexml(xmlstring);
%% Write the dataset
dset.close();
......@@ -9,6 +9,7 @@
#define ISMRMRD_DATASET_H
#include "ismrmrd/ismrmrd.h"
#include <hdf5.h>
#ifdef __cplusplus
#include <string>
......@@ -28,7 +29,7 @@ extern "C" {
typedef struct ISMRMRD_Dataset {
char *filename;
char *groupname;
int fileid;
hid_t fileid;
} ISMRMRD_Dataset;
/**
......
......@@ -162,6 +162,10 @@ enum ISMRMRD_AcquisitionFlags {
ISMRMRD_ACQ_IS_RTFEEDBACK_DATA = 28,
ISMRMRD_ACQ_IS_SURFACECOILCORRECTIONSCAN_DATA = 29,
ISMRMRD_ACQ_COMPRESSION1 = 53,
ISMRMRD_ACQ_COMPRESSION2 = 54,
ISMRMRD_ACQ_COMPRESSION3 = 55,
ISMRMRD_ACQ_COMPRESSION4 = 56,
ISMRMRD_ACQ_USER1 = 57,
ISMRMRD_ACQ_USER2 = 58,
ISMRMRD_ACQ_USER3 = 59,
......
......@@ -133,20 +133,22 @@ int ismrmrd_make_consistent_acquisition(ISMRMRD_Acquisition *acq) {
traj_size = ismrmrd_size_of_acquisition_traj(acq);
if (traj_size > 0) {
acq->traj = (float *)realloc(acq->traj, traj_size);
if (acq->traj == NULL) {
float *newPtr = (float *)realloc(acq->traj, traj_size);
if (newPtr == NULL) {
return ISMRMRD_PUSH_ERR(ISMRMRD_MEMORYERROR,
"Failed to realloc acquisition trajectory array");
}
acq->traj = newPtr;
}
data_size = ismrmrd_size_of_acquisition_data(acq);
if (data_size > 0) {
acq->data = (complex_float_t *)realloc(acq->data, data_size);
if (acq->data == NULL) {
complex_float_t *newPtr = (complex_float_t *)realloc(acq->data, data_size);
if (newPtr == NULL) {
return ISMRMRD_PUSH_ERR(ISMRMRD_MEMORYERROR,
"Failed to realloc acquisition data array");
}
acq->data = newPtr;
}
return ISMRMRD_NOERROR;
......@@ -269,20 +271,22 @@ int ismrmrd_make_consistent_image(ISMRMRD_Image *im) {
attr_size = ismrmrd_size_of_image_attribute_string(im);
if (attr_size > 0) {
// 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) {