[ismrmrd] 92/281: Encapsulation of Acquisition and Image

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:01:01 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 e3d9db2844743ed67685e83c2ce61ff863ef846c
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date:   Thu Feb 21 14:20:39 2013 -0500

    Encapsulation of Acquisition and Image
---
 examples/c++/test_create_dataset.cpp |  23 +-
 examples/c++/test_recon_dataset.cpp  |   4 +-
 ismrmrd.h                            | 808 ++++++++++++++++++++++++++++++-----
 ismrmrd_hdf5.cpp                     |  33 +-
 tests/c++/t_image.cpp                |   6 +-
 5 files changed, 742 insertions(+), 132 deletions(-)

diff --git a/examples/c++/test_create_dataset.cpp b/examples/c++/test_create_dataset.cpp
index 983632f..c684245 100644
--- a/examples/c++/test_create_dataset.cpp
+++ b/examples/c++/test_create_dataset.cpp
@@ -110,13 +110,10 @@ int main(int argc, char** argv)
 	//Let's append the data to the file
 	ISMRMRD::Acquisition acq;
 
-	acq.data_.resize(readout*2);
-/*	if (!acq.data_) {
-		std::cout << "Error allocating memory for the acquisition" << std::endl;
-	}
-*/
 	for (unsigned int i = 0; i < phase_encoding_lines; i++) {
-		acq.head_.flags = 0;
+		acq.setFlags(0);
+		//acq.head_.flags = 0;
+
 		//Set some flags
 		if (i == 0) {
 			acq.setFlag(ISMRMRD::FlagBit(ISMRMRD::ACQ_FIRST_IN_SLICE));
@@ -124,13 +121,13 @@ int main(int argc, char** argv)
 		if (i == (phase_encoding_lines-1)) {
 			acq.setFlag(ISMRMRD::FlagBit(ISMRMRD::ACQ_LAST_IN_SLICE));
 		}
-		acq.head_.idx.kspace_encode_step_1 = i;
-		acq.head_.active_channels = 1;
-		acq.head_.available_channels = 1;
-		acq.head_.number_of_samples = readout;
-		acq.head_.center_sample = (readout>>1);
-		acq.head_.sample_time_us = 5.0;
-		memcpy(&acq.data_[0],&img_test->data_[i*readout],sizeof(float)*readout*2);
+		acq.getIdx().kspace_encode_step_1 = i;
+		acq.setActiveChannels(1);
+		acq.setAvailableChannels(1);
+		acq.setNumberOfSamples(readout);
+		acq.setCenterSample(readout>>1);
+		acq.setSampleTimeUs(5.0);
+		memcpy(&acq[0],&img_test->data_[i*readout],sizeof(float)*readout*2);
 		d.appendAcquisition(&acq);
 	}
 
diff --git a/examples/c++/test_recon_dataset.cpp b/examples/c++/test_recon_dataset.cpp
index 2067691..390e70e 100644
--- a/examples/c++/test_recon_dataset.cpp
+++ b/examples/c++/test_recon_dataset.cpp
@@ -103,8 +103,8 @@ int main(int argc, char** argv)
 
 		//Copy data, we should probably be more careful here and do more tests....
 		//We are not considering multiple channels here.
-		unsigned int offset = acq->head_.idx.kspace_encode_step_1*buffer.dimensions_[0];
-		memcpy(&buffer[offset],&acq->data_[0],sizeof(float)*2*buffer.dimensions_[0]);
+		unsigned int offset = acq->getIdx().kspace_encode_step_1*buffer.dimensions_[0];
+		memcpy(&buffer[offset],&acq->getData()[0],sizeof(float)*2*buffer.dimensions_[0]);
 	}
 
 	//Let's FFT the k-space to image
diff --git a/ismrmrd.h b/ismrmrd.h
index 49a1e18..86e3c72 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -32,12 +32,19 @@ typedef unsigned __int64 uint64_t;
 #include <iostream>
 #include <vector>
 #include <valarray>
+#include <complex>
 #include <assert.h>
 #endif
 
 #pragma pack(push, 2) //Use 2 byte alignment
 
 #define ISMRMRD_VERSION 1
+#define ISMRMRD_POSITION_LENGTH   3
+#define ISMRMRD_QUATERNION_LENGTH 4
+#define ISMRMRD_USER_INTS         8
+#define ISMRMRD_USER_FLOATS       8
+#define ISMRMRD_PHYS_STAMPS       8
+#define ISMRMRD_CHANNEL_MASKS     16
 
 #ifdef __cplusplus
 namespace ISMRMRD
