[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