[ismrmrd] 250/281: changes to XML functionality

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:01:20 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 74ddb5ae4a41799d2d3172b6b8ab1e553fadba8d
Author: Michael S. Hansen <michael.hansen at nih.gov>
Date:   Tue Aug 12 12:37:46 2014 -0400

    changes to XML functionality
---
 xml/dump_ismrmrd_header.cpp |  35 ++++++
 xml/ismrmrd_xml.cpp         | 282 +++++++++++++++++++++++++++++++++++++++++++-
 xml/ismrmrd_xml.h           |  46 ++++----
 3 files changed, 336 insertions(+), 27 deletions(-)

diff --git a/xml/dump_ismrmrd_header.cpp b/xml/dump_ismrmrd_header.cpp
new file mode 100644
index 0000000..010906d
--- /dev/null
+++ b/xml/dump_ismrmrd_header.cpp
@@ -0,0 +1,35 @@
+#include <iostream>
+#include "ismrmrd.h"
+#include "ismrmrd_hdf5.h"
+#include "ismrmrd_xml.h"
+
+int main(int argc, char** argv)
+{
+
+  if (argc < 2) {
+    std::cout << "Usage:\n\tdump_ismrmrd_header <ISMRMRD_FILE_NAME>\n" << std::endl;
+    return -1;
+  }
+
+  std::string filename(argv[1]);
+
+  std::cout << "ISMRMRD Header Dump: " << 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;
+
+  ISMRMRD::IsmrmrdHeaderProxy hp(xml->c_str());
+
+  std::cout << "Resonance frequency: " << hp.h().experimentalConditions.get().H1resonanceFrequency_Hz << std::endl;
+  std::cout << "TR: " << hp.h().sequenceParameters.get().TR[0] << std::endl;
+  //for (size_t i = 0; i < hp.h().userParameters.get().userParameterLong.size(); i++) {
+    //std::cout << "UserLong: " << hp.h().userParameters.get().userParameterLong[i].name.size() << std::endl;
+    /*
+    std::cout << "UserLong: " << hp.h().userParameters.get().userParameterLong[i].name.c_str() << ", " 
+	      << hp.h().userParameters.get().userParameterLong[i].value << std::endl;
+    */
+  //}
+  return 0;
+}
diff --git a/xml/ismrmrd_xml.cpp b/xml/ismrmrd_xml.cpp
index 30511a3..29586af 100644
--- a/xml/ismrmrd_xml.cpp
+++ b/xml/ismrmrd_xml.cpp
@@ -73,6 +73,152 @@ namespace ISMRMRD
     return o;
   }
 