@@ -109,16 +116,16 @@ enum AcquisitionFlags {
 
  */
 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 */
+	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[ISMRMRD_USER_INTS];  /**< Free user parameters */
 };
 
 /**
@@ -126,28 +133,30 @@ struct EncodingCounters {
  */
 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              quaternion[4];                  /**< Angulation of acquisition */
-	float              patient_table_position[3];      /**< Patient table off-center */
-	EncodingCounters   idx;                            /**< Encoding loop counters, see above */
-	int32_t            user_int[8];                    /**< Free user parameters */
-	float              user_float[8];                  /**< Free user parameters */
+	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[ISMRMRD_PHYS_STAMPS];       /**< 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[ISMRMRD_CHANNEL_MASKS];              /**< 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[ISMRMRD_POSITION_LENGTH];                /**< Three-dimensional spatial offsets from isocenter */
+	float              quaternion[ISMRMRD_QUATERNION_LENGTH];            /**< Angulation of acquisition */
+	float              patient_table_position[ISMRMRD_POSITION_LENGTH];  /**< Patient table off-center */
+	EncodingCounters   idx;                                              /**< Encoding loop counters, see above */
+	int32_t            user_int[ISMRMRD_USER_INTS];                      /**< Free user parameters */
+	float              user_float[ISMRMRD_USER_FLOATS];                  /**< Free user parameters */
+
+
 };
 
 enum ImageDataType
