[ismrmrd] 06/281: More 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 e5f31349ddfd596787051216eaaf156db7c4e801
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date:   Mon Jul 30 16:16:47 2012 -0400

    More work on HDF5 interface
---
 ismrmrd.h                |  78 +++++++++++++--
 ismrmrd_hdf5.cpp         | 241 ++++++++++++++++++++++++++---------------------
 ismrmrd_hdf5.h           |  36 ++++++-
 ismrmrd_hdf5_datatypes.h |   6 --
 4 files changed, 236 insertions(+), 125 deletions(-)

diff --git a/ismrmrd.h b/ismrmrd.h
index 4d06a69..04aaddf 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -25,20 +25,72 @@ typedef unsigned __int64 uint64_t;
 #include <stdio.h>
 #include <string.h>
 
-#pragma pack(4) //Use 4 byte alignment
+#pragma pack(push, 4) //Use 4 byte alignment
 
 #define ISMRMRD_VERSION 1
 
 namespace ISMRMRD
 {
-  
+
+  class FlagBit
+  {
+
+  public:
+	  FlagBit(unsigned short b)
+	  	  : bitmask_(0)
+	  {
+		  if (b > 0) {
+			  bitmask_ = 1;
+			  bitmask_ = (bitmask_ << (b-1));
+		  }
+	  }
+
+	  bool isSet(uint64_t& m) {
+		  return ((m & bitmask_)>0);
+	  }
+
+	  uint64_t bitmask_;
+
+  };
+
   /* FLAGS */
-  //FIRST_SCAN_ SLICE,PARTITIONS, ETC
-  //LAST_SCAN
-  //Noise scan
-  //reference data (parallel imaging)
-  //Navigation data
-  //REVERSE
+  enum {
+	  /* Looping indicators */
+	  FIRST_IN_ENCODE_STEP1                	= 1,
+	  LAST_IN_ENCODE_STEP1    				= 2,
+	  FIRST_IN_ENCODE_STEP2   				= 3,
+	  LAST_IN_ENCODE_STEP2    				= 4,
+	  FIRST_IN_AVERAGE        				= 5,
+	  LAST_IN_AVERAGE         				= 6,
+	  FIRST_IN_SLICE          				= 7,
+	  LAST_IN_SLICE           				= 8,
+	  FIRST_IN_CONTRAST       				= 9,
+	  LAST_IN_CONTRAST        				= 10,
+	  FIRST_IN_PHASE          				= 11,
+	  LAST_IN_PHASE           				= 12,
+	  FIRST_IN_REPETITION     				= 13,
+	  LAST_IN_REPETITION      				= 14,
+	  FIRST_IN_SET            				= 15,
+	  LAST_IN_SET             				= 16,
+	  FIRST_IN_SEGMENT        				= 17,
+	  LAST_IN_SEGMENT         				= 18,
+
+	  IS_NOISE_MEASUREMENT                	= 19,
+	  IS_PARALLEL_CALIBRATION             	= 20,
+	  IS_PARALLEL_CALIBRATION_AND_IMAGING 	= 21,
+	  IS_REVERSE              				= 22,
+	  IS_NAVIGATION_DATA      				= 23,
+
+	  USER1                   				= 57,
+	  USER2                   				= 58,
+	  USER3                   				= 59,
+	  USER4                   				= 60,
+	  USER5                   				= 61,
+	  USER6                   				= 62,
+	  USER7                   				= 63,
+	  USER8                   				= 64
+  };
+
 
   /**
      Struct used for keeping track of typical loop counters in MR experiment.
@@ -103,6 +155,14 @@ namespace ISMRMRD
      if (data_) delete [] data_;
    }
 
+   bool isFlagSet(FlagBit f) {
+	   return f.isSet(head_.flags);
+   }
+
+   void setFlag(FlagBit f) {
+	   head_.flags |= f.bitmask_;
+   }
+
    AcquisitionHeader head_; //Header, see above
    
    float* traj_;            //Trajectory, elements = head_.trajectory_dimensions*head_.number_of_samples
@@ -116,4 +176,6 @@ namespace ISMRMRD
 
 } //End of ISMRMRD namespace
 
+#pragma pack(pop) //Restore old alignmen
+
 #endif //ISMRMRD_H
diff --git a/ismrmrd_hdf5.cpp b/ismrmrd_hdf5.cpp
index e0fc8d6..a76b826 100644
--- a/ismrmrd_hdf5.cpp
+++ b/ismrmrd_hdf5.cpp
@@ -12,7 +12,6 @@ namespace ISMRMRD
 int IsmrmrdDataset::openHDF5File()
 {
 
-	std::cout << "Opening dataset..." << std::endl;
 	if (file_exists_) {
 		try {
 			if (!H5File::isHdf5(filename_.c_str())) {
@@ -33,139 +32,167 @@ int IsmrmrdDataset::openHDF5File()
 			return -1;
 		}
 		file_open_ = true;
+		file_exists_ = true;
+	} else {
+		std::cerr << "Unable to find HDF5 file (" << filename_ << "), and file cannot be created." << std::endl;
+		return -1;
 	}
 
 	return 0;
 }
 
 
+bool IsmrmrdDataset::linkExists(const char* name)
+{
+	if (!file_open_) {
+		std::cerr << "IsmrmrdDataset::linkExists: file not open." << std::endl;
+		return -1;
+	}
+	std::vector<std::string> name_elements;
+	std::string splitstr("/");
+	std::string namestr(name);
+	boost::split(name_elements, namestr, boost::is_any_of(splitstr));
+	std::string current_path("");
+	for (unsigned int i = 0; i < name_elements.size(); i++) {
+		if (name_elements[i].size() > 0) {
+			current_path = current_path + std::string("/") + name_elements[i];
+			if (!H5Lexists(file_->getId(), current_path.c_str(), H5P_DEFAULT )) {
+				return false;
+			}
+		}
+	}
+	return true;
+}
 
+int IsmrmrdDataset::createGroupForDataset(const char* name)
+{
+	if (!file_open_) {
+		std::cerr << "IsmrmrdDataset::linkExists: file not open." << std::endl;
+		return -1;
+	}
 
-  int H5AppendAcquisition(const Acquisition& a, const char* filename, const char* varname)
-  {
-	   /*
+	std::vector<std::string> name_elements;
+	std::string splitstr("/");
+	std::string namestr(name);
+	boost::split(name_elements, namestr, boost::is_any_of(splitstr));
+	std::string current_path("");
+	for (unsigned int i = 0; i < name_elements.size(); i++) {
+		if (name_elements[i].size() > 0) {
+			current_path = current_path + std::string("/") + name_elements[i];
+			if (!H5Lexists(file_->getId(), current_path.c_str(), H5P_DEFAULT )) {
+				file_->createGroup( current_path.c_str());
+			}
+		}
+	}
+	return 0;
+}
 
-    H5Acquisition tmp;
-    tmp.head = a.head_;
+int IsmrmrdDataset::appendAcquisition(Acquisition* a)
+{
+	std::vector<hsize_t> dims(2,1);
+	std::vector<hsize_t> max_dims(2,1);max_dims[0] = H5S_UNLIMITED;
 
-    tmp.traj.len = a.head_.trajectory_dimensions*a.head_.number_of_samples;
-    tmp.traj.p = (void*) a.traj_;
+	int rank = 2;
+	std::vector<hsize_t> ddims = dims;
+	std::vector<hsize_t> offset(rank,0);
 
-    tmp.data.len = a.head_.number_of_samples*a.head_.active_channels*2;
-    tmp.data.p = (void*) a.data_;
+	bool new_dataset = false;
 
-    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())));
+	if (!dataset_open_) {
+		try {
+			boost::shared_ptr<DataType> datatype = getIsmrmrdHDF5Type<AcquisitionHeader_with_data>();
+			if (!linkExists(data_path_.c_str())) {
+				DataSpace mspace1( dims.size(), &dims[0], &max_dims[0]);
+				DSetCreatPropList cparms;
+				cparms.setChunk( dims.size(), &dims[0] );
+				dataset_ = boost::shared_ptr<DataSet>(new DataSet(file_->createDataSet( data_path_.c_str(), *datatype, mspace1, cparms)));
+				new_dataset = true;
+			} else {
+				dataset_ = boost::shared_ptr<DataSet>(new DataSet(file_->openDataSet(data_path_.c_str())));
+				DataType mtype = dataset_->getDataType();
+				if (!(mtype == (*datatype))) {
+					std::cout << "Attempting to append data to HDF5 dataset with the wrong type" << std::endl;
+					return -1;
+				}
 
-	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);
+			}
+			dataset_open_ = true;
+		} catch( Exception& e ) {
+			std::cout << "Exception caught while opening (creating) HDF5 dataset" << std::endl;
+			std::cout << e.getDetailMsg() << std::endl;
+			return -1;
+		}
+	}
 
-	boost::shared_ptr<DataType> datatype(ct);
+	try {
+		boost::shared_ptr<DataType> datatype = getIsmrmrdHDF5Type<AcquisitionHeader_with_data>();
+		AcquisitionHeader_with_data tmp;
+		tmp.head = a->head_;
+		tmp.traj.len = tmp.head.trajectory_dimensions*tmp.head.number_of_samples;
+		tmp.traj.p = static_cast<void*>(a->traj_);
+
+		tmp.data.len = tmp.head.active_channels*tmp.head.number_of_samples;
+		tmp.data.p = static_cast<void*>(a->data_);
+
+		DataSpace mspace1 = dataset_->getSpace();
+		rank = mspace1.getSimpleExtentNdims();
+		if (rank != 2) {
+			std::cerr << "Wrong rank (" << rank << ") found in HDF5 dataset" << std::endl;
+			return -1;
+		}
 
+		if (!new_dataset) {
+			mspace1.getSimpleExtentDims(&ddims[0], NULL);
+			offset[0] = ddims[0];
+			ddims[0]++;
 
-	return hdf5_append_struct(&tmp, datatype, filename, varname);
-	*/
-    return 0;
-}
+			dataset_->extend(&ddims[0]);
+		}
+		DataSpace fspace2 = dataset_->getSpace();
+		fspace2.selectHyperslab( H5S_SELECT_SET, &dims[0], &offset[0] );
 