+  String parse_string(pugi::xml_node& n, const char* child) 
+  {
+    String r(n.child_value(child));
+    if (r.size() == 0) throw std::runtime_error("Null length string");
+    return r;
+  }
+
+  Optional<String> parse_optional_string(pugi::xml_node& n, const char* child)
+  {
+    String s(n.child_value(child));
+    Optional<String> r;
+    if (s.size()) r = s;
+    return r;
+  }
+
+  Optional<float> parse_optional_float(pugi::xml_node& n, const char* child)
+  {
+    Optional<float> r;
+    pugi::xml_node nc = n.child(child);
+    if (nc) {
+      r = std::atof(nc.child_value());
+    }
+    return r;
+  }
+
+  Optional<long> parse_optional_long(pugi::xml_node& n, const char* child) {
+    Optional<long> r;
+    pugi::xml_node nc = n.child(child);
+    if (nc) {
+      r = std::atoi(nc.child_value());
+    }
+    return r;
+  }
+
+  Optional<unsigned short> parse_optional_ushort(pugi::xml_node& n, const char* child) {
+    Optional<unsigned short> r;
+    pugi::xml_node nc = n.child(child);
+    if (nc) {
+      r = static_cast<unsigned short>(std::atoi(nc.child_value()));
+    }
+    return r;
+  }
+
+  Vector<float> parse_vector_float(pugi::xml_node& n, const char* child) 
+  {
+    Vector<float> r;
+    
+    pugi::xml_node nc = n.child(child);
+
+    while (nc) {
+      float f = std::atof(nc.child_value());
+      r.push_back(f);
+      nc = nc.next_sibling(child);
+    }
+    
+    return r;
+  }
+
+  Vector<String> parse_vector_string(pugi::xml_node& n, const char* child)
+  {
+    Vector<String> r;
+    pugi::xml_node nc = n.child(child);
+    while (nc) {
+      String s = nc.child_value();
+      r.push_back(s);
+      nc = nc.next_sibling(child);
+    }
+    return r;
+  }
+
+  Vector<UserParameterLong> parse_user_parameter_long(pugi::xml_node& n, const char* child) 
+  {
+    Vector<UserParameterLong> r;
+    pugi::xml_node nc = n.child(child);
+    while (nc) {
+      UserParameterLong v;
+      pugi::xml_node name = nc.child("name");
+      pugi::xml_node value = nc.child("value");
+
+      if (!name || !value) {
+	throw std::runtime_error("Malformed user parameter (long)");
+      }
+
+      v.name = String(name.child_value());
+      v.value = std::atoi(value.child_value());
+
+      r.push_back(v);
+
+      nc = nc.next_sibling(child);
+    }
+    return r;
+  }
+
+  Vector<UserParameterDouble> parse_user_parameter_double(pugi::xml_node& n, const char* child) 
+  {
+    Vector<UserParameterDouble> r;
+    pugi::xml_node nc = n.child(child);
+    while (nc) {
+      UserParameterDouble v;
+      pugi::xml_node name = nc.child("name");
+      pugi::xml_node value = nc.child("value");
+
+      if (!name || !value) {
+	throw std::runtime_error("Malformed user parameter (double)");
+      }
+
+      char buffer[10000];
+      memcpy(buffer,name.child_value(),strlen(name.child_value())+1);
+      String tmp("BLAH");
+      v.name = "BLAKKK";//tmp;//String("BLAH");//name.child_value());
+      v.value = std::atof(value.child_value());
+
+      r.push_back(v);
+
+      nc = nc.next_sibling(child);
+    }
+   
+    return r;
+  }
+
+  Vector<UserParameterString> parse_user_parameter_string(pugi::xml_node& n, const char* child) 
+  {
+    Vector<UserParameterString> r;
+    pugi::xml_node nc = n.child(child);
+    while (nc) {
+      UserParameterString v;
+      pugi::xml_node name = nc.child("name");
+      pugi::xml_node value = nc.child("value");
+
+      if (!name || !value) {
+	throw std::runtime_error("Malformed user parameter (string)");
+      }
+
+      v.name = String(name.child_value());
+      v.value = String(value.child_value());
+
+      r.push_back(v);
+
+      nc = nc.next_sibling(child);
+    }
+   
+    return r;
+  }
+
+  //End of utility functions for deserializing header
+
   void IsmrmrdHeaderProxy::deserialize(const char* xml) 
   {
     pugi::xml_document doc;
@@ -89,7 +235,7 @@ namespace ISMRMRD
       pugi::xml_node encoding = root.child("encoding");
       pugi::xml_node parallelImaging = root.child("parallelImaging");
       pugi::xml_node sequenceParameters = root.child("sequenceParameters");
-      pugi::xml_node dicomeParameters = root.child("dicomParameters");
+      pugi::xml_node dicomParameters = root.child("dicomParameters");
       pugi::xml_node userParameters = root.child("userParameters");
       
       //Parsing experimentalConditions
@@ -138,36 +284,162 @@ namespace ISMRMRD
 	  if (!trajectory) {
 	    throw std::runtime_error("trajectory not found in encoding section");
 	  } else {
-	    e.trajectory = String(trajectory.value());
+	    e.trajectory = String(encoding.child_value("trajectory"));
 	  }
 
 	  pugi::xml_node trajectoryDescription = encoding.child("trajectoryDescription");
 	  
 	  if (trajectoryDescription) {
+	    TrajectoryDescription traj;
+	    try {
+	      traj.identifier = parse_string(trajectoryDescription,"identifier");
+	      traj.userParameterLong = 
+		parse_user_parameter_long(trajectoryDescription, "userParameterLong");
+	      traj.userParameterDouble = 
+		parse_user_parameter_double(trajectoryDescription, "userParameterDouble");
+	      traj.comment = parse_optional_string(trajectoryDescription, "comment");
+	      e.trajectoryDescription = traj;
+	    } catch (std::runtime_error& e) {
+	      std::cout << "Error parsing trajectory description" << std::endl;
+	      throw;
+	    }
 	    
 	  }
 
+	  h_.encoding.push_back(e);
 	  encoding = encoding.next_sibling("encoding");
 	}
 
       }
 
       if (subjectInformation) {
-
+	SubjectInformation info;
+	info.patientName = parse_optional_string(subjectInformation, "patientName");
+	info.patientWeight_kg = parse_optional_float(subjectInformation, "patientWeight_kg");
+	info.patientID = parse_optional_string(subjectInformation, "patientID");
+	info.patientBirthdate = parse_optional_string(subjectInformation, "patientBirthdate");
+	info.patientGender = parse_optional_string(subjectInformation, "patientGender");
+	h_.subjectInformation = info;
       }
 
       if (studyInformation) {
-
+	StudyInformation info;
+	info.studyDate = parse_optional_string(studyInformation,"studyDate");
+	info.studyTime = parse_optional_string(studyInformation,"studyTime");
+	info.studyID = parse_optional_string(studyInformation,"studyID");
+	info.accessionNumber = parse_optional_long(studyInformation,"accessionNumber");
+	info.referringPhysicianName = parse_optional_string(studyInformation,"referringPhysicianName");
+	info.studyDescription = parse_optional_string(studyInformation,"studyDescription");
+	h_.studyInformation = info;
       }
 
       if (measurementInformation) {
-
+	MeasurementInformation info;
+	info.measurementID = parse_optional_string(measurementInformation,"measurementID");
+	info.seriesDate = parse_optional_string(measurementInformation, "seriesDate");
+	info.seriesTime = parse_optional_string(measurementInformation, "seriesTime");
+	info.patientPosition = parse_string(measurementInformation, "patientPosition");
+	info.initialSeriesNumber = parse_optional_long(measurementInformation, "initialSeriesNumber");
+	info.protocolName = parse_optional_string(measurementInformation, "protocolName");
+	info.seriesDescription = parse_optional_string(measurementInformation, "seriesDescription");
+	
+	pugi::xml_node measurementDependency = measurementInformation.child("measurementDependency");
+	while (measurementDependency) {
+	  try {
+	    MeasurementDependency d;
+	    d.dependencyID = parse_string(measurementDependency,"dependencyID");
+	    d.dependencyType = parse_string(measurementDependency,"dependencyType");
+	    info.measurementDepencency.push_back(d);
+	  } catch (std::runtime_error& e) {
+	    std::cout << "Error parsing measurement dependency: " << e.what() << std::endl;
+	    throw;
+	  } 
+	  measurementDependency = measurementDependency.next_sibling("measurementDependency");
+	}
+	h_.measurementInformation = info;
       }
 
       if (acquisitionSystemInformation) {
+	AcquisitionSystemInformation info;
+	info.systemVendor = parse_optional_string(acquisitionSystemInformation, "systemVendor");
+	info.systemModel = parse_optional_string(acquisitionSystemInformation, "systemModel");
+	info.systemFieldStrength_T = parse_optional_float(acquisitionSystemInformation, "systemFieldStrength_T");
+	info.relativeReceiverNoiseBandwidth = parse_optional_float(acquisitionSystemInformation, "relativeReceiverNoiseBandwidth");
+	info.receiverChannels = parse_optional_ushort(acquisitionSystemInformation, "receiverChannels");
+	info.institutionName = parse_optional_string(acquisitionSystemInformation, "institutionName");
+	info.stationName = parse_optional_string(acquisitionSystemInformation, "stationName");
+
+	h_.acquisitionSystemInformation = info;
+      }
+
+      if (parallelImaging) {
+	ParallelImaging info;
+	
+	pugi::xml_node accelerationFactor = parallelImaging.child("accelerationFactor");
+	if (!accelerationFactor) {
+	  throw std::runtime_error("Unable to accelerationFactor section in parallelImaging");
+	} else {
+	  info.accelerationFactor.kspace_encoding_step_1 = static_cast<unsigned short>(std::atoi(accelerationFactor.child_value("kspace_encoding_step_1")));
+	  info.accelerationFactor.kspace_encoding_step_2 = static_cast<unsigned short>(std::atoi(accelerationFactor.child_value("kspace_encoding_step_2")));
+	}
 
+	info.calibrationMode = parse_optional_string(parallelImaging,"calibrationMode");
+	info.interleavingDimension = parse_optional_string(parallelImaging,"interleavingDimension");
+	h_.parallelImaging = info;
       }
 