@@ -187,29 +196,29 @@ enum ImageFlags {
  */
 struct ImageHeader
 {
-	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  */
-	uint16_t           	matrix_size[3];                 /**< Pixels in the 3 spatial dimensions */
-	float              	field_of_view[3];               /**< Size (in mm) of the 3 spatial dimensions */
-	uint16_t           	channels;                       /**< Number of receive channels */
-	float              	position[3];                    /**< Three-dimensional spatial offsets from isocenter */
-	float              	quaternion[4];                  /**< Angulation of acquisition */
-	float              	patient_table_position[3];      /**< Patient table off-center */
-	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 */
-	uint32_t           	acquisition_time_stamp;         /**< Acquisition clock */
-	uint32_t           	physiology_time_stamp[3];       /**< Physiology time stamps, e.g. ecg, breating, etc. */
-	uint16_t           	image_data_type;                /**< e.g. unsigned short, float, complex float, etc. */
-	uint16_t           	image_type;                     /**< e.g. magnitude, phase, complex, real, imag, etc. */
-	uint16_t           	image_index;					/**< e.g. image number in series of images  */
-	uint16_t			image_series_index;             /**< e.g. series number */
-	int32_t            	user_int[8];                    /**< Free user parameters */
-	float              	user_float[8];                  /**< Free user parameters */
+	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  */
+	uint16_t           	matrix_size[3];                                  /**< Pixels in the 3 spatial dimensions */
+	float              	field_of_view[3];                                /**< Size (in mm) of the 3 spatial dimensions */
+	uint16_t           	channels;                                        /**< Number of receive channels */
+	float              	position[ISMRMRD_POSITION_LENGTH];               /**< Three-dimensional spatial offsets from isocenter */
+	float              	quaternion[ISMRMRD_QUATERNION_LENGTH];           /**< Angulation of acquisition */
+	float              	patient_table_position[ISMRMRD_POSITION_LENGTH]; /**< Patient table off-center */
+	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 */
+	uint32_t           	acquisition_time_stamp;                          /**< Acquisition clock */
+	uint32_t           	physiology_time_stamp[ISMRMRD_PHYS_STAMPS];      /**< Physiology time stamps, e.g. ecg, breating, etc. */
+	uint16_t           	image_data_type;                                 /**< e.g. unsigned short, float, complex float, etc. */
+	uint16_t           	image_type;                                      /**< e.g. magnitude, phase, complex, real, imag, etc. */
+	uint16_t           	image_index;					                 /**< e.g. image number in series of images  */
+	uint16_t			image_series_index;                              /**< e.g. series number */
+	int32_t            	user_int[ISMRMRD_USER_INTS];                     /**< Free user parameters */
+	float              	user_float[ISMRMRD_USER_FLOATS];                 /**< Free user parameters */
 };
 
 #ifdef __cplusplus
@@ -217,7 +226,7 @@ struct ImageHeader
  *  Container for generic array. This structure is used through the HDF5 file interaction.
  */
 template <typename T> class NDArrayContainer {
-    
+
 public:
 	NDArrayContainer() {}
 
@@ -267,7 +276,7 @@ public:
     T& operator[] (const size_t& p) {
         return data_[p];
     }
-    
+
     T operator[] (const size_t& p) const {
         return data_[p];
     }
@@ -275,11 +284,11 @@ public:
     void resize (const size_t& s) {
         data_.resize(s);
     }
-    
+
     void resize (const size_t& s, const T& t) {
         data_.resize(s,t);
     }
-    
+
 	bool is_consistent() const {
 		return (elements() == data_.size());
 	}
@@ -297,35 +306,30 @@ public:
  *   Container for an image (header and data)
  */
 template <typename T>
-class Image : public NDArrayContainer<T> {
-    
+class Image {
+
 public:
-	Image() :
-        NDArrayContainer<T>() {
+	Image(unsigned int matrix_size_x = 0,
+		  unsigned int matrix_size_y = 1,
+		  unsigned int matrix_size_z = 1,
+		  unsigned int channels      = 1)
+    {
 		memset(&head_,0,sizeof(ImageHeader));
 		head_.version = ISMRMRD_VERSION;
+        head_.matrix_size[0] = matrix_size_x;
+        head_.matrix_size[1] = matrix_size_y;
+        head_.matrix_size[2] = matrix_size_z;
+        head_.channels       = channels;
+        setSpecificDataType();
+        makeConsistent();
 	}
-    
-	Image (const std::vector<unsigned int>& dimensions, T* d) :
-        NDArrayContainer<T> (dimensions, d) {
-        head_.matrix_size[0] = dimensions[0];
-        head_.matrix_size[1] = dimensions[1];
-        head_.matrix_size[2] = dimensions[2];
-        head_.channels       = dimensions[3];
-	}
-    
-	Image (const std::vector<unsigned int>& dimensions, T t = T(0)) :
-        NDArrayContainer<T> (dimensions, t) {
-        head_.matrix_size[0] = dimensions[0];
-        head_.matrix_size[1] = dimensions[1];
-        head_.matrix_size[2] = dimensions[2];
-        head_.channels       = dimensions[3];
-	}
-    
+
+
     Image(const Image& a) {   // copy constructor
 		if (this != &a) {
             head_ = a.head_;
             this->data_ = a.data_;
+            makeConsistent();
 		}
 	}
 
@@ -333,6 +337,7 @@ public:
 		if (this != &a) {
             head_ = a.head_;
             this->data_ = a.data_;
+            makeConsistent();
 		}
 		return *this;
 	}
@@ -342,11 +347,11 @@ public:
 	bool isFlagSet(FlagBit& f) const {
 		return f.isSet(head_.flags);
 	}
-    
+
 	void setFlag(FlagBit& f) {
 		head_.flags |= f.bitmask_;
 	}
-    
+
 	size_t getNumberOfElements() const {
 		return head_.matrix_size[0]*
             head_.matrix_size[1]*
@@ -354,18 +359,336 @@ public:
             head_.channels;
 	}
 
+
+	uint32_t getAcquisitionTimeStamp() const {
+		return head_.acquisition_time_stamp;
+	}
+
+	void setAcquisitionTimeStamp(uint32_t acquisitionTimeStamp) {
+		head_.acquisition_time_stamp = acquisitionTimeStamp;
+	}
+
+	uint16_t getAverage() const {
+		return head_.average;
+	}
+
+	void setAverage(uint16_t average) {
+		this->head_.average = average;
+	}
+
+	uint16_t getChannels() const {
+		return head_.channels;
+	}
+
+	void setChannels(uint16_t channels) {
+		this->head_.channels = channels;
+	}
+
+	uint16_t getContrast() const {
+		return head_.contrast;
+	}
+
+	void setContrast(uint16_t contrast) {
+		this->head_.contrast = contrast;
+	}
+
+	float getFieldOfViewX() const {
+		return head_.field_of_view[0];
+	}
+
+	void setFieldOfViewX(float f) {
+		head_.field_of_view[0] = f;
+	}
+
+	float getFieldOfViewY() const {
+		return head_.field_of_view[1];
+	}
+
+	void setFieldOfViewY(float f) {
+		head_.field_of_view[1] = f;
+	}
+
+	float getFieldOfViewZ() const {
+		return head_.field_of_view[2];
+	}
+
+	void setFieldOfViewZ(float f) {
+		head_.field_of_view[2] = f;
+	}
+
+	uint64_t getFlags() const {
+		return head_.flags;
+	}
+
+	void setFlags(uint64_t flags) {
+		this->head_.flags = flags;
+	}
+
+	uint16_t getImageDataType() const {
+		return head_.image_data_type;
+	}
+
+	void setImageDataType(uint16_t imageDataType) {
+		head_.image_data_type = imageDataType;
+	}
+
+	uint16_t getImageIndex() const {
+		return head_.image_index;
+	}
+
+	void setImageIndex(uint16_t imageIndex) {
+		head_.image_index = imageIndex;
+	}
+
+	uint16_t getImageSeriesIndex() const {
+		return head_.image_series_index;
+	}
+
+	void setImageSeriesIndex(uint16_t imageSeriesIndex) {
+		head_.image_series_index = imageSeriesIndex;
+	}
+
+	uint16_t getImageType() const {
+		return head_.image_type;
+	}
+
+	void setImageType(uint16_t imageType) {
+		head_.image_type = imageType;
+	}
+
+	uint16_t getMatrixSizeX() const {
+		return head_.matrix_size[0];
+	}
+
+	void setMatrixSizeX(uint16_t s) {
+		head_.matrix_size[0] = s;
+		makeConsistent();
+	}
+
+	uint16_t getMatrixSizeY() const {
+		return head_.matrix_size[1];
+	}
+
+	void setMatrixSizeY(uint16_t s) {
+		head_.matrix_size[1] = s;
+		makeConsistent();
+	}
+
+	uint16_t getMatrixSizeZ() const {
+		return head_.matrix_size[2];
+	}
+
+	void setMatrixSizeZ(uint16_t s) {
+		head_.matrix_size[2] = s;
+		makeConsistent();
+	}
+
+
+	uint32_t getMeasurementUid() const {
+		return head_.measurement_uid;
+	}
+
+	void setMeasurementUid(uint32_t measurementUid) {
+		head_.measurement_uid = measurementUid;
+	}
+
+	const float getPatientTablePosition(unsigned int axis) const {
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			return head_.patient_table_position[axis];
+		}
+		return 0;
+	}
+
+	void setPatientTablePosition(unsigned int axis, float value) {
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			head_.patient_table_position[axis] = value;
+		}
+	}
+
+	const uint32_t getPhysiologyTimeStamp(unsigned int stamp_id) const {
+		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+			return head_.physiology_time_stamp[stamp_id];
+		}
+		return 0;
+	}
+
+	void setPhysiologyTimeStamp(unsigned int stamp_id, uint32_t value){
+		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+			head_.physiology_time_stamp[stamp_id] = value;
+		}
+	}
+
+	const float getPosition(unsigned int axis) const {
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			return head_.position[axis];
+		}
+		return 0;
+	}
+
+	void setPosition(unsigned int axis, float value){
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			head_.position[axis] = value;
+		}
+	}
+
+
+	const float getQuaternion(unsigned int index) const {
+		if (index < ISMRMRD_QUATERNION_LENGTH) {
+			return head_.quaternion[index];
+		}
+		return 0;
+	}
+
+	void setQuaternion(unsigned int index, float value) {
+		if (index < ISMRMRD_QUATERNION_LENGTH) {
+			head_.quaternion[index] = value;
+		}
+	}
+
+	uint16_t getPhase() const {
+		return head_.phase;
+	}
+
+	void setPhase(uint16_t phase) {
+		this->head_.phase = phase;
+	}
+
+
+	uint16_t getRepetition() const {
+		return head_.repetition;
+	}
+
+	void setRepetition(uint16_t repetition) {
+		this->head_.repetition = repetition;
+	}
+
+	uint16_t getSet() const {
+		return head_.set;
+	}
+
+	void setSet(uint16_t set) {
+		this->head_.set = set;
+	}
+
+	uint16_t getSlice() const {
+		return head_.slice;
+	}
+
+	void setSlice(uint16_t slice) {
+		this->head_.slice = slice;
+	}
+
+	const float getUserFloat(unsigned int index) const {
+		if (index < ISMRMRD_USER_FLOATS) {
+			return head_.user_float[index];
+		}
+		return 0.0f;
+	}
+
+	void setUserFloat(unsigned int index, float value) {
+		if (index < ISMRMRD_USER_FLOATS) {
+			head_.user_float[index] = value;
+		}
+	}
+
+	const int32_t getUserInt(unsigned int index) const {
+		if (index < ISMRMRD_USER_INTS) {
+			return head_.user_int[index];
+		}
+		return 0;
+	}
+
+	void setUserInt(unsigned int index, int32_t value) {
+		if (index < ISMRMRD_USER_INTS) {
+			head_.user_int[index] = value;
+		}
+	}
+
+	uint16_t getVersion() const {
+		return head_.version;
+	}
+
+	void setVersion(uint16_t version) {
+		this->head_.version = version;
+	}
+
+	const std::valarray<T>& getData() const {
+		return data_;
+	}
+
+	void setData(const std::valarray<T>& data) {
+		data_ = data;
+	}
+
+	const ImageHeader& getHead() const {
+		return head_;
+	}
+
+	void setHead(const ImageHeader& head) {
+		head_ = head;
+		makeConsistent();
+	}
+
+    T& operator[] (const size_t& p) {
+        return data_[p];
+    }
+
+    T operator[] (const size_t& p) const {
+        return data_[p];
+    }
+
+
+protected:
 	ImageHeader head_;     /**< ImageHeader as defined above */
