[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