[ismrmrd] 252/281: The new XML library can now deserialize and serialize

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:01:21 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 2f3e02a50982cd7636c1cbc68d07ef27a098a73b
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date:   Wed Aug 13 11:10:34 2014 -0400

    The new XML library can now deserialize and serialize
---
 xml/.gitignore                                     |   1 +
 xml/CMakeLists.txt                                 |  24 +--
 xml/ismrmrd_xml.cpp                                | 205 +++++++++++++++++++--
 xml/ismrmrd_xml.h                                  |  17 +-
 ...ump_ismrmrd_header.cpp => test_ismrmrd_xml.cpp} |  32 +++-
 5 files changed, 230 insertions(+), 49 deletions(-)

diff --git a/xml/.gitignore b/xml/.gitignore
new file mode 100644
index 0000000..b81c795
--- /dev/null
+++ b/xml/.gitignore
@@ -0,0 +1 @@
+*.xml
\ No newline at end of file
diff --git a/xml/CMakeLists.txt b/xml/CMakeLists.txt
index 74e4d12..8a8202d 100644
--- a/xml/CMakeLists.txt
+++ b/xml/CMakeLists.txt
@@ -4,31 +4,17 @@ add_library(ismrmrd_xml SHARED
   pugixml.cpp
   )
 
-
-include_directories(${ISMRMRD_SOURCE_DIR})
-
-add_executable(dump_ismrmrd_header
-  dump_ismrmrd_header.cpp
+add_executable(test_ismrmrd_xml
+  test_ismrmrd_xml.cpp
+  pugixml.cpp
 )
 
-target_link_libraries(dump_ismrmrd_header
-  ismrmrd
+target_link_libraries(test_ismrmrd_xml
   ismrmrd_xml)
 
-if(WIN32)
-    target_link_libraries(ismrmrd_xml optimized ${HDF5_hdf5_LIBRARY_RELEASE}
-        optimized ${HDF5_hdf5_cpp_LIBRARY_RELEASE})
-    target_link_libraries(ismrmrd_xml debug ${HDF5_hdf5_LIBRARY_DEBUG}
-        debug ${HDF5_hdf5_cpp_LIBRARY_DEBUG})
-    target_link_libraries(ismrmrd_xml ${Boost_LIBRARIES})
-else(WIN32)
-    target_link_libraries(ismrmrd_xml ${HDF5_LIBRARIES} ${Boost_THREAD_LIBRARY}
-        ${Boost_SYSTEM_LIBRARY})
-endif(WIN32)
-
 install (FILES ismrmrd_xml.h
   DESTINATION ${ISMRMRD_INSTALL_INCLUDE_DIR})
 
 install (TARGETS ismrmrd_xml DESTINATION ${ISMRMRD_INSTALL_LIB_DIR})
 
-install (TARGETS dump_ismrmrd_header DESTINATION ${ISMRMRD_INSTALL_BIN_DIR})
+install (TARGETS test_ismrmrd_xml DESTINATION ${ISMRMRD_INSTALL_BIN_DIR})
diff --git a/xml/ismrmrd_xml.cpp b/xml/ismrmrd_xml.cpp
index 1aea1e1..a34aec0 100644
--- a/xml/ismrmrd_xml.cpp
+++ b/xml/ismrmrd_xml.cpp
@@ -23,9 +23,9 @@ namespace ISMRMRD
     if (!fieldOfView_mm) {
       throw std::runtime_error("fieldOfView_mm not found in encodingSpace");
     } else {
-      e.fieldOfView_mm.x = std::atoi(fieldOfView_mm.child_value("x"));
-      e.fieldOfView_mm.y = std::atoi(fieldOfView_mm.child_value("y"));
-      e.fieldOfView_mm.z = std::atoi(fieldOfView_mm.child_value("z"));
+      e.fieldOfView_mm.x = std::atof(fieldOfView_mm.child_value("x"));
+      e.fieldOfView_mm.y = std::atof(fieldOfView_mm.child_value("y"));
+      e.fieldOfView_mm.z = std::atof(fieldOfView_mm.child_value("z"));
     }
 
     return e;
@@ -155,8 +155,7 @@ namespace ISMRMRD
 
       char buffer[10000];
       memcpy(buffer,name.child_value(),strlen(name.child_value())+1);
-      std::string tmp("BLAH");
-      v.name = "BLAKKK";//xtmp;//std::string("BLAH");//name.child_value());
+      v.name = name.child_value();
       v.value = std::atof(value.child_value());
 
       r.push_back(v);
@@ -321,9 +320,9 @@ namespace ISMRMRD
 	while (measurementDependency) {
 	  try {
 	    MeasurementDependency d;
-	    d.dependencyID = parse_string(measurementDependency,"dependencyID");
+	    d.measurementID = parse_string(measurementDependency,"measurementID");
 	    d.dependencyType = parse_string(measurementDependency,"dependencyType");
-	    info.measurementDepencency.push_back(d);
+	    info.measurementDependency.push_back(d);
 	  } catch (std::runtime_error& e) {
 	    std::cout << "Error parsing measurement dependency: " << e.what() << std::endl;
 	    throw;
@@ -374,7 +373,7 @@ namespace ISMRMRD
 	DicomParameters p;
 	p.studyInstanceUID = parse_string(dicomParameters,"studyInstanceUID");
 	p.seriesInstanceUIDRoot = parse_optional_string(dicomParameters,"seriesInstanceUIDRoot");
-	p.frameOfReference = parse_optional_string(dicomParameters,"frameOfReferenceUID");
+	p.frameOfReferenceUID = parse_optional_string(dicomParameters,"frameOfReferenceUID");
 
 	//This part of the schema is totally messed up and needs to be fixed, but for now we will just read it. 
 	pugi::xml_node ri = dicomParameters.child("referencedImageSequemce");
@@ -393,7 +392,7 @@ namespace ISMRMRD
 	  MRImageModule m;
 	  m.imageType = parse_optional_string(mrimageModule,"imageType");
 	  m.scanningSequence = parse_optional_string(mrimageModule, "scanningSequence");
-	  m.sequenceVartiant = parse_optional_string(mrimageModule, "sequenceVariant");
+	  m.sequenceVariant = parse_optional_string(mrimageModule, "sequenceVariant");
 	  m.scanOptions = parse_optional_string(mrimageModule, "scanOptions");
 	  m.mrAcquisitionType = parse_optional_string(mrimageModule, "mrAcquisitionType");
 	  m.echoTrainLength = parse_optional_long(mrimageModule, "echoTrainLength");
@@ -433,6 +432,13 @@ namespace ISMRMRD
     o = std::string(buffer);
   }
 
+  void to_string_val(const double& v, std::string& o)
+  {
+    char buffer[256];
+    sprintf(buffer,"%f",v);
+    o = std::string(buffer);
+  }
+
   void to_string_val(const unsigned short& v, std::string& o)
   {
     char buffer[256];
@@ -440,7 +446,15 @@ namespace ISMRMRD
     o = std::string(buffer);
   }
 
-  template <class T> void append_optional_node(pugi::xml_node& n, const char* child, const Optional<T>& v) {
+  void to_string_val(const long& v, std::string& o)
+  {
+    char buffer[256];
+    sprintf(buffer,"%ld",v);
+    o = std::string(buffer);
+  }
+
+  template <class T> void append_optional_node(pugi::xml_node& n, const char* child, const Optional<T>& v) 
+  {
     if (v) {
       pugi::xml_node n2 = n.append_child(child);
       std::string v_as_string;
@@ -449,20 +463,55 @@ namespace ISMRMRD
     }
   } 
   
-  template <class T> void append_node(pugi::xml_node& n, const char* child, const T& v) {
+  template <class T> void append_node(pugi::xml_node& n, const char* child, const T& v) 
+  {
     pugi::xml_node n2 = n.append_child(child);
     std::string v_as_string;
-    to_string_val(*v, v_as_string);
+    to_string_val(v, v_as_string);
     n2.append_child(pugi::node_pcdata).set_value(v_as_string.c_str());
   } 
 
+  void append_encoding_space(pugi::xml_node& n, const char* child, const EncodingSpace& s) 
+  {
+    pugi::xml_node n2 = n.append_child(child);
+    pugi::xml_node n3 = n2.append_child("matrixSize");
+    append_node(n3,"x",s.matrixSize.x);
+    append_node(n3,"y",s.matrixSize.y);
+    append_node(n3,"z",s.matrixSize.z);
+    n3 = n2.append_child("fieldOfView_mm");
+    append_node(n3,"x",s.fieldOfView_mm.x);
+    append_node(n3,"y",s.fieldOfView_mm.y);
+    append_node(n3,"z",s.fieldOfView_mm.z);
+  }
+  
+  void append_encoding_limit(pugi::xml_node& n, const char* child, const Optional<Limit>& l) 
+  {
+    if (l) {
+      pugi::xml_node n2 = n.append_child(child);
+      append_node(n2,"minimum",l->minimum);
+      append_node(n2,"maximum",l->maximum);
+      append_node(n2,"center",l->center);
+    }
+  }
+
+  template <class T> 
+  void append_user_parameter(pugi::xml_node& n, const char* child, 
+			     const std::vector<T>& v) 
+  {
+    for (size_t i = 0; i < v.size(); i++) {
+      pugi::xml_node n2 = n.append_child(child);
+      append_node(n2,"name",v[i].name);
+      append_node(n2,"value",v[i].value);
+    }
+  }
+
   //End utility functions for serialization
 
   void serialize(const IsmrmrdHeader& h, std::ostream& o)
   {
     pugi::xml_document doc;
     pugi::xml_node root = doc.append_child();
-    pugi::xml_node n1;
+    pugi::xml_node n1,n2;
     pugi::xml_attribute a;
 
     root.set_name("ismrmrdHeader");
@@ -489,6 +538,37 @@ namespace ISMRMRD
       append_optional_node(n1,"patientGender",h.subjectInformation->patientGender);
     }
 
+    if (h.studyInformation) {
+      n1 = root.append_child();
+      n1.set_name("studyInformation");
+      append_optional_node(n1,"studyDate",h.studyInformation->studyDate);
+      append_optional_node(n1,"studyTime",h.studyInformation->studyTime);
+      append_optional_node(n1,"studyID",h.studyInformation->studyID);
+      append_optional_node(n1,"accessionNumber",h.studyInformation->accessionNumber);
+      append_optional_node(n1,"referringPhysicianName",h.studyInformation->referringPhysicianName);
+      append_optional_node(n1,"studyDescription",h.studyInformation->studyDescription);
+    }
+
+    if (h.measurementInformation) {
+      n1 = root.append_child();
+      n1.set_name("measurementInformation");
+      append_optional_node(n1,"measurementID",h.measurementInformation->measurementID);
+      append_optional_node(n1,"seriesDate",h.measurementInformation->seriesDate);
+      append_optional_node(n1,"seriesTime",h.measurementInformation->seriesTime);
+      append_node(n1,"patientPosition",h.measurementInformation->patientPosition);
+      append_optional_node(n1,"initialSeriesNumber",h.measurementInformation->initialSeriesNumber);
+      append_optional_node(n1,"protocolName",h.measurementInformation->protocolName);
+      append_optional_node(n1,"seriesDescription",h.measurementInformation->seriesDescription);
+
+      for (size_t i = 0; i < h.measurementInformation->measurementDependency.size(); i++) {
+	n2 = n1.append_child();
+	n2.set_name("measurementDependency");
+	append_node(n2,"deoendencyType",h.measurementInformation->measurementDependency[i].dependencyType);
+	append_node(n2,"measurementID",h.measurementInformation->measurementDependency[i].measurementID);
+      }
+
+    }
+
     if (h.acquisitionSystemInformation) {
       n1 = root.append_child();
       n1.set_name("acquisitionSystemInformation");
@@ -501,6 +581,105 @@ namespace ISMRMRD
       append_optional_node(n1,"stationName",h.acquisitionSystemInformation->stationName);
     }
 
+    n1 = root.append_child();
+    n1.set_name("experimentalConditions");
+    append_node(n1,"H1resonanceFrequency_Hz", h.experimentalConditions.H1resonanceFrequency_Hz);
+
+    if (!h.encoding.size()) {
+      throw std::runtime_error("Encoding array is empty. Invalid ISMRMRD header structure");
+    }
+
+    for (size_t i = 0; i < h.encoding.size(); i++) {
+      n1 = root.append_child("encoding");
+      append_encoding_space(n1,"encodedSpace",h.encoding[i].encodedSpace);
+      append_encoding_space(n1,"reconSpace",h.encoding[i].reconSpace);
+      n2 = n1.append_child("encodingLimits");
+      append_encoding_limit(n2,"kspace_encoding_step_0",h.encoding[i].encodingLimits.kspace_encoding_step_0);
+      append_encoding_limit(n2,"kspace_encoding_step_1",h.encoding[i].encodingLimits.kspace_encoding_step_1);
+      append_encoding_limit(n2,"kspace_encoding_step_2",h.encoding[i].encodingLimits.kspace_encoding_step_2);
+      append_encoding_limit(n2,"average",h.encoding[i].encodingLimits.average);
+      append_encoding_limit(n2,"slice",h.encoding[i].encodingLimits.slice);
+      append_encoding_limit(n2,"contrast",h.encoding[i].encodingLimits.contrast);
+      append_encoding_limit(n2,"phase",h.encoding[i].encodingLimits.phase);
+      append_encoding_limit(n2,"repetition",h.encoding[i].encodingLimits.repetition);
+      append_encoding_limit(n2,"set",h.encoding[i].encodingLimits.set);
+      append_encoding_limit(n2,"segment",h.encoding[i].encodingLimits.segment);
+      append_node(n1,"trajectory",h.encoding[i].trajectory);
+      
+      if (h.encoding[i].trajectoryDescription) {
+	n2 = n1.append_child("trajectoryDescription");
+	append_node(n2,"identifier",h.encoding[i].trajectoryDescription->identifier);
+	append_user_parameter(n2,"userParameterLong",h.encoding[i].trajectoryDescription->userParameterLong); 
+	append_user_parameter(n2,"userParameterDouble",h.encoding[i].trajectoryDescription->userParameterDouble); 
+	append_optional_node(n2,"comment",h.encoding[i].trajectoryDescription->comment);
+      }
+    }
+
+    if (h.parallelImaging) {
+      n1 = root.append_child("parallelImaging");
+      n2 = n1.append_child("accelerationFactor");
+      append_node(n2,"kspace_encoding_step_1",h.parallelImaging->accelerationFactor.kspace_encoding_step_1);
+      append_node(n2,"kspace_encoding_step_2",h.parallelImaging->accelerationFactor.kspace_encoding_step_2);
+      append_optional_node(n1, "calibrationMode", h.parallelImaging->calibrationMode);
+      append_optional_node(n1, "interleavingDimension", h.parallelImaging->interleavingDimension);
+    }
+
+    if (h.sequenceParameters) {
+      n1 = root.append_child("sequenceParameters");
+      if (!h.sequenceParameters->TR.size()) {
+	throw std::runtime_error("TR section of sequenceParameters does not contain any values");
+      }
+      if (!h.sequenceParameters->TE.size()) {
+	throw std::runtime_error("TE section of sequenceParameters does not contain any values");
+      }
+
+      for (size_t i = 0; i < h.sequenceParameters->TR.size(); i++) {
+	append_node(n1,"TR",h.sequenceParameters->TR[i]);
+      }
+      for (size_t i = 0; i < h.sequenceParameters->TE.size(); i++) {
+	append_node(n1,"TE",h.sequenceParameters->TE[i]);
+      }
+      for (size_t i = 0; i < h.sequenceParameters->TI.size(); i++) {
+	append_node(n1,"TI",h.sequenceParameters->TI[i]);
+      }
+    }
+
+    if (h.dicomParameters) {
+      n1 = root.append_child("dicomParameters");
+      append_node(n1, "studyInstanceUID", h.dicomParameters->studyInstanceUID);
+      append_optional_node(n1, "seriesInstanceUIDRoot",h.dicomParameters->seriesInstanceUIDRoot);
+      append_optional_node(n1, "frameOfReferenceUID", h.dicomParameters->frameOfReferenceUID);
+      
+      //TODO: Sort out stuff with this referenced image sequence. This is all messed up. 
+      if (h.dicomParameters->referencedImageSequence.size()) {
+	n2 = n1.append_child("referencedImageSequence");
+	for (size_t i = 0; i < h.dicomParameters->referencedImageSequence.size(); i++) {
+	  append_node(n2,"referencedSOPInstanceUID", h.dicomParameters->referencedImageSequence[i].referencedSOPInstanceUID);
+	}
+      }
+      
+      if (h.dicomParameters->mrImageModule) {
+	n2 = n1.append_child("MRImageModule");
+	append_optional_node(n2,"imageType",h.dicomParameters->mrImageModule->imageType);
+	append_optional_node(n2,"scanningSequence",h.dicomParameters->mrImageModule->scanningSequence);
+	append_optional_node(n2,"sequenceVariant",h.dicomParameters->mrImageModule->sequenceVariant);
+	append_optional_node(n2,"scanOptions",h.dicomParameters->mrImageModule->scanOptions);
+	append_optional_node(n2,"mrAcquisitionType",h.dicomParameters->mrImageModule->mrAcquisitionType);
+	append_optional_node(n2,"echoTrainLength",h.dicomParameters->mrImageModule->echoTrainLength);
+	append_optional_node(n2,"triggerTime",h.dicomParameters->mrImageModule->triggerTime);
+	append_optional_node(n2,"flipAngle_deg",h.dicomParameters->mrImageModule->flipAngle_deg);
+	append_optional_node(n2,"freqEncodingDirection",h.dicomParameters->mrImageModule->freqEncodingDirection);
+      }
+    }
+
+    if (h.userParameters) {
+      n1 = root.append_child("userParameters");
+      append_user_parameter(n1,"userParameterLong",h.userParameters->userParameterLong);
+      append_user_parameter(n1,"userParameterDouble",h.userParameters->userParameterDouble);
+      append_user_parameter(n1,"userParameterString",h.userParameters->userParameterString);
+      append_user_parameter(n1,"userParameterBase64",h.userParameters->userParameterBase64);
+    }
+
     doc.save(o);
   }
 
diff --git a/xml/ismrmrd_xml.h b/xml/ismrmrd_xml.h
index 2459022..6a9f729 100644
--- a/xml/ismrmrd_xml.h
+++ b/xml/ismrmrd_xml.h
@@ -79,7 +79,7 @@ namespace ISMRMRD
 
   }; 
 
-  struct EXPORTISMRMRDXML SubjectInformation 
+  struct SubjectInformation 
   {
     Optional<std::string> patientName;
     Optional<float> patientWeight_kg;
@@ -101,7 +101,7 @@ namespace ISMRMRD
   struct MeasurementDependency
   {
     std::string dependencyType;
-    std::string dependencyID;
+    std::string measurementID;
   };
 
   struct MeasurementInformation
@@ -113,7 +113,7 @@ namespace ISMRMRD
     Optional<long int> initialSeriesNumber;
     Optional<std::string> protocolName;
     Optional<std::string> seriesDescription;
-    std::vector<MeasurementDependency> measurementDepencency;
+    std::vector<MeasurementDependency> measurementDependency;
   };
 
   
@@ -253,7 +253,7 @@ namespace ISMRMRD
   {
     Optional<std::string> imageType;
     Optional<std::string> scanningSequence;
-    Optional<std::string> sequenceVartiant;
+    Optional<std::string> sequenceVariant;
     Optional<std::string> scanOptions;
     Optional<std::string> mrAcquisitionType;
     Optional<long> echoTrainLength;
@@ -266,7 +266,7 @@ namespace ISMRMRD
   {
     std::string studyInstanceUID;
     Optional<std::string> seriesInstanceUIDRoot;
-    Optional<std::string> frameOfReference;
+    Optional<std::string> frameOfReferenceUID;
     std::vector<ReferencedImageSequence> referencedImageSequence;
     Optional<MRImageModule> mrImageModule;
   };
@@ -292,7 +292,7 @@ namespace ISMRMRD
     Optional<StudyInformation> studyInformation;
     Optional<MeasurementInformation> measurementInformation;
     Optional<AcquisitionSystemInformation> acquisitionSystemInformation;
-    Optional<ExperimentalConditions> experimentalConditions;
+    ExperimentalConditions experimentalConditions;
     std::vector<Encoding> encoding;
     Optional<ParallelImaging> parallelImaging;
     Optional<SequenceParameters> sequenceParameters;
@@ -302,8 +302,9 @@ namespace ISMRMRD
 
 
 
-  void deserialize(const char* xml, IsmrmrdHeader& h);
-  void serialize(const IsmrmrdHeader& h, std::ostream& o);
+  EXPORTISMRMRDXML void deserialize(const char* xml, IsmrmrdHeader& h);
+  EXPORTISMRMRDXML void serialize(const IsmrmrdHeader& h, std::ostream& o);
+
 
   /*
   class IsmrmrdHeaderProxy 
diff --git a/xml/dump_ismrmrd_header.cpp b/xml/test_ismrmrd_xml.cpp
similarity index 54%
rename from xml/dump_ismrmrd_header.cpp
rename to xml/test_ismrmrd_xml.cpp
index a22dc50..db9abfe 100644
--- a/xml/dump_ismrmrd_header.cpp
+++ b/xml/test_ismrmrd_xml.cpp
@@ -1,29 +1,42 @@
 #include <iostream>
-#include "ismrmrd.h"
-#include "ismrmrd_hdf5.h"
+#include <fstream>
+#include <streambuf>
 #include "ismrmrd_xml.h"
+#include "pugixml.hpp"
 
 int main(int argc, char** argv)
 {
 
   if (argc < 2) {
-    std::cout << "Usage:\n\tdump_ismrmrd_header <ISMRMRD_FILE_NAME>\n" << std::endl;
+    std::cout << "Usage:\n\ttest_ismrmrd_xml <ismrmrd_xml_header.xml>\n" << std::endl;
     return -1;
   }
 
   std::string filename(argv[1]);
 
-  std::cout << "ISMRMRD Header Dump: " << filename << std::endl;
+  std::cout << "ISMRMRD Header: " << filename << std::endl;
 
-  ISMRMRD::IsmrmrdDataset d(filename.c_str(),"/dataset");
-  
-  boost::shared_ptr<std::string> xml = d.readHeader();
-  //std::cout << "XML: \n" << *xml << std::endl;
+  std::ifstream t(filename.c_str());
+  std::string xml((std::istreambuf_iterator<char>(t)),
+		  std::istreambuf_iterator<char>());
 
   ISMRMRD::IsmrmrdHeader h;
+  deserialize(xml.c_str(),h);
+
+  pugi::xml_document doc;
+  pugi::xml_parse_result result = doc.load(xml.c_str());
+
+  std::ofstream raw("raw.xml");
+  std::ofstream proc("processed.xml");
+  
+
+  doc.save(raw);
+  serialize(h,proc);
+
+  /*
   deserialize(xml->c_str(),h);
 
-  std::cout << "Resonance frequency: " << h.experimentalConditions.get().H1resonanceFrequency_Hz << std::endl;
+  std::cout << "Resonance frequency: " << h.experimentalConditions.H1resonanceFrequency_Hz << std::endl;
   std::cout << "TR: " << h.sequenceParameters.get().TR[0] << std::endl;
   if (h.userParameters) {
     std::cout << "User parameters found" << std::endl;
@@ -34,5 +47,6 @@ int main(int argc, char** argv)
   }
 
   serialize(h,std::cout);
+  */
   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