-    static const unsigned short MAX_IMAGE_DIMS;
+	std::valarray<T> data_;
+	void makeConsistent() {
+		if (getNumberOfElements() != data_.size()) {
+			data_.resize(getNumberOfElements());
+		}
+	}
+
+	void setSpecificDataType();
 
 };
 
+template <> inline void Image<float>::setSpecificDataType() {
+	head_.image_data_type = DATA_FLOAT;
+}
+
+template <> inline void Image<double>::setSpecificDataType() {
+	head_.image_data_type = DATA_DOUBLE;
+}
+
+template <> inline void Image< std::complex<float> >::setSpecificDataType() {
+	head_.image_data_type = DATA_COMPLEX_FLOAT;
+}
+
+template <> inline void Image< std::complex<double> >::setSpecificDataType() {
+	head_.image_data_type = DATA_COMPLEX_DOUBLE;
+}
+
+template <> inline void Image< unsigned short >::setSpecificDataType() {
+	head_.image_data_type = DATA_UNSIGNED_SHORT;
+}
+
+
+
 /**
  * @brief Single acquisition
  */
-class Acquisition : public NDArrayContainer<float> {
+
+/* TODO:
+ *    - Move data and traj to protected
+ *    - Check data and traj sizes when assigning number of samples, active channels, traj dimensions
+ *    - Check active channels when assigning channel bits
+ *    - Assign channel bits when assiging number of channels
+ *    - Change Image to have encapsulation
+ *    - Make Image Data Type Consistent with field.
+ *    - Test, test, test.
+ */
+class Acquisition {
     
 public:
-    
 	Acquisition()
         : traj_(), data_() {
 		memset(&head_,0,sizeof(AcquisitionHeader));
@@ -373,35 +696,320 @@ public:
 	}
     
 	~Acquisition() {}
-    
-	bool isFlagSet(const FlagBit& f) const {
-		return f.isSet(head_.flags);
-	}
-    
-	void setFlag(const FlagBit& f) {
-		head_.flags |= f.bitmask_;
-	}
-    
+
 	Acquisition (const Acquisition& a) {   // copy constructor
 		if (this != &a) {
 			head_ = a.head_;
-            traj_ = a.traj_;
-            data_ = a.data_;
-            /* TODO: Consistency checks*/
+			data_.resize(a.data_.size());
+			memcpy(&data_[0],&a.data_[0],sizeof(float)*a.data_.size());
+			traj_.resize(a.traj_.size());
+			memcpy(&traj_[0],&a.traj_[0],sizeof(float)*a.traj_.size());
 		}
 	}
     
 	Acquisition& operator=(const Acquisition& a) {
 		if (this != &a) {
             head_ = a.head_;
-            traj_ = a.traj_;
-            data_ = a.data_;
+			data_.resize(a.data_.size());
+			memcpy(&data_[0],&a.data_[0],sizeof(float)*a.data_.size());
+			traj_.resize(a.traj_.size());
+			memcpy(&traj_[0],&a.traj_[0],sizeof(float)*a.traj_.size());
 		}
 		return *this;
 	}
 	
+	const AcquisitionHeader& getHead() {
+		return head_;
+	}
+
+	void setHead(const AcquisitionHeader& h) {
+		head_ = h;
+		makeConsistent();
+	}
+
+	bool isFlagSet(const FlagBit& f) const {
+		return f.isSet(head_.flags);
+	}
+
+	void setFlag(const FlagBit& f) {
+		head_.flags |= f.bitmask_;
+	}
+
+	uint32_t getAcquisitionTimeStamp() const {
+		return head_.acquisition_time_stamp;
+	}
+
+	void setAcquisitionTimeStamp(uint32_t acquisitionTimeStamp) {
+		head_.acquisition_time_stamp = acquisitionTimeStamp;
+	}
+
+	uint16_t getActiveChannels() const {
+		return head_.active_channels;
+	}
+
+	void setActiveChannels(uint16_t activeChannels) {
+		head_.active_channels = activeChannels;
+		makeConsistent();
+	}
+
+	uint16_t getAvailableChannels() const {
+		return head_.available_channels;
+	}
+
+	void setAvailableChannels(uint16_t availableChannels) {
+		head_.available_channels = availableChannels;
+	}
+
+	uint16_t getCenterSample() const {
+		return head_.center_sample;
+	}
+
+	void setCenterSample(uint16_t centerSample) {
+		head_.center_sample = centerSample;
+	}
+
+	bool isChannelActive(unsigned int channel_id) {
+		if (channel_id < 64*ISMRMRD_CHANNEL_MASKS) {
+			unsigned int mask_idx = channel_id>>6;
+			unsigned int mask_bit = channel_id-mask_idx*64;
+			return (head_.channel_mask[mask_idx] & (1 << mask_bit) > 0);
+		}
+		return false;
+	}
+
+	void setChannelActive(unsigned int channel_id) {
+		if (channel_id < 64*ISMRMRD_CHANNEL_MASKS) {
+			unsigned int mask_idx = channel_id>>6;
+			unsigned int mask_bit = channel_id-mask_idx*64;
+			head_.channel_mask[mask_idx] |= (1 << mask_bit);
+		}
+	}
+
+	unsigned int getActiveChannelBits() {
+		unsigned int bits = 0;
+		for (unsigned int i = 0; i < ISMRMRD_CHANNEL_MASKS*64; i++) {
+			if (isChannelActive(i)) {
+				bits++;
+			}
+		}
+		return bits;
+	}
+
+	uint16_t getDiscardPost() const {
+		return head_.discard_post;
+	}
+
+	void setDiscardPost(uint16_t discardPost) {
+		head_.discard_post = discardPost;
+	}
+
+	uint16_t getDiscardPre() const {
+		return head_.discard_pre;
+	}
+
+	void setDiscardPre(uint16_t discardPre) {
+		head_.discard_pre = discardPre;
+	}
+
+	uint16_t getEncodingSpaceRef() const {
+		return head_.encoding_space_ref;
+	}
+
+	void setEncodingSpaceRef(uint16_t encodingSpaceRef) {
+		head_.encoding_space_ref = encodingSpaceRef;
+	}
+
+	uint64_t getFlags() const {
+		return head_.flags;
+	}
+
+	void setFlags(uint64_t flags) {
+		this->head_.flags = flags;
+	}
+
+	EncodingCounters& getIdx() {
+		return head_.idx;
+	}
+
+	void setIdx(const EncodingCounters& idx) {
+		this->head_.idx = idx;
+	}
+
+	uint32_t getMeasurementUid() const {
+		return head_.measurement_uid;
+	}
+
+	void setMeasurementUid(uint32_t measurementUid) {
+		head_.measurement_uid = measurementUid;
+	}
+
+	uint16_t getNumberOfSamples() const {
+		return head_.number_of_samples;
+	}
+
+	void setNumberOfSamples(uint16_t numberOfSamples) {
+		head_.number_of_samples = numberOfSamples;
+		makeConsistent();
+	}
+
+	const float getPatientTablePosition(unsigned int axis) const {
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			return head_.patient_table_position[axis];
+		}
+		return 0;
+	}
+
+	void setPatientTablePosition(unsigned int axis, float value) {
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			head_.patient_table_position[axis] = value;
+		}
+	}
+
+	const uint32_t getPhysiologyTimeStamp(unsigned int stamp_id) const {
+		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+			return head_.physiology_time_stamp[stamp_id];
+		}
+		return 0;
+	}
+
+	void setPhysiologyTimeStamp(unsigned int stamp_id, uint32_t value){
+		if (stamp_id < ISMRMRD_PHYS_STAMPS) {
+			head_.physiology_time_stamp[stamp_id] = value;
+		}
+	}
+
+	const float getPosition(unsigned int axis) const {
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			return head_.position[axis];
+		}
+		return 0;
+	}
+
+	void setPosition(unsigned int axis, float value){
+		if (axis < ISMRMRD_POSITION_LENGTH) {
+			head_.position[axis] = value;
+		}
+	}
+
+
+	const float getQuaternion(unsigned int index) const {
+		if (index < ISMRMRD_QUATERNION_LENGTH) {
+			return head_.quaternion[index];
+		}
+		return 0;
+	}
+
+	void setQuaternion(unsigned int index, float value) {
+		if (index < ISMRMRD_QUATERNION_LENGTH) {
+			head_.quaternion[index] = value;
+		}
+	}
+
+	float getSampleTimeUs() const {
+		return head_.sample_time_us;
+	}
+
+	void setSampleTimeUs(float sampleTimeUs) {
+		head_.sample_time_us = sampleTimeUs;
+	}
+
+	uint32_t getScanCounter() const {
+		return head_.scan_counter;
+	}
+
+	void setScanCounter(uint32_t scanCounter) {
+		head_.scan_counter = scanCounter;
+	}
+
+	uint16_t getTrajectoryDimensions() const {
+		return head_.trajectory_dimensions;
+	}
+
+	void setTrajectoryDimensions(uint16_t trajectoryDimensions) {
+		head_.trajectory_dimensions = trajectoryDimensions;
+	}
+
+	const float getUserFloat(unsigned int index) const {
+		if (index < ISMRMRD_USER_FLOATS) {
+			return head_.user_float[index];
+		}
+		return 0.0f;
+	}
+
+	void setUserFloat(unsigned int index, float value) {
+		if (index < ISMRMRD_USER_FLOATS) {
+			head_.user_float[index] = value;
+		}
+	}
+
+	const int32_t getUserInt(unsigned int index) const {
+		if (index < ISMRMRD_USER_INTS) {
+			return head_.user_int[index];
+		}
+		return 0;
+	}
+
+	void setUserInt(unsigned int index, int32_t value) {
+		if (index < ISMRMRD_USER_INTS) {
+			head_.user_int[index] = value;
+		}
+	}
+
+	uint16_t getVersion() const {
+		return head_.version;
+	}
+
+	void setVersion(uint16_t version) {
+		this->head_.version = version;
+	}
+
+	const std::valarray<float>& getData() const {
+		return data_;
+	}
+
+	void setData(const std::valarray<float>& data) {
+		data_ = data;
+	}
+
+	const std::valarray<float>& getTraj() const {
+		return traj_;
+	}
+
+	void setTraj(const std::valarray<float>& traj) {
+		traj_ = traj;
+	}
+
+    float& operator[] (const size_t& p) {
+        return data_[p];
+    }
+
+    float operator[] (const size_t& p) const {
+        return data_[p];
+    }
+
+protected:
+	size_t calcTrajLength() {
+		return head_.trajectory_dimensions*head_.number_of_samples;
+	}
+
+	size_t calcDataLength() {
+		return head_.active_channels*head_.number_of_samples*2;
+	}
+
+
+	void makeConsistent() {
+		if (head_.active_channels > head_.available_channels) {
+			head_.available_channels = head_.active_channels;
+		}
+		if (calcTrajLength() != traj_.size()) {
+			traj_.resize(calcTrajLength());
+		}
+		if (calcDataLength() != data_.size()) {
+			data_.resize(calcDataLength());
+		}
+	}
+
 	AcquisitionHeader head_; /**< Header, see above */
