[ismrmrd] 04/281: Started work on HDF5 interface
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:00:48 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag ismrmrd0.5
in repository ismrmrd.
commit 7b53618bea3c7434dc6f3fd2473e0f6990917e1d
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date: Sat Jul 28 05:04:09 2012 -0400
Started work on HDF5 interface
---
CMakeLists.txt | 4 ++
cmake/FindIsmrmrd.cmake | 13 +++++
ismrmrd.h | 125 ++++++++++++++++++++++++++++++++----------------
ismrmrd_export.h | 14 ++++++
ismrmrd_hdf5.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++
ismrmrd_hdf5.h | 21 ++++++++
schema/ismrmrd.xsd | 13 ++++-
7 files changed, 265 insertions(+), 43 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0879d99..55d4cdc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,3 +15,7 @@ WRAP_XSD(XSDS_SOURCES XSD_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/schema ${XSDS} OP
INCLUDE_DIRECTORIES(${XSD_INCLUDES})
add_executable(ismrmrd main.cpp ${XSDS_SOURCES})
target_link_libraries(ismrmrd ${XERCESC_LIBRARIES})
+
+INSTALL(FILES ismrmrd.h DESTINATION include)
+INSTALL(FILES schema/ismrmrd.xsd DESTINATION schema)
+INSTALL(FILES cmake/FindIsmrmrd.cmake DESTINATION cmake)
\ No newline at end of file
diff --git a/cmake/FindIsmrmrd.cmake b/cmake/FindIsmrmrd.cmake
new file mode 100644
index 0000000..2e26b9d
--- /dev/null
+++ b/cmake/FindIsmrmrd.cmake
@@ -0,0 +1,13 @@
+# - Find ISMRMRRD
+# ISMRMRD_FOUND - True if ISMRMRD found.
+# ISMRMRD_INCLUDE_DIR - where to find ismrmrd.h, etc.
+
+FIND_PATH( ISMRMRD_INCLUDE_DIR "ismrmrd.h"
+ PATH_SUFFIXES "ismrmrd" )
+
+# handle the QUIETLY and REQUIRED arguments and set TINYXML_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE( "FindPackageHandleStandardArgs" )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( "Ismrmrd" DEFAULT_MSG ISMRMRD_INCLUDE_DIR)
+
+MARK_AS_ADVANCED( ISMRMRD_INCLUDE_DIR)
\ No newline at end of file
diff --git a/ismrmrd.h b/ismrmrd.h
index 0e5b03a..2c5592a 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -22,54 +22,97 @@ typedef unsigned __int64 uint64_t;
#include <stdint.h>
#endif
+#include <stdio.h>
+#include <string.h>
+
#pragma pack(4) //Use 4 byte alignment
+#define ISMRMRD_VERSION 1
+
namespace ISMRMRD
{
+
+ /* FLAGS */
+ //FIRST_SCAN_ SLICE,PARTITIONS, ETC
+ //LAST_SCAN
+ //Noise scan
+ //reference data (parallel imaging)
+ //Navigation data
+ //REVERSE
-/**
- Struct used for keeping track of typical loop counters in MR experiment.
+ /**
+ Struct used for keeping track of typical loop counters in MR experiment.
+
+ */
+ struct EncodingCounters {
+ uint16_t kspace_encode_step_1; //e.g. phase encoding line number
+ uint16_t kspace_encode_step_2; //e.g. partition encodning number
+ uint16_t average; //e.g. signal average number
+ uint16_t slice; //e.g. imaging slice number
+ uint16_t contrast; //e.g. echo number in multi-echo
+ uint16_t phase; //e.g. cardiac phase number
+ uint16_t repetition; //e.g. dynamic number for dynamic scanning
+ uint16_t set; //e.g. flow encodning set
+ uint16_t segment; //e.g. segment number for segmented acquisition
+ uint16_t user[8]; //Free user parameters
+ };
- */
-struct EncodingCounters {
- uint16_t kspace_encode_step_1; //e.g. phase encoding line number
- uint16_t kspace_encode_step_2; //e.g. partition encodning number
- uint16_t average; //e.g. signal average number
- uint16_t slice; //e.g. imaging slice number
- uint16_t contrast; //e.g. echo number in multi-echo
- uint16_t phase; //e.g. cardiac phase number
- uint16_t repetition; //e.g. dynamic number for dynamic scanning
- uint16_t set; //e.g. flow encodning set
- uint16_t segment; //e.g. segment number for segmented acquisition
- uint16_t user[8]; //Free user parameters
-};
+ /**
+ Header for each MR acquisition.
+ */
+ struct AcquisitionHeader
+ {
+ uint16_t version; //First unsigned int indicates the version
+ uint64_t flags; //bit field with flags
+ uint32_t measurement_uid; //Unique ID for the measurement
+ uint32_t scan_counter; //Current acquisition number in the measurement
+ uint32_t acquisition_time_stamp; //Acquisition clock
+ uint32_t physiology_time_stamp[3]; //Physiology time stamps, e.g. ecg, breating, etc.
+ uint16_t number_of_samples; //Number of samples acquired
+ uint16_t available_channels; //Available coils
+ uint16_t active_channels; //Active coils on current acquisiton
+ uint64_t channel_mask[16]; //Mask to indicate which channels are active. Support for 1024 channels
+ uint16_t discard_pre; //Samples to be discarded at the beginning of acquisition
+ uint16_t discard_post; //Samples to be discarded at the end of acquisition
+ uint16_t center_sample; //Sample at the center of k-space
+ uint16_t encoding_space_ref; //Reference to an encoding space, typically only one per acquisition
+ uint16_t trajectory_dimensions; //Indicates the dimensionality of the trajectory vector (0 means no trajectory)
+ float sample_time_us; //Time between samples in micro seconds, sampling BW
+ float position[3]; //Three-dimensional spatial offsets from isocenter
+ float quarternion[4]; //Angulation of acquisition
+ float patient_table_position[3]; //Patient table off-center
+ EncodingCounters idx; //Encoding loop counters, see above
+ uint32_t user_int[8]; //Free user parameters
+ float user_float[8]; //Free user parameters
+ };
+
+ class Acquisition
+ {
-/**
- Header for each MR acquisition.
- */
-struct Acquisition
-{
- uint64_t flags; //bit field with flags
- uint32_t measurement_uid; //Unique ID for the measurement
- uint32_t scan_counter; //Current acquisition number in the measurement
- uint32_t acquisition_time_stamp; //Acquisition clock
- uint32_t physiology_time_stamp[3]; //Physiology time stamps, e.g. ecg, breating, etc.
- uint16_t number_of_samples; //Number of samples acquired
- uint16_t available_channels; //Available coils
- uint16_t active_channels; //Active coils on current acquisiton
- uint64_t channel_mask[4]; //Mask to indicate which channels are active. Support for 256 channels
- uint16_t discard_pre; //Samples to be discarded at the beginning of acquisition
- uint16_t discard_post; //Samples to be discarded at the end of acquisition
- uint16_t center_sample; //Sample at the center of k-space
- uint16_t encoding_space_ref; //Reference to an encoding space, typically only one per acquisition
- float sample_time_us; //Time between samples in micro seconds, sampling BW
- float position[3]; //Three-dimensional spatial offsets from isocenter
- float quarternion[4]; //Angulation of acquisition
- float patient_table_position[3]; //Patient table off-center
- EncodingCounters idx; //Encoding loop counters, see above
- uint32_t user_int[8]; //Free user parameters
- float user_float[8]; //Free user parameters
-};
+ public:
+ Acquisition()
+ : traj_(0)
+ , data_(0)
+ {
+ memset(head_,0,sizeof(AcquisitionHeader));
+ head_.version = ISMRMRD_VERSION;
+ }
+
+ ~Acquisition() {
+ if (traj_) delete [] traj_;
+ if (data_) delete [] data_;
+ }
+
+ AcquisitionHeader head_; //Header, see above
+
+ float* traj_; //Trajectory, elements = head_.trajectory_dimensions*head_.number_of_samples
+ // [kx,ky,kx,ky.....] (for head_.trajectory_dimensions = 2)
+ // [kx,ky,kz,kx,ky,kz,.....] (for head_.trajectory_dimensions = 3)
+
+ float* data_; //Actual data, elements = head_.number_of_samples*head_.active_channels*2
+ // [re,im,re,im,.....,re,im,re,im,.....,re,im,re,im,.....]
+ // ---channel 1-------channel 2---------channel 3-----
+ };
} //End of ISMRMRD namespace
diff --git a/ismrmrd_export.h b/ismrmrd_export.h
new file mode 100644
index 0000000..57d57bc
--- /dev/null
+++ b/ismrmrd_export.h
@@ -0,0 +1,14 @@
+#ifndef ISMRMRD_EXPORT_H_
+#define ISMRMRD_EXPORT_H_
+
+#if defined (WIN32)
+#if defined (ismrmrd_EXPORTS)
+#define EXPORTISMRMRD __declspec(dllexport)
+#else
+#define EXPORTISMRMRD __declspec(dllimport)
+#endif
+#else
+#define EXPORTISMRMRD
+#endif
+
+#endif /* ISMRMRD_EXPORT_H_ */
diff --git a/ismrmrd_hdf5.cpp b/ismrmrd_hdf5.cpp
new file mode 100644
index 0000000..a88ab25
--- /dev/null
+++ b/ismrmrd_hdf5.cpp
@@ -0,0 +1,118 @@
+#include "ismrmrd_hdf5.h"
+
+#include <H5Cpp.h>
+
+#ifndef H5_NO_NAMESPACE
+using namespace H5;
+#endif
+
+#include <boost/algorithm/string.hpp>
+
+
+namespace ISMRMRD
+{
+
+ struct H5Acquisition
+ {
+ AcquisitionHeader head;
+ hvl_t traj;
+ hvl_t data;
+ };
+
+
+template <class T> boost::shared_ptr<CompType> getHDF5CompositeType();
+template <class T> boost::shared_ptr<DataType> getHDF5ArrayType(int LENGTH);
+
+template <> boost::shared_ptr<DataType> getHDF5ArrayType<float>(int LENGTH)
+{
+ std::vector<hsize_t> dims(1,LENGTH);
+ //hid_t array_tid = H5Tarray_create(H5T_NATIVE_FLOAT, 1, &dims[0]);
+ boost::shared_ptr<DataType> ret(new ArrayType(PredType::NATIVE_FLOAT, 1, &dims[0]));
+ return ret;
+}
+
+template <> boost::shared_ptr<DataType> getHDF5ArrayType<ACE_UINT16>(int LENGTH)
+{
+ std::vector<hsize_t> dims(1,LENGTH);
+ //hid_t array_tid = H5Tarray_create(H5T_NATIVE_USHORT, 1, &dims[0]);
+ //boost::shared_ptr<DataType> ret(new DataType(array_tid));
+ boost::shared_ptr<DataType> ret(new ArrayType(PredType::NATIVE_USHORT, 1, &dims[0]));
+ return ret;
+}
+
+template <> boost::shared_ptr<CompType> getHDF5CompositeType<LoopCounters>()
+{
+ boost::shared_ptr<CompType> ret;
+
+ try {
+ ret = boost::shared_ptr<CompType>(new CompType(sizeof(LoopCounters)));
+
+ ret->insertMember( "line", HOFFSET(LoopCounters,line), PredType::NATIVE_USHORT);
+ ret->insertMember( "acquisition", HOFFSET(LoopCounters,acquisition), PredType::NATIVE_USHORT);
+ ret->insertMember( "slice", HOFFSET(LoopCounters,slice), PredType::NATIVE_USHORT);
+ ret->insertMember( "partition", HOFFSET(LoopCounters,partition), PredType::NATIVE_USHORT);
+ ret->insertMember( "echo", HOFFSET(LoopCounters,echo), PredType::NATIVE_USHORT);
+ ret->insertMember( "phase", HOFFSET(LoopCounters,phase), PredType::NATIVE_USHORT);
+ ret->insertMember( "repetition", HOFFSET(LoopCounters,repetition), PredType::NATIVE_USHORT);
+ ret->insertMember( "set", HOFFSET(LoopCounters,set), PredType::NATIVE_USHORT);
+ ret->insertMember( "segment", HOFFSET(LoopCounters,segment), PredType::NATIVE_USHORT);
+ ret->insertMember( "channel", HOFFSET(LoopCounters,channel), PredType::NATIVE_USHORT);
+ } catch ( ... ) {
+ std::cout << "Exception caught while creating HDF5 compound datatype for LoopCounter" << std::endl;
+ }
+ return ret;
+}
+
+template <> boost::shared_ptr<CompType> getHDF5CompositeType<GadgetMessageAcquisition>()
+{
+ boost::shared_ptr<CompType> ret(new CompType(sizeof(GadgetMessageAcquisition)));
+ ret->insertMember( "flags", HOFFSET(GadgetMessageAcquisition,flags), PredType::NATIVE_UINT);
+ ret->insertMember( "meas_uid", HOFFSET(GadgetMessageAcquisition,meas_uid), PredType::NATIVE_UINT);
+ ret->insertMember( "scan_counter", HOFFSET(GadgetMessageAcquisition, scan_counter), PredType::NATIVE_UINT);
+ ret->insertMember( "time_stamp", HOFFSET(GadgetMessageAcquisition, time_stamp), PredType::NATIVE_UINT);
+ ret->insertMember( "pmu_time_stamp", HOFFSET(GadgetMessageAcquisition, pmu_time_stamp), PredType::NATIVE_UINT);
+ ret->insertMember( "samples", HOFFSET(GadgetMessageAcquisition, samples), PredType::NATIVE_USHORT);
+ ret->insertMember( "channels", HOFFSET(GadgetMessageAcquisition, channels), PredType::NATIVE_USHORT);
+ ret->insertMember( "centre_column", HOFFSET(GadgetMessageAcquisition, centre_column), PredType::NATIVE_USHORT);
+
+ boost::shared_ptr<DataType> position_type = getHDF5ArrayType<float>(3);
+ boost::shared_ptr<DataType> quarterion_type = getHDF5ArrayType<float>(4);
+ boost::shared_ptr<CompType> loopcounters_type = getHDF5CompositeType<LoopCounters>();
+
+ ret->insertMember( "position", HOFFSET(GadgetMessageAcquisition, position), *position_type);
+ ret->insertMember( "quarternion", HOFFSET(GadgetMessageAcquisition, quarternion), *quarterion_type);
+ ret->insertMember( "table_position", HOFFSET(GadgetMessageAcquisition, table_position), PredType::NATIVE_FLOAT);
+ ret->insertMember( "idx", HOFFSET(GadgetMessageAcquisition, idx), *loopcounters_type);
+ ret->insertMember( "min_idx", HOFFSET(GadgetMessageAcquisition, min_idx), *loopcounters_type);
+ ret->insertMember( "max_idx", HOFFSET(GadgetMessageAcquisition, max_idx), *loopcounters_type);
+
+ return ret;
+}
+
+
+ int H5AppendAcquisition(const Acquisition& a, const char* filename, const char* varname);
+ {
+
+ H5Acquisition tmp;
+ tmp.head = a.head_;
+
+ tmp.traj.len = a.head_.trajectory_dimensions*a.head_.number_of_samples;
+ tmp.traj.p = (void*) a.traj_;
+
+ tmp.data.len = a.head_.number_of_samples*a.head_.active_channels*2;
+ tmp.data.p = (void*) a.data_;
+
+ boost::shared_ptr<DataType> structdatatype = getHDF5CompositeType<STRUCT>();
+ boost::shared_ptr<DataType> vdatatype = getHDF5Type<DATATYPE>();
+ vdatatype = boost::shared_ptr<DataType>(new DataType(H5Tvlen_create (vdatatype->getId())));
+
+ CompType* ct = new CompType(sizeof(local_hdf5_append_struct<STRUCT>));
+ ct->insertMember( "h", HOFFSET(local_hdf5_append_struct<STRUCT>,h), *structdatatype);
+ ct->insertMember( "d", HOFFSET(local_hdf5_append_struct<STRUCT>,d), *vdatatype);
+
+ boost::shared_ptr<DataType> datatype(ct);
+
+
+ return hdf5_append_struct(&tmp, datatype, filename, varname);
+}
+} //End of ISMRMRD namespace
diff --git a/ismrmrd_hdf5.h b/ismrmrd_hdf5.h
new file mode 100644
index 0000000..a06cef2
--- /dev/null
+++ b/ismrmrd_hdf5.h
@@ -0,0 +1,21 @@
+#prama once
+#ifndef ISMRMRD_HDF5_H
+#define ISMRMRD_HDF5_H
+
+#include "ismrmrd_export.h"
+#include "ismrmrd.h"
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace ISMRMRD
+{
+
+ EXPORTISMRMRD int H5AppendAcquisition(Acquisition* a, const char* filename, const char* varname);
+ EXPORTISMRMRD boost::shared_ptr<Acquisition> H5ReadAcquisition(const char* filename, const char* varname, unsigned long index = 0);
+
+
+
+} //end of ISMRMRD namespace
+
+#endif //ISMRMRD_HDF5_H
diff --git a/schema/ismrmrd.xsd b/schema/ismrmrd.xsd
index f7bf784..da4f419 100644
--- a/schema/ismrmrd.xsd
+++ b/schema/ismrmrd.xsd
@@ -18,6 +18,7 @@ elementFormDefault="qualified">
<xs:element name="reconSpace" type="encodingSpaceType" minOccurs="1" maxOccurs="1"/>
<xs:element name="encodingLimits" type="encodingLimitsType" minOccurs="1" maxOccurs="1"/>
<xs:element name="trajectory" type="trajectoryType" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="trajectoryDescription" type="trajectoryDescriptionType" minOccurs="0" maxOccurs="1" />
</xs:all>
</xs:complexType>
</xs:element>
@@ -42,7 +43,7 @@ elementFormDefault="qualified">
<xs:complexType name="experimentalConditionsType">
<xs:all>
- <xs:element name="H1resonanceFrequencyHz" type="xs:long"/>
+ <xs:element name="H1resonanceFrequency_Hz" type="xs:long"/>
</xs:all>
</xs:complexType>
@@ -111,6 +112,15 @@ elementFormDefault="qualified">
</xs:restriction>
</xs:simpleType>
+ <xs:complexType name="trajectoryDescriptionType">
+ <xs:sequence>
+ <xs:element name="identifier" type="xs:string" minOccurs="1" maxOccurs="1" />
+ <xs:element name="userParameterLong" type="userParameterLongType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="userParameterDouble" type="userParameterDoubleType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="comment" type="xs:string" minOccurs="0" maxOccurs="1" />
+ </xs:sequence>
+ </xs:complexType>
+
<xs:complexType name="userParameterLongType">
<xs:all>
<xs:element name="name" type="xs:string"/>
@@ -124,5 +134,4 @@ elementFormDefault="qualified">
<xs:element name="value" type="xs:double"/>
</xs:all>
</xs:complexType>
-
</xs:schema>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ismrmrd.git
More information about the debian-science-commits
mailing list