[ismrmrd] 26/177: Added Cpp Dataset type. Can now read/write XML header and Acquisitions.
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:01:58 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag v1.1.0.beta.1
in repository ismrmrd.
commit 90cdaf0653c5318d8e43194d8f0930fbd261c41c
Author: Souheil Inati <souheil.inati at nih.gov>
Date: Wed Aug 27 13:34:15 2014 -0400
Added Cpp Dataset type. Can now read/write XML header and Acquisitions.
---
CMakeLists.txt | 3 +-
doc/doxygen/Doxyfile.in | 6 ++--
examples/c++/basic_test.cpp | 63 ++++++++++++++++++++++++++++++++++++-
examples/c/main.c | 16 ++++++++++
ismrmrd.c | 22 ++++++++++---
ismrmrd.cpp | 41 ++++++++++++++++++++++--
ismrmrd.h | 23 ++++++++++++--
ismrmrd_dataset.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++
ismrmrd_dataset.h | 29 +++++++++++++++++
9 files changed, 266 insertions(+), 13 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19d40b0..d848309 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,7 @@ add_library(ismrmrd SHARED
ismrmrd.c
ismrmrd.cpp
ismrmrd_dataset.c
+ ismrmrd_dataset.cpp
xml/ismrmrd_xml.cpp
xml/ismrmrd_meta.cpp
xml/pugixml.cpp)
@@ -73,7 +74,7 @@ install(FILES
# copy the examples directory
install(DIRECTORY examples DESTINATION .)
-#add_subdirectory(doc)
+add_subdirectory(doc)
#add_subdirectory(utilities)
#add_subdirectory(tests)
#add_subdirectory(matlab)
diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in
index b11e86e..39e238c 100644
--- a/doc/doxygen/Doxyfile.in
+++ b/doc/doxygen/Doxyfile.in
@@ -629,7 +629,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../../ @CMAKE_CURRENT_BINARY_DIR@/../../src/xsd/
+INPUT = @CMAKE_SOURCE_DIR@ @CMAKE_SOURCE_DIR@/xml
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -653,7 +653,7 @@ FILE_PATTERNS =
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
-RECURSIVE = YES
+RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
@@ -682,7 +682,7 @@ EXCLUDE_PATTERNS =
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
-EXCLUDE_SYMBOLS = ISMRMRD::complex_t ISMRMRD::double_complex_t ISMRMRD::AcquisitionHeader_with_data ISMRMRD::ImageHeader_with_data
+EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
diff --git a/examples/c++/basic_test.cpp b/examples/c++/basic_test.cpp
index 099efbf..2943974 100644
--- a/examples/c++/basic_test.cpp
+++ b/examples/c++/basic_test.cpp
@@ -1,6 +1,7 @@
#include <iostream>
#include "ismrmrd.h"
#include "ismrmrd_xml.h"
+#include "ismrmrd_dataset.h"
int main (int args, char** argv) {
@@ -17,6 +18,14 @@ int main (int args, char** argv) {
std::cout << "Flags 2: " << acqhdr.flags() << std::endl;
std::cout << "ACQ_FIRST_IN_SLICE: " << acqhdr.isFlagSet(ISMRMRD_ACQ_FIRST_IN_SLICE) << std::endl;
+ // How to use the AcquisitionHeader as a wrapper to the C struct.
+ ISMRMRD_AcquisitionHeader c_acqhdr;
+ ismrmrd_init_acquisition_header(&c_acqhdr);
+ c_acqhdr.flags = 64;
+
+ AcquisitionHeader acqhdr2(&c_acqhdr);
+ std::cout << "AcquisitionHeader copy: flags: " << acqhdr2.flags() << std::endl;
+
Acquisition acq;
std::cout << "Version: " << acq.version() << std::endl;
std::cout << "Flags 0: " << acq.flags() << std::endl;
@@ -31,8 +40,60 @@ int main (int args, char** argv) {
acq.number_of_samples(64);
std::cout << "Number of samples: " << acq.number_of_samples() << std::endl;
+ Acquisition acq2(acq);
+ std::cout << "Acquisition flags: " << acq.flags() << " Acquisition copy flags: " << acq2.flags() << std::endl;
+ std::cout << "Acquisition ACQ_FIRST_IN_SLICE: " << acq.isFlagSet(ISMRMRD_ACQ_FIRST_IN_SLICE) << std::endl;
+ std::cout << "Acquisition copy ACQ_FIRST_IN_SLICE: " << acq2.isFlagSet(ISMRMRD_ACQ_FIRST_IN_SLICE) << std::endl;
+ std::cout << "Acquisition nsamp: " << acq.number_of_samples() << " Acquisition copy nsamp: " << acq2.number_of_samples() << std::endl;
+
+ // How to use the Acquisition as a wrapper to the C struct.
+ ISMRMRD_Acquisition c_acq;
+ ismrmrd_init_acquisition(&c_acq);
+ c_acq.head.number_of_samples = 128;
+ c_acq.head.active_channels = 4;
+ ismrmrd_make_consistent_acquisition(&c_acq);
+ for (int k=0; k<c_acq.head.number_of_samples; k++) {
+ for (int c=0; c<c_acq.head.active_channels; c++) {
+ c_acq.data[k*c_acq.head.active_channels + c] = std::complex<float>(1.0, 1.0);
+ }
+ }
+ ismrmrd_set_flag(&(c_acq.head.flags), ISMRMRD_ACQ_FIRST_IN_SLICE);
+ Acquisition acq3(&c_acq);
+ std::cout << "Acquisition nsamp: " << c_acq.head.number_of_samples << " Acquisition wrapper nsamp: " << acq3.number_of_samples() << std::endl;
+ std::cout << "Acquisition data[4]: " << c_acq.data[4].real() << " Acquisition wrapper data[4]: " << acq3.data()[4].real() << std::endl;
+
+ // Open an existing file
+ Dataset dataset1 = Dataset("myfile.h5", "/dataset", false);
+
+ // Open a second dataset
+ Dataset dataset2 = Dataset("myfile2.h5", "/dataset", true);
+
+ // Read the header from file 1
+ std::string xmlstring;
+ dataset1.readHeader(xmlstring);
+ std::cout << "XML Header: " << xmlstring << std::endl;
- ISMRMRD::IsmrmrdHeader h;
+ // Write the header to file 2
+ dataset2.writeHeader(xmlstring);
+
+ // Read the number of acquisitions
+ unsigned long numacq = dataset1.getNumberOfAcquisitions();
+ std::cout << "Number of acquisitions: " << numacq << std::endl;
+
+ // Read the first few acquisitions
+ if (numacq > 3) { numacq=3; }
+
+ for (unsigned long n = 0; n<numacq; n++) {
+ Acquisition * acqref = dataset1.readAcquisition(n);
+ std::cout << "Acquisition " << n << " nsamp: " << acqref->number_of_samples() << std::endl;
+ std::cout << "Acquisition " << n << " flags: " << acqref->flags() << std::endl;
+ std::cout << "Acquisition " << n << " data[4]: " << acqref->data()[4].real() << std::endl;
+ dataset2.appendAcquisition(* acqref);
+ delete acqref;
+ }
+ std::cout << "Dataset2: number of acquisitions: " << dataset2.getNumberOfAcquisitions() << std::endl;
+
+ //ISMRMRD::IsmrmrdHeader h;
//serialize(h,std::cout);
return 0;
diff --git a/examples/c/main.c b/examples/c/main.c
index ab16e0d..c3e7699 100644
--- a/examples/c/main.c
+++ b/examples/c/main.c
@@ -34,8 +34,12 @@ int main(void)
/* Append some acquisitions */
ISMRMRD_Acquisition acq;
+ // must initialize an acquisition before you can use it
+ ismrmrd_init_acquisition(&acq);
int nacq_write = 5;
for (int n=0; n < nacq_write; n++) {
+ // must free an acquisition before you can reinitialize it
+ ismrmrd_init_acquisition(&acq);
ismrmrd_init_acquisition(&acq);
acq.head.number_of_samples = 128;
acq.head.active_channels = 4;
@@ -75,6 +79,7 @@ int main(void)
/* read the next to last one */
ISMRMRD_Acquisition acq2;
+ ismrmrd_init_acquisition(&acq2);
unsigned long index = 0;
if (nacq_read>1) {
index = nacq_read - 1;
@@ -88,7 +93,18 @@ int main(void)
printf("Flags: %llu\n", acq2.head.flags);
printf("Data[4]: %f, %f\n", creal(acq2.data[4]), cimag(acq2.data[4]));
+ ISMRMRD_Acquisition acq3;
+ ismrmrd_init_acquisition(&acq3);
+ ismrmrd_copy_acquisition(&acq3, &acq2);
+
+ printf("Pointers 3: %p\t 2: %p\n", (void *) acq3.data, (void *) acq2.data);
+ printf("Data 3: %f\t 2: %f\n", creal(acq3.data[4]), creal(acq2.data[4]));
+
/* Clean up */
+ /* This frees the internal memory of the acquisitions */
+ ismrmrd_cleanup_acquisition(&acq);
+ ismrmrd_cleanup_acquisition(&acq2);
+ ismrmrd_cleanup_acquisition(&acq3);
free(xmlstring);
/* Close the dataset */
diff --git a/ismrmrd.c b/ismrmrd.c
index 8124128..5c2d930 100644
--- a/ismrmrd.c
+++ b/ismrmrd.c
@@ -41,8 +41,19 @@ void ismrmrd_init_acquisition_header(ISMRMRD_AcquisitionHeader *hdr) {
void ismrmrd_init_acquisition(ISMRMRD_Acquisition *acq) {
ismrmrd_init_acquisition_header(&acq->head);
- acq->traj = NULL;
- acq->data = NULL;
+ acq->traj = (float *)malloc(ismrmrd_size_of_acquisition_traj(acq));
+ acq->data = (complex_float_t *)malloc(ismrmrd_size_of_acquisition_data(acq));
+}
+
+void ismrmrd_cleanup_acquisition(ISMRMRD_Acquisition *acq) {
+ free(acq->data);
+ free(acq->traj);
+}
+
+ISMRMRD_Acquisition * ismrmrd_create_acquisition() {
+ ISMRMRD_Acquisition *acq = (ISMRMRD_Acquisition *) malloc(sizeof(ISMRMRD_Acquisition));
+ ismrmrd_init_acquisition(acq);
+ return acq;
}
void ismrmrd_free_acquisition(ISMRMRD_Acquisition *acq) {
@@ -52,10 +63,13 @@ void ismrmrd_free_acquisition(ISMRMRD_Acquisition *acq) {
}
void ismrmrd_copy_acquisition(ISMRMRD_Acquisition *acqdest, const ISMRMRD_Acquisition *acqsource) {
+ /* Copy the header */
memcpy(&acqdest->head, &acqsource->head, sizeof(ISMRMRD_AcquisitionHeader));
+ /* Reallocate memory for the trajectory and the data*/
ismrmrd_make_consistent_acquisition(acqdest);
- memcpy(&acqdest->traj, &acqsource->traj, ismrmrd_size_of_acquisition_traj(acqdest));
- memcpy(&acqdest->data, &acqsource->data, ismrmrd_size_of_acquisition_data(acqdest));
+ /* Copy the trajectory and the data */
+ memcpy(acqdest->traj, acqsource->traj, ismrmrd_size_of_acquisition_traj(acqsource));
+ memcpy(acqdest->data, acqsource->data, ismrmrd_size_of_acquisition_data(acqsource));
}
int ismrmrd_make_consistent_acquisition(ISMRMRD_Acquisition *acq) {
diff --git a/ismrmrd.cpp b/ismrmrd.cpp
index 0a9b4c7..7828ae6 100644
--- a/ismrmrd.cpp
+++ b/ismrmrd.cpp
@@ -5,8 +5,13 @@ namespace ISMRMRD {
//
// AcquisitionHeader class implementation
//
+// Constructors
AcquisitionHeader::AcquisitionHeader() {
- ismrmrd_init_acquisition_header(&(head_));
+ ismrmrd_init_acquisition_header(&head_);
+};
+
+AcquisitionHeader::AcquisitionHeader(const ISMRMRD_AcquisitionHeader *head) {
+ memcpy(&head_, head, sizeof(ISMRMRD_AcquisitionHeader));
};
// Accessors and mutators
@@ -128,9 +133,36 @@ void AcquisitionHeader::clearAllFlags() {
//
// Acquisition class Implementation
//
+// Constructors, assignment operator, destructor
Acquisition::Acquisition() {
ismrmrd_init_acquisition(&acq_);
-};
+}
+
+Acquisition::Acquisition(const Acquisition &other) {
+ // This is a deep copy
+ ismrmrd_init_acquisition(&acq_);
+ ismrmrd_copy_acquisition(&acq_, &other.acq_);
+}
+
+Acquisition::Acquisition(const ISMRMRD_Acquisition *acq) {
+ // This is a deep copy
+ ismrmrd_init_acquisition(&acq_);
+ ismrmrd_copy_acquisition(&acq_, acq);
+}
+
+Acquisition & Acquisition::operator= (const Acquisition &other) {
+ // Assignment makes a copy
+ if (this != &other )
+ {
+ ismrmrd_init_acquisition(&acq_);
+ ismrmrd_copy_acquisition(&acq_, &other.acq_);
+ }
+ return *this;
+}
+
+Acquisition::~Acquisition() {
+ ismrmrd_cleanup_acquisition(&acq_);
+}
// Accessors and mutators
const uint16_t &Acquisition::version() {
@@ -235,6 +267,11 @@ int32_t (&Acquisition::user_int()) [ISMRMRD_USER_INTS] { return acq_.head.user_i
float (&Acquisition::user_float()) [ISMRMRD_USER_FLOATS] { return acq_.head.user_float; };
+// Data and Trajectory accessors
+complex_float_t * Acquisition::data() { return acq_.data; };
+
+float * Acquisition::traj() { return acq_.traj; };
+
// Flag methods
bool Acquisition::isFlagSet(const uint64_t val) {
return ismrmrd_is_flag_set(acq_.head.flags, val);
diff --git a/ismrmrd.h b/ismrmrd.h
index 0fcb6e3..e5c92ac 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -210,13 +210,15 @@ typedef struct ISMRMRD_Acquisition {
complex_float_t *data;
} ISMRMRD_Acquisition;
-void ismrmrd_init_acquisition(ISMRMRD_Acquisition *acq);
+ISMRMRD_Acquisition * ismrmrd_create_acquisition();
void ismrmrd_free_acquisition(ISMRMRD_Acquisition *acq);
+void ismrmrd_init_acquisition(ISMRMRD_Acquisition *acq);
+void ismrmrd_cleanup_acquisition(ISMRMRD_Acquisition *acq);
void ismrmrd_copy_acquisition(ISMRMRD_Acquisition *acqdest, const ISMRMRD_Acquisition *acqsource);
int ismrmrd_make_consistent_acquisition(ISMRMRD_Acquisition *acq);
size_t ismrmrd_size_of_acquisition_traj(const ISMRMRD_Acquisition *acq);
size_t ismrmrd_size_of_acquisition_data(const ISMRMRD_Acquisition *acq);
-
+
/**********/
/* Images */
/**********/
@@ -338,8 +340,13 @@ void ismrmrd_quaternion_to_directions(float quat[4], float read_dir[3], float ph
class AcquisitionHeader {
public:
+ // Constructors
AcquisitionHeader();
+ AcquisitionHeader(const ISMRMRD_AcquisitionHeader *head);
+ // TODO
+ // Do we need to define an assignment operator?
+
// Accessors and mutators
const uint16_t &version();
const uint64_t &flags();
@@ -384,8 +391,14 @@ protected:
};
class Acquisition {
+ friend class Dataset;
public:
+ // Constructors, assignment, destructor
Acquisition();
+ Acquisition(const Acquisition &other);
+ Acquisition(const ISMRMRD_Acquisition *acq);
+ Acquisition & operator= (const Acquisition &other);
+ ~Acquisition();
// Accessors and mutators
const uint16_t &version();
@@ -415,6 +428,12 @@ public:
int32_t (&user_int())[ISMRMRD_USER_INTS];
float (&user_float())[ISMRMRD_USER_FLOATS];
+ // Data and Trajectory accessors
+ complex_float_t * data();
+ uint64_t numDataElements();
+ float * traj();
+ uint64_t numTrajElements();
+
// Flag methods
bool isFlagSet(const uint64_t val);
void setFlag(const uint64_t val);
diff --git a/ismrmrd_dataset.cpp b/ismrmrd_dataset.cpp
new file mode 100644
index 0000000..88d7a39
--- /dev/null
+++ b/ismrmrd_dataset.cpp
@@ -0,0 +1,76 @@
+#include "ismrmrd_dataset.h"
+
+namespace ISMRMRD {
+//
+// Dataset class implementation
+//
+// Constructor
+Dataset::Dataset(const char* filename, const char* groupname, bool create_file_if_needed)
+{
+ // TODO error checking and exception throwing
+ // Initialize the dataset
+ int status;
+ status = ismrmrd_init_dataset(&dset_, filename, groupname);
+ // Open the file
+ status = ismrmrd_open_dataset(&dset_, create_file_if_needed);
+}
+
+// Destructor
+Dataset::~Dataset()
+{
+ int status = ismrmrd_close_dataset(&dset_);
+}
+
+// XML Header
+int Dataset::writeHeader(const std::string& xmlstring)
+{
+ int status = ismrmrd_write_header(&dset_, xmlstring.c_str());
+ return status;
+}
+
+int Dataset::writeHeader(const char* xml)
+{
+ int status = ismrmrd_write_header(&dset_, xml);
+ return status;
+}
+
+int Dataset::readHeader(std::string& xmlstring){
+ char * temp = ismrmrd_read_header(&dset_);
+ xmlstring = std::string(temp);
+ free(temp);
+ return ISMRMRD_NOERROR;
+}
+
+char * Dataset::readHeader()
+{
+ // The C-API uses malloc. In Cpp we expect pointers to have been created with new,
+ // so we make a copy.
+ char * temp = ismrmrd_read_header(&dset_);
+ size_t xmllength = strlen(temp);
+ char * xml = new char[xmllength];
+ memcpy(xml, temp, xmllength);
+ free(temp);
+ return xml;
+}
+
+// Acquisitions
+int Dataset::appendAcquisition(const Acquisition &acq)
+{
+ int status = ismrmrd_append_acquisition(&dset_, &acq.acq_);
+ return status;
+}
+
+Acquisition * Dataset::readAcquisition(unsigned long index)
+{
+ Acquisition * acq = new Acquisition();
+ int status = ismrmrd_read_acquisition(&dset_, index, &acq->acq_);
+ return acq;
+}
+
+unsigned long Dataset::getNumberOfAcquisitions()
+{
+ unsigned long num = ismrmrd_get_number_of_acquisitions(&dset_);
+ return num;
+}
+
+} // namespace ISMRMRD
diff --git a/ismrmrd_dataset.h b/ismrmrd_dataset.h
index ca74cd9..1f589de 100644
--- a/ismrmrd_dataset.h
+++ b/ismrmrd_dataset.h
@@ -146,6 +146,35 @@ int ismrmrd_get_number_of_arrays(const ISMRMRD_Dataset *dset, const char *varnam
#ifdef __cplusplus
} /* extern "C" */
+
+//
+// ISMRMRD Datset C++ Interface
+//
+
+// TODO:
+// - exports as needed
+class Dataset {
+public:
+ // Constructor and destructor
+ Dataset(const char* filename, const char* groupname, bool create_file_if_needed = true);
+ ~Dataset();
+
+ // Methods
+ // XML Header
+ int writeHeader(const std::string& xmlstring);
+ int writeHeader(const char* xml);
+ int readHeader(std::string& xmlstring);
+ char * readHeader();
+ // Acquisitions
+ int appendAcquisition(const Acquisition &acq);
+ Acquisition * readAcquisition(unsigned long index);
+ unsigned long getNumberOfAcquisitions();
+
+protected:
+ ISMRMRD_Dataset dset_;
+};
+
+
} /* ISMRMRD namespace */
#endif
--
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