-    
     std::valarray<float> traj_;
     std::valarray<float> data_;
     
diff --git a/ismrmrd_hdf5.cpp b/ismrmrd_hdf5.cpp
index 1ee7812..d675516 100644
--- a/ismrmrd_hdf5.cpp
+++ b/ismrmrd_hdf5.cpp
@@ -317,12 +317,12 @@ int IsmrmrdDataset::appendAcquisition(Acquisition* a)
 	try {
 		boost::shared_ptr<DataType> datatype = getIsmrmrdHDF5Type<AcquisitionHeader_with_data>();
 		AcquisitionHeader_with_data tmp;
-		tmp.head = a->head_;
+		tmp.head = a->getHead();
 		tmp.traj.len = tmp.head.trajectory_dimensions*tmp.head.number_of_samples;
-		tmp.traj.p = static_cast<void*>(&a->traj_[0]);
+		tmp.traj.p = const_cast<float*>(&a->getTraj()[0]);
 
 		tmp.data.len = tmp.head.active_channels*tmp.head.number_of_samples*2;
-		tmp.data.p = static_cast<void*>(&a->data_[0]);
+		tmp.data.p = const_cast<float*>(&a->getData()[0]);
 
 		DataSpace mspace1 = dataset_->getSpace();
 		rank = mspace1.getSimpleExtentNdims();
@@ -446,13 +446,18 @@ boost::shared_ptr< Acquisition > IsmrmrdDataset::readAcquisition(unsigned long i
 		dataset_->read(reinterpret_cast<void*>(&tmp), *datatype, memspace, dataspace, H5P_DEFAULT);
 
 		ret = boost::shared_ptr<Acquisition>(new Acquisition());
-		ret->head_ = tmp.head;
+		ret->setHead(tmp.head);
+		//ret->head_ = tmp.head;
         size_t tl = tmp.traj.len;
         size_t dl = tmp.data.len;
-        ret->traj_.resize(tl);
-		memcpy(&ret->traj_[0], tmp.traj.p, sizeof(float)*tl);
-        ret->data_.resize(dl);
-		memcpy(&ret->data_[0], tmp.data.p, sizeof(float)*dl);
+        if ((tl != ret->getTraj().size()) || (dl != ret->getData().size())) {
+        	std::cout << "Header does not match data length in file" << std::endl;
+        	throw;
+        }
+		memcpy(const_cast<float*>(&ret->getTraj()[0]), tmp.traj.p, sizeof(float)*tl);
+		free(tmp.traj.p); //Avoid memory leak
+		memcpy(const_cast<float*>(&ret->getData()[0]), tmp.data.p, sizeof(float)*dl);
+		free(tmp.data.p); //Avoid memory leak
 
 	} catch (...) {
 		std::cout << "Error caught while attempting to read HDF5 file" << std::endl;
@@ -517,9 +522,9 @@ boost::shared_ptr<std::string> IsmrmrdDataset::readHeader()
 
 template <typename T> int IsmrmrdDataset::appendImage(Image<T>& m, const char* varname) {
 	ImageHeader_with_data<T> tmp;
-	tmp.head = m.head_;
+	tmp.head = m.getHead();
 	tmp.data.len = m.getNumberOfElements();
-	tmp.data.p = &m.data_[0];
+	tmp.data.p = const_cast<T*>(&m.getData()[0]);
 	std::vector<unsigned int> dims(1,1);
 	NDArrayContainer<ImageHeader_with_data<T> > cont(dims, &tmp);
 	return appendArray<ImageHeader_with_data<T> >(cont, varname);
@@ -538,13 +543,11 @@ template <typename T> boost::shared_ptr< Image<T> > IsmrmrdDataset::readImage(co
 		return ret;
 	}
 	//We will copy the header
-	memcpy(&ret->head_, &(tmp->data_[0].head), sizeof(ImageHeader));
-
-	//Here we grab the data, which is part of the hvl_t member of ImageHeader_with_data, which does NOT get deallocated automatically.
+	ret->setHead(tmp->data_[0].head);
 
     size_t dlen = tmp->data_[0].data.len;
-    ret->data_.resize(dlen);
-	memcpy (&ret->data_, tmp->data_[0].data.p, dlen*sizeof(T));
+	memcpy (const_cast<T*>(&ret->getData()[0]), tmp->data_[0].data.p, dlen*sizeof(T));
+	free(tmp->data_[0].data.p); //Avoid memory leak
 	return ret;
 }
 
diff --git a/tests/c++/t_image.cpp b/tests/c++/t_image.cpp
index 3b467a6..528c47b 100644
--- a/tests/c++/t_image.cpp
+++ b/tests/c++/t_image.cpp
@@ -12,16 +12,18 @@ int main (int args, char** argv) {
     dims.push_back (1);
     dims.push_back (16); // channels
     
-    Image<std::complex<float> > img_s (dims);
+    Image<std::complex<float> > img_s (dims[0], dims[1], dims[2], dims[3]);
 
-    if (!img_s.is_consistent()) // dimensions and data size match?
+    if (img_s.getNumberOfElements() != img_s.getData().size()) // dimensions and data size match?
         return 1;
     
+    /* This test should no longer be needed.
     size_t img_s_gne = img_s.getNumberOfElements();
     size_t img_s_e   = img_s.elements();
 
     if (img_s_gne != img_s_e) // header and data match?
         return 1;
+    */
     
     return 0;
     

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