[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