-  /*
-template <class T> boost::shared_ptr<CompType> getHDF5CompositeType();
-template <class T> boost::shared_ptr<DataType> getHDF5ArrayType(int LENGTH);
+		DataSpace mspace2( rank, &dims[0] );
+		dataset_->write( &tmp, *datatype, mspace2, fspace2 );
 
-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;
-}
+	} catch( Exception& e ) {
+		std::cout << "Exception caught while writing HDF5 data" << std::endl;
+		std::cout << e.getDetailMsg() << std::endl;
+		return -1;
+	}
 
-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;
+	return 0;
 }
 
-template <> boost::shared_ptr<CompType> getHDF5CompositeType<LoopCounters>()
-{
-	boost::shared_ptr<CompType> ret;
+int IsmrmrdDataset::writeHeader(std::string& xml) {
+	std::vector<hsize_t> dims(1,1);
+	std::vector<hsize_t> max_dims(1,1);
 
+	boost::shared_ptr<DataSet> xml_dataset;
+	hid_t datatype = H5Tcopy (H5T_C_S1);
+	H5Tset_size (datatype, H5T_VARIABLE);
 	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;
+		if (!linkExists(xml_header_path_.c_str())) {
+			DataSpace mspace1( dims.size(), &dims[0], &max_dims[0]);
+			xml_dataset = boost::shared_ptr<DataSet>(new DataSet(file_->createDataSet( xml_header_path_.c_str(), datatype, mspace1)));
+		} else {
+			xml_dataset = boost::shared_ptr<DataSet>(new DataSet(file_->openDataSet(xml_header_path_.c_str())));
+			DataType mtype = dataset_->getDataType();
+			if (!(mtype == (datatype))) {
+				std::cout << "Attempting to append XML data to HDF5 dataset with the wrong type" << std::endl;
+				return -1;
+			}
+		}
+		DataSpace mspace1 = xml_dataset->getSpace();
+		xml_dataset->write( xml.c_str(), datatype, mspace1);
+	} catch( Exception& e ) {
+			std::cout << "Exception caught while writing XML Header to HDF5 file" << std::endl;
+			std::cout << e.getDetailMsg() << std::endl;
+			return -1;
 	}
-	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);
+ return 0;
 }
-*/
 
 } //End of ISMRMRD namespace
