[ismrmrd] 31/281: Added example reconstruction of test dataset

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:00:52 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 8387b1f866fc5bdf19d185972fc110bd401472c2
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date:   Thu Sep 6 15:02:11 2012 -0400

    Added example reconstruction of test dataset
---
 CMakeLists.txt         |   3 +
 test_recon_dataset.cpp | 160 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f59306..50d2d80 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,6 +59,9 @@ IF(FFTW3_FOUND)
 	add_executable(ismrmrd_create_dataset test_create_dataset.cpp)
 	target_link_libraries(ismrmrd_create_dataset ${XERCESC_LIBRARIES} ismrmrd ${FFTW3_LIBRARIES})
 	INSTALL(TARGETS ismrmrd_create_dataset DESTINATION bin)
+	add_executable(ismrmrd_recon_dataset test_recon_dataset.cpp)
+	target_link_libraries(ismrmrd_recon_dataset ${XERCESC_LIBRARIES} ismrmrd ${FFTW3_LIBRARIES})
+	INSTALL(TARGETS ismrmrd_recon_dataset DESTINATION bin)
 ELSE(FFTW3_FOUND)
 	MESSAGE("FFTW3 NOT Found....cannot build test applications")
 ENDIF(FFTW3_FOUND)
diff --git a/test_recon_dataset.cpp b/test_recon_dataset.cpp
new file mode 100644
index 0000000..549fda9
--- /dev/null
+++ b/test_recon_dataset.cpp
@@ -0,0 +1,160 @@
+/*
+ * test_recon_dataset.cpp
+ *
+ *  Created on: Sep 6, 2012
+ *      Author: Michael S. Hansen (michael.hansen at nih.gov)
+ *
+ */
+
+#include <iostream>
+#include "ismrmrd.h"
+#include "ismrmrd.hxx"
+#include "ismrmrd_hdf5.h"
+#include "fftw3.h"
+
+//Helper function for the FFTW library
+template<typename TI, typename TO> void circshift(TO *out, const TI *in, int xdim, int ydim, int xshift, int yshift)
+{
+  for (int i =0; i < ydim; i++) {
+    int ii = (i + yshift) % ydim;
+    for (int j = 0; j < xdim; j++) {
+      int jj = (j + xshift) % xdim;
+      out[ii * xdim + jj] = in[i * xdim + j];
+    }
+  }
+}
+
+#define fftshift(out, in, x, y) circshift(out, in, x, y, (x/2), (y/2))
+
+void print_usage(const char* application)
+{
+	std::cout << "Usage:" << std::endl;
+	std::cout << "  - " << application << " <HDF5_FILENAME> " << "<SCHEMA_FILENAME>" << std::endl;
+}
+
+int main(int argc, char** argv)
+{
+	if (argc < 3) {
+		print_usage(argv[0]);
+		return -1;
+	}
+
+	std::string datafile(argv[1]);
+	std::string schemafile(argv[2]);
+
+	std::cout << "Simple ISMRMRD Reconstruction program" << std::endl;
+	std::cout << "   - filename: " << datafile << std::endl;
+	std::cout << "   - schema  : " << schemafile << std::endl;
+
+	//Let's open the dataset
+	ISMRMRD::IsmrmrdDataset d(datafile.c_str(),"dataset");
+
+	//We will start by getting the header and turning it into a C++ class
+	//In order to do true validation of the XML, we will use the XML schema
+	xml_schema::properties props;
+	props.schema_location ("http://www.ismrm.org/ISMRMRD", schemafile);
+
+	boost::shared_ptr<std::string> xml = d.readHeader();
+	std::istringstream str_stream(*xml, std::stringstream::in);
+
+	boost::shared_ptr<ISMRMRD::ismrmrdHeader> cfg;
+
+	try {
+		cfg = boost::shared_ptr<ISMRMRD::ismrmrdHeader>(ISMRMRD::ismrmrdHeader_ (str_stream,0,props));
+	}  catch (const xml_schema::exception& e) {
+		std::cout << "Failed to parse XML Parameters: " << e.what() << std::endl;
+	}
+
+	//Let's print some information from the header
+	ISMRMRD::ismrmrdHeader::encoding_sequence e_seq = cfg->encoding();
+	if (e_seq.size() != 1) {
+		std::cout << "Number of encoding spaces: " << e_seq.size() << std::endl;
+		std::cout << "This simple reconstruction application only supports one encoding space" << std::endl;
+		return -1;
+	}
+
+	ISMRMRD::encodingSpaceType e_space = (*e_seq.begin()).encodedSpace();
+	ISMRMRD::encodingSpaceType r_space = (*e_seq.begin()).reconSpace();
+	ISMRMRD::encodingLimitsType e_limits = (*e_seq.begin()).encodingLimits();
+
+	std::cout << "Encoding Matrix Size        : [" << e_space.matrixSize().x() << ", " << e_space.matrixSize().y() << ", " << e_space.matrixSize().z() << "]" << std::endl;
+	std::cout << "Reconstruction Matrix Size  : [" << r_space.matrixSize().x() << ", " << r_space.matrixSize().y() << ", " << r_space.matrixSize().z() << "]" << std::endl;
+	std::cout << "Number of acquisitions      : " << d.getNumberOfAcquisitions() << std::endl;
+
+	if (e_space.matrixSize().z() != 1) {
+		std::cout << "This simple reconstruction application only supports 2D encoding spaces" << std::endl;
+		return -1;
+	}
+
+	//Allocate a buffer for the data
+	ISMRMRD::NDArrayContainer< std::complex<float> > buffer;
+	buffer.dimensions_.push_back(e_space.matrixSize().x());
+	buffer.dimensions_.push_back(e_space.matrixSize().y());
+	buffer.data_.resize(e_space.matrixSize().x()*e_space.matrixSize().y(), std::complex<float>(0.0,0.0));
+
+	//Now loop through and copy data
+	unsigned int number_of_acquisitions = d.getNumberOfAcquisitions();
+	for (unsigned int i = 0; i < number_of_acquisitions; i++) {
+		//Read one acquisition at a time
+		boost::shared_ptr<ISMRMRD::Acquisition> acq = d.readAcquisition(i);
+
+		//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.data_[offset],acq->data_,sizeof(float)*2*buffer.dimensions_[0]);
+	}
+
+	//Let's FFT the k-space to image
+	fftwf_complex* tmp = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*buffer.data_.size());
+
+	if (!tmp) {
+		std::cout << "Error allocating temporary storage for FFTW" << std::endl;
+		return -1;
+	}
+
+	fftshift(reinterpret_cast<std::complex<float>*>(tmp),&buffer.data_[0],buffer.dimensions_[0],buffer.dimensions_[1]);
+
+	//Create the FFTW plan
+	fftwf_plan p = fftwf_plan_dft_2d(buffer.dimensions_[1], buffer.dimensions_[0], tmp,tmp, FFTW_BACKWARD, FFTW_ESTIMATE);
+
+	fftwf_execute(p);
+
+	fftshift(&buffer.data_[0],reinterpret_cast<std::complex<float>*>(tmp),buffer.dimensions_[0],buffer.dimensions_[1]);
+
+	//Clean up.
+	fftwf_destroy_plan(p);
+	fftwf_free(tmp);
+
+	//Now, let's remove the oversampling in the readout and take the magnitude
+	//Allocate a buffer for the data
+	ISMRMRD::NDArrayContainer< float > img;
+	img.dimensions_.push_back(r_space.matrixSize().x());
+	img.dimensions_.push_back(r_space.matrixSize().y());
+	img.data_.resize(r_space.matrixSize().x()*r_space.matrixSize().y(), 0.0);
+
+	for (unsigned int y = 0; y < img.dimensions_[1]; y++) {
+		for (unsigned int x = 0; x < img.dimensions_[0]; x++) {
+			img.data_[y*img.dimensions_[0]+x] =
+				std::abs(buffer.data_[y*buffer.dimensions_[0] + x + ((e_space.matrixSize().x()-r_space.matrixSize().x())>>1)]);
+		}
+	}
+
+	//Let's write the reconstructed image straight in the same data file
+	ISMRMRD::ImageHeader img_h;
+	img_h.channels = 1;
+	img_h.image_data_type = ISMRMRD::DATA_COMPLEX_FLOAT; //This is actually just guidance
+	img_h.image_type      = ISMRMRD::TYPE_COMPLEX;       //This is actually just guidance
+	img_h.slice = 0;
+	//And so on
+
+	//Now append, we will append image and header separately (in two different datasets)
+	d.appendImageHeader(img_h,"myimage.head");
+	d.appendArray(img,"myimage.img");
+
+
+	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