+      if (sequenceParameters) {
+	SequenceParameters p;
+	p.TR = parse_vector_float(sequenceParameters,"TR");
+	p.TE = parse_vector_float(sequenceParameters,"TE");
+	p.TI = parse_vector_float(sequenceParameters,"TI");
+	h_.sequenceParameters = p;
+      }
+
+      if (dicomParameters) { 
+	DicomParameters p;
+	p.studyInstanceUID = parse_string(dicomParameters,"studyInstanceUID");
+	p.seriesInstanceUIDRoot = parse_optional_string(dicomParameters,"seriesInstanceUIDRoot");
+	p.frameOfReference = 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");
+	if (ri) {
+	  pugi::xml_node ric = ri.child("referencedSOPInstanceUID");
+	  while (ric) {
+	    ReferencedImageSequence r;
+	    r.referencedSOPInstanceUID = ric.child_value();
+	    p.referencedImageSequence.push_back(r);
+	    ric = ric.next_sibling("referenceSOPInstanceIUID");
+	  }
+	}
+	
+	pugi::xml_node mrimageModule = dicomParameters.child("MRImageModule");
+	if (mrimageModule) {
+	  MRImageModule m;
+	  m.imageType = parse_optional_string(mrimageModule,"imageType");
+	  m.scanningSequence = parse_optional_string(mrimageModule, "scanningSequence");
+	  m.sequenceVartiant = 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");
+	  m.triggerTime = parse_optional_float(mrimageModule, "triggerTime");
+	  m.flipAngle_deg = parse_optional_float(mrimageModule, "flipAngle_deg");
+	  m.freqEncodingDirection = parse_optional_string(mrimageModule, "freqEncodingDirection");
+	  p.mrImageModule = m;
+	}
+	h_.dicomParameters = p;
+      }
+
+
+      if (userParameters) {
+	UserParameters p;
+ 	//p.userParameterLong = parse_user_parameter_long(userParameters,"userParameterLong");
+ 	p.userParameterDouble = parse_user_parameter_double(userParameters,"userParameterDouble");
+ 	p.userParameterString = parse_user_parameter_string(userParameters,"userParameterString");
+ 	p.userParameterBase64 = parse_user_parameter_string(userParameters,"userParameterBase64");
+	h_.userParameters = p;
+      }
 
     } else {
       throw std::runtime_error("Root node 'ismrmrdHeader' not found");
diff --git a/xml/ismrmrd_xml.h b/xml/ismrmrd_xml.h
index febc072..9584aa4 100644
--- a/xml/ismrmrd_xml.h
+++ b/xml/ismrmrd_xml.h
@@ -32,7 +32,11 @@ namespace ISMRMRD
       , siz_(0)
       {} 
 
-    Vector(const T* v, size_t len) {
+    Vector(const T* v, size_t len)
+      : v_(0)
+      , len_(0)
+      , siz_(0)
+    {
       allocate(len);
       copy(v,len);
       siz_ = len;
@@ -99,12 +103,16 @@ namespace ISMRMRD
     void allocate(size_t len) {
       T* tmp_v = v_;
       if (len != len_) {
-	//Allocate new array
-	try {
-	  v_ = new T[len];
-	} catch (std::bad_alloc&) {
-	  std::cout << "Error allocating memory in IsmrmrdXmlString" << std::endl;
-	  throw;
+	if (len) {
+	  //Allocate new array
+	  try {
+	    v_ = new T[len];
+	  } catch (std::bad_alloc&) {
+	    std::cout << "Error allocating memory in ISMRMRD::Vector" << std::endl;
+	    throw;
+	  }
+	} else {
+	  v_ = 0;
 	}
 
 	//Copy old content if applicable
@@ -134,26 +142,26 @@ namespace ISMRMRD
    */
   class String : public Vector<char>
   {
-    typedef Vector<char> inherited;
 
   public:
     ///Default constructor
     String() 
+      : Vector()
     {
-      inherited();
     }
     
 
     ///Construct taking null terminated string
-    String(const char* s) 
+    String(const char* s)
+      : Vector(s,strlen(s)+1)
     {
-      inherited(s,strlen(s)+1);
+      std::cout << "Constructing string: " << s << std::endl;
     }
     
     ///Construct taking length of string as input
     String(const char* s, size_t length) 
+      : Vector(length+1)
     {
-      inherited(length+1);
       copy(s,length);
       v_[length-1] = '\0';
     }
@@ -183,7 +191,7 @@ namespace ISMRMRD
 
     ///Get the length of the string
     size_t size() {
-      return inherited::size()-1;
+      return siz_-1;
     }
   };
 
@@ -238,7 +246,7 @@ namespace ISMRMRD
     Optional<String> patientName;
     Optional<float> patientWeight_kg;
     Optional<String> patientID;
-    Optional<String> patientBirthDate;
+    Optional<String> patientBirthdate;
     Optional<String> patientGender;
   };
 
@@ -247,7 +255,7 @@ namespace ISMRMRD
     Optional<String> studyDate;
     Optional<String> studyTime;
     Optional<String> studyID;
-    Optional<long int> accessionNumber;
+    Optional<long> accessionNumber;
     Optional<String> referringPhysicianName;
     Optional<String> studyDescription;
   };
@@ -364,18 +372,12 @@ namespace ISMRMRD
     String value;
   };
 
-  struct UserParameterBase64
-  {
-    String name;
-    String value;
-  };
-
   struct UserParameters
   {
     Vector<UserParameterLong> userParameterLong;
     Vector<UserParameterDouble> userParameterDouble;
     Vector<UserParameterString> userParameterString;
-    Vector<UserParameterBase64> userParameterBase64;
+    Vector<UserParameterString> userParameterBase64;
   };
 
   struct TrajectoryDescription

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