diff --git a/ismrmrd_hdf5.h b/ismrmrd_hdf5.h
index c6be388..309ec40 100644
--- a/ismrmrd_hdf5.h
+++ b/ismrmrd_hdf5.h
@@ -26,33 +26,61 @@ public:
 	: filename_(filename)
 	, groupname_(groupname)
 	, file_open_(false)
+	, dataset_open_(false)
 	, create_file_if_needed_(create_file_if_needed)
 	{
 		std::ifstream ifile(filename_.c_str());
 		file_exists_ = ifile;
 
 		if (openHDF5File() < 0) {
-			std::cerr << "Error opening HDF file" << std::endl;
+			std::cerr << "IsmrmrdDataset: Error opening HDF file." << std::endl;
 		}
+
+		if (!linkExists(groupname_.c_str())) {
+			if (createGroupForDataset(groupname_.c_str()) < 0) {
+				std::cerr << "IsmrmrdDataset: Error create HDF5 group." << std::endl;
+			}
+		}
+
+		xml_header_path_ = groupname_ + std::string("/xml");
+		data_path_ = groupname_ + std::string("/data");
  	}
 
-	bool fileExists() {
-		return file_exists_;
-	}
+	int appendAcquisition(Acquisition* a);
+	int writeHeader(std::string& xml);
 
 protected:
 	int openHDF5File();
+	bool linkExists(const char* name);
+	int createGroupForDataset(const char* name);
+
+	bool fileExists() {
+		return file_exists_;
+	}
 
 	std::string filename_;
 	std::string groupname_;
+	std::string xml_header_path_;
+	std::string data_path_;
+
 	bool file_open_;
 	bool file_exists_;
 	bool create_file_if_needed_;
+	bool dataset_open_;
 
 	boost::shared_ptr<H5File> file_;
+	boost::shared_ptr<DataSet> dataset_;
 
 };
 
+
+struct AcquisitionHeader_with_data
+{
+	AcquisitionHeader head;
+	hvl_t traj;
+	hvl_t data;
+};
+
 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);
 
diff --git a/ismrmrd_hdf5_datatypes.h b/ismrmrd_hdf5_datatypes.h
index 2b8be4f..6357e59 100644
--- a/ismrmrd_hdf5_datatypes.h
+++ b/ismrmrd_hdf5_datatypes.h
@@ -95,12 +95,6 @@ template <> boost::shared_ptr<DataType> getIsmrmrdHDF5Type<AcquisitionHeader>()
 
 }
 
-struct AcquisitionHeader_with_data
-{
-	AcquisitionHeader head;
-	hvl_t traj;
-	hvl_t data;
-};
 
 struct complex_t
 {

-- 
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