[ismrmrd] 163/177: Fixed Matlab xmlhdr deserialize. Simple Matlab examples are now working again.

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:02:15 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 b4c9d62ebc0047c4e1215ab496b1e6e85a362091
Author: Souheil Inati <souheil.inati at nih.gov>
Date:   Fri Oct 24 11:01:25 2014 -0400

    Fixed Matlab xmlhdr deserialize.  Simple Matlab examples are now working again.
---
 examples/matlab/test_create_dataset.m |   2 +-
 examples/matlab/test_recon_dataset.m  |  57 +++--
 matlab/+ismrmrd/+xml/deserialize.m    | 383 +++++++++++++++++++++++++++-------
 3 files changed, 331 insertions(+), 111 deletions(-)

diff --git a/examples/matlab/test_create_dataset.m b/examples/matlab/test_create_dataset.m
index 8fe20b7..71b7a6c 100644
--- a/examples/matlab/test_create_dataset.m
+++ b/examples/matlab/test_create_dataset.m
@@ -5,7 +5,7 @@
 % data from 4 coils from a single slice object that looks like a square
 
 % File Name
-filename = 'matlabtestdata.h5';
+filename = 'testdata.h5';
 
 % Create an empty ismrmrd dataset
 if exist(filename,'file')
diff --git a/examples/matlab/test_recon_dataset.m b/examples/matlab/test_recon_dataset.m
index 00cd4e5..70e0078 100644
--- a/examples/matlab/test_recon_dataset.m
+++ b/examples/matlab/test_recon_dataset.m
@@ -11,6 +11,7 @@
 % Limitations:
 %   only works with a single encoded space
 %   fully sampled k-space (no partial fourier or undersampling)
+%   multiple repetitions
 %   doesn't handle averages, phases, segments and sets
 %   ignores noise scans (no pre-whitening)
 % 
@@ -30,7 +31,7 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%% 
 filename = 'testdata.h5';
 if exist(filename, 'file')
-    dset = ismrmrd.IsmrmrdDataset(filename, 'dataset');
+    dset = ismrmrd.Dataset(filename, 'dataset');
 else
     error(['File ' filename ' does not exist.  Please generate it.'])
 end
@@ -39,54 +40,50 @@ end
 %% Read some fields from the XML header %%
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % We need to check if optional fields exists before trying to read them
-% Some functions return java.lang.Integer type and we convert to double
+
+hdr = ismrmrd.xml.deserialize(dset.readxml);
 
 %% Encoding and reconstruction information
 % Matrix size
-enc_Nx = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getX;
-enc_Ny = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getY;
-enc_Nz = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getMatrixSize.getZ;
-rec_Nx = dset.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getX;
-rec_Ny = dset.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getY;
-rec_Nz = dset.xmlhdr.getEncoding.get(0).getReconSpace.getMatrixSize.getZ;
+enc_Nx = hdr.encoding.encodedSpace.matrixSize.x;
+enc_Ny = hdr.encoding.encodedSpace.matrixSize.y;
+enc_Nz = hdr.encoding.encodedSpace.matrixSize.z;
+rec_Nx = hdr.encoding.reconSpace.matrixSize.x;
+rec_Ny = hdr.encoding.reconSpace.matrixSize.y;
+rec_Nz = hdr.encoding.reconSpace.matrixSize.z;
 
 % Field of View
-enc_FOVx = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getFieldOfViewMm.getX;
-enc_FOVy = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getFieldOfViewMm.getY;
-enc_FOVz = dset.xmlhdr.getEncoding.get(0).getEncodedSpace.getFieldOfViewMm.getZ;
-rec_FOVx = dset.xmlhdr.getEncoding.get(0).getReconSpace.getFieldOfViewMm.getX;
-rec_FOVy = dset.xmlhdr.getEncoding.get(0).getReconSpace.getFieldOfViewMm.getY;
-rec_FOVz = dset.xmlhdr.getEncoding.get(0).getReconSpace.getFieldOfViewMm.getZ;
-
-% Number of slices
-if isempty(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getSlice)
-    nSlices = 1;
-else
-  nSlices = dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getSlice.getMaximum;
-  if nSlices == 0;
+enc_FOVx = hdr.encoding.encodedSpace.fieldOfView_mm.x;
+enc_FOVy = hdr.encoding.encodedSpace.fieldOfView_mm.y;
+enc_FOVz = hdr.encoding.encodedSpace.fieldOfView_mm.z;
+rec_FOVx = hdr.encoding.reconSpace.fieldOfView_mm.x;
+rec_FOVy = hdr.encoding.reconSpace.fieldOfView_mm.y;
+rec_FOVz = hdr.encoding.reconSpace.fieldOfView_mm.z;
+
+% Number of slices, coils, repetitions, contrasts etc.
+% We have to wrap the following in a try/catch because a valid xml header may
+% not have an entry for some of the parameters
+
+try
+  nSlices = hdr.encoding.encodingLimits.slice.maximum + 1;
+catch
     nSlices = 1;
-  end
 end
 
-% Number of coils, repetitions, contrasts etc.
-% We have to wrap this in a try/catch because a valid xml header may
-% not have an entry for the the parameter in question
-% Encoding limit values in the XML header are zero based
-% Java return values needed to be converte to matlab types for math.
 try 
-    nCoils = double(dset.xmlhdr.getAcquisitionSystemInformation.getReceiverChannels);
+    nCoils = hdr.acquisitionSystemInformation.receiverChannels;
 catch
     nCoils = 1;
 end
 
 try
-    nReps = double(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getRepetition.getMaximum) + 1;
+    nReps = hdr.encoding.encodingLimits.repetition.maximum + 1;
 catch
     nReps = 1;
 end
 
 try
-    nContrasts = double(dset.xmlhdr.getEncoding.get(0).getEncodingLimits.getContrast.getMaximum) + 1;
+    nContrasts = hdr.encoding.encodingLimits.contrast.maximum + 1 + 1;
 catch
     nContrasts = 1;
 end
diff --git a/matlab/+ismrmrd/+xml/deserialize.m b/matlab/+ismrmrd/+xml/deserialize.m
index f167749..d52b8b0 100644
--- a/matlab/+ismrmrd/+xml/deserialize.m
+++ b/matlab/+ismrmrd/+xml/deserialize.m
@@ -2,128 +2,351 @@ function [header] = deserialize(xmlstring)
 %DESERIALIZE Summary of this function goes here
 %   Detailed explanation goes here
 
-% Get a parser
-db = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
+    % Get a parser
+    db = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();
 
-% Turn the string into a stream
-isrc = org.xml.sax.InputSource();
-isrc.setCharacterStream(java.io.StringReader(xmlstring))
+    % Turn the string into a stream
+    isrc = org.xml.sax.InputSource();
+    isrc.setCharacterStream(java.io.StringReader(xmlstring))
 
-% Parse it
-dom = db.parse(isrc);
+    % Parse it
+    dom = db.parse(isrc);
 
-% Get the root element
-rootNode = dom.getDocumentElement();
+    % Get the root element
+    rootNode = dom.getDocumentElement();
 
-% Initialize an empty struct
-header = struct;
+    % Fill it
+    header = parseNode(rootNode);
 
-% The header always has a few nodes (e.g. encoding is required)
-childNodes = getChildNodes(rootNode);
+end
+
+% ----- Subfunction parseChild -----
+function info = parseNode(theNode)
+
+% Walk down the tree
+childNodes = getChildNodes(theNode);
 numChildNodes = getLength(childNodes);
 
+info = struct;
+
 for n = 1:numChildNodes
     theChild = item(childNodes,n-1);
     name = char(getNodeName(theChild));
-    
-    if strcmp(name,'version')
-        header.version = str2num(getTextContent(theChild));
-    end
 
-    if strcmp(name,'subjectInformation')
-        header.subjectInformation = parseSubjectInformation(theChild);
-    end
-    
-    if strcmp(name,'studyInformation')
-        header.studyInformation = parseStudyInformation(theChild);
+    %Some elements occure more than once
+    if isfield(info,name)
+        num = length(info.(name))+1;
+    else
+        num = 1;
     end
-    
-    if strcmp(name,'measurementInformation')
-        header.measurementInformation = parseMeasurementInformation(theChild);
+
+    if strcmp(name, 'encoding')
+        if num == 1
+            info.encoding = struct('encodedSpace',struct,'reconSpace',struct, ...
+                'encodingLimits', struct, 'trajectory', '', ...
+                'trajectoryDescription', struct,  ...
+                'parallelImaging', struct, 'echoTrainLength', 0);
+        end
+        temp = parseNode(theChild);
+        fnames = fieldnames(temp);
+        for f = 1:length(fnames)
+            info.encoding(num).(fnames{f}) = temp.(fnames{f});
+        end
+        continue;
     end
     
-    if strcmp(name,'acquisitionSystemInformation')
-        header.acquisitionSystemInformation = parseAcquisitionSystemInformation(theChild);
+    if isCompoundType(name)        
+        if num == 1
+            info.(name) = parseNode(theChild);
+        else
+            info.(name)(num) = parseNode(theChild);
+        end
+        continue;
     end
-    
-    if strcmp(name,'experimentalConditions')
-        header.experimentalConditions = parseExperimentalConditions(theChild);
+
+    if isUserParameterType(name)
+        if num == 1
+            info.(name) = parseUserParameter(theChild);
+        else
+            info.(name)(num) = parseUserParameter(theChild);
+        end
+        continue;
     end
 
-    if strcmp(name,'encoding')
-        % there can be multiple encodings but there must be at least one
-        if isfield(header, 'encoding')
-            nenc = length(header.encoding);
+    if isStringType(name)
+        if num == 1
+            info.(name) = char(getTextContent(theChild));
         else
-            nenc = 1;
+            info.(name)(num) = char(getTextContent(theChild));
         end
-        header.encoding(nenc) = parseEncoding(theChild);
+        continue;
     end
 
-    if strcmp(name,'sequenceParameters')
-        header.sequenceParameters = parseSequenceParameters(theChild);
+    if isNumericalType(name)
+        if num == 1
+            info.(name) = str2num(getTextContent(theChild));
+        else
+            info.(name)(num) = str2num(getTextContent(theChild));
+        end
+        continue;
     end
 
-    if strcmp(name,'userParameters')
-        header.userParameters = parseUserParameters(theChild);
+    if isDateType(name)
+        if num == 1
+            info.(name) = char(getTextContent(theChild));
+        else
+            info.(name)(num) = char(getTextContent(theChild));
+        end
+        continue;
     end
 
 end
 
 end
 
-% ----- Subfunction parseSubjectInformation -----
-function subjectInformation = parseSubjectInformation(theNode)
-    subjectInformation = struct;
-end
+%%%%%%%%%%%%%%%%%%%
+function info = parseUserParameter(theNode)
 
-% ----- Subfunction parseStudyInformation -----
-function studyInformation = parseStudyInformation(theNode)
-    studyInformation = struct;
-end
+    paramType = char(getNodeName(theNode));
+    childNodes = getChildNodes(theNode);
+    numChildNodes = getLength(childNodes);
+    
+    info = struct;
+    
+    for n = 1:numChildNodes
+        theChild = item(childNodes,n-1);
+        if strcmp(getNodeName(theChild),'name')
+            info.name = char(getTextContent(theChild));
+        end
+        if strcmp(getNodeName(theChild),'value')
+            if strcmp(paramType, 'userParameterLong')
+                info.value = str2num(getTextContent(theChild));
+            end
 
-% ----- Subfunction parseMeasurementInformation -----
-function measurementInformation = parseMeasurementInformation(theNode)
-    measurementInformation = struct;
-end
+            if strcmp(paramType, 'userParameterDouble')
+                info.value = str2num(getTextContent(theChild));
+            end
+
+            if strcmp(paramType, 'userParameterString')
+                info.value = char(getTextContent(theChild));
+            end
 
-% ----- Subfunction parseAcquisitionSystemInformation -----
-function acquisitionSystemInformation = parseAcquisitionSystemInformation(theNode)
-    acquisitionSystemInformation = struct;
+            if strcmp(paramType, 'userParameterBase64')
+                info.value = char(getTextContent(theChild));
+            end
+        end
+    end
 end
 
-% ----- Subfunction parseExperimentalConditions -----
-function experimentalConditions = parseExperimentalConditions(theNode)
+% ----- Type specific functions ----
+function status = isCompoundType(name)
 
-% Walk down the tree
-childNodes = getChildNodes(theNode);
-numChildNodes = getLength(childNodes);
+    % treat encoding separately
+    headerNodeNames = { ...
+        'version', ...
+        'subjectInformation', ...
+        'studyInformation', ...
+        'measurementInformation', ...
+        'acquisitionSystemInformation', ...
+        'experimentalConditions', ...
+        'encoding', ...
+        'sequenceParameters', ...
+        'userParameters', ...
+        'measurementDependency', ...
+        'referencedImageSequence', ...
+        'encodedSpace', ...
+        'reconSpace', ...
+        'encodingLimits', ...
+        'trajectoryDescription', ...
+        'echoTrainLength', ...
+        'matrixSize', ...
+        'fieldOfView_mm', ...
+        'kspace_encoding_step_0', ...
+        'kspace_encoding_step_1', ...
+        'kspace_encoding_step_2', ...
+        'average', ...
+        'slice', ...
+        'contrast', ...
+        'phase', ...
+        'repetition', ...
+        'set', ...
+        'segment'};
+    
+    status = ismember(name, headerNodeNames);
+end
 
-experimentalConditions = struct;
+function status = isNumericalType(name)
+    headerNumericalTypes = { ...
+      'version', ...
+      'patientWeight', ...
+      'accessionNumber', ...
+      'initialSeriesNumber', ...
+      'systemFieldStrength_T', ...
+      'relativeReceiverNoiseBandwidth', ...
+      'receiverChannels', ...
+      'H1resonanceFrequency_Hz', ...
+      'TR', ...
+      'TE', ...
+      'TI', ...
+      'flipAngle_deg', ...
+      'x', 'y', 'z', ...
+      'minimum', 'maximum', 'center'};
+  
+    status = ismember(name, headerNumericalTypes);
+end
 
-for n = 1:numChildNodes
-    theChild = item(childNodes,n-1);
-    name = char(getNodeName(theChild));
+function status = isStringType(name)
+    headerStringTypes = {...
+      'patientName', ...
+      'patientID', ...
+      'patientGender', ...
+      'studyID', ...
+      'referringPhysicianName', ...
+      'studyDescription', ...
+      'studyInstanceUID', ...
+      'measurementID', ...
+      'patientPosition', ...
+      'protocolName', ...
+      'seriesDescription', ...
+      'seriesInstanceUIDRoot', ...
+      'frameOfReferenceUID', ...
+      'referencedSOPInstanceUID', ...
+      'dependencyType', ...
+      'measurementID', ...
+      'systemVendor', ...
+      'systemModel', ...
+      'institutionName', ...
+      'stationName', ...
+      'trajectory'};
+      %'calibrationMode',...
+      %'interleavingDimension'};
 
-    if strcmp(name,'H1resonanceFrequency_Hz')
-        experimentalConditions.H1resonanceFrequency_Hz = str2num(getTextContent(theChild));
-        break;
-    end
+      status = ismember(name, headerStringTypes);
 end
 
+function status = isDateType(name)
+    headerDateTypes = {...
+      'patientBirthdate', ...
+      'studyDate', ...
+      'studyTime', ...
+      'seriesDate', ...
+      'seriesTime'};
+    status = ismember(name, headerDateTypes);
 end
 
-% ----- Subfunction parseEncoding -----
-function encoding = parseEncoding(theNode)
-    encoding = struct;
-end
+function status = isUserParameterType(name)
+    typeNames =  { ...
+        'userParameterLong', ...
+        'userParameterDouble', ...
+        'userParameterString', ....
+        'userParameterBase64'};
 
-% ----- Subfunction parseSequenceParameters -----
-function sequenceParameters = parseSequenceParameters(theNode)
-    sequenceParameters = struct;
+    status = ismember(name, typeNames);
 end
+% 
+%   <xs:complexType name="encoding">
+%     <xs:all>
+%       <xs:element maxOccurs="1" minOccurs="1" name="encodedSpace" type="encodingSpaceType"/>
+%       <xs:element maxOccurs="1" minOccurs="1" name="reconSpace" type="encodingSpaceType"/>
+%       <xs:element maxOccurs="1" minOccurs="1" name="encodingLimits" type="encodingLimitsType"/>
+%       <xs:element maxOccurs="1" minOccurs="1" name="trajectory" type="trajectoryType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="trajectoryDescription" type="trajectoryDescriptionType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="parallelImaging" type="parallelImagingType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="echoTrainLength" type="xs:long"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="encodingSpaceType">
+%     <xs:all>
+%       <xs:element maxOccurs="1" minOccurs="1" name="matrixSize" type="matrixSize"/>
+%       <xs:element maxOccurs="1" minOccurs="1" name="fieldOfView_mm" type="fieldOfView_mm"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="matrixSize">
+%     <xs:sequence>
+%       <xs:element default="1" maxOccurs="1" minOccurs="1" name="x" type="xs:unsignedShort"/>
+%       <xs:element default="1" maxOccurs="1" minOccurs="1" name="y" type="xs:unsignedShort"/>
+%       <xs:element default="1" maxOccurs="1" minOccurs="1" name="z" type="xs:unsignedShort"/>
+%     </xs:sequence>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="fieldOfView_mm">
+%     <xs:sequence>
+%       <xs:element maxOccurs="1" minOccurs="1" name="x" type="xs:float"/>
+%       <xs:element maxOccurs="1" minOccurs="1" name="y" type="xs:float"/>
+%       <xs:element maxOccurs="1" minOccurs="1" name="z" type="xs:float"/>
+%     </xs:sequence>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="limitType">
+%     <xs:all>
+%       <xs:element default="0" name="minimum" type="xs:unsignedShort"/>
+%       <xs:element default="0" name="maximum" type="xs:unsignedShort"/>
+%       <xs:element default="0" name="center" type="xs:unsignedShort"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="encodingLimitsType">
+%     <xs:all>
+%       <xs:element maxOccurs="1" minOccurs="0" name="kspace_encoding_step_0" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="kspace_encoding_step_1" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="kspace_encoding_step_2" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="average" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="slice" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="contrast" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="phase" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="repetition" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="set" type="limitType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="segment" type="limitType"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:simpleType name="trajectoryType">
+%     <xs:restriction base="xs:string">
+%       <xs:enumeration value="cartesian"/>
+%       <xs:enumeration value="epi"/>
+%       <xs:enumeration value="radial"/>
+%       <xs:enumeration value="goldenangle"/>
+%       <xs:enumeration value="spiral"/>
+%       <xs:enumeration value="other"/>
+%     </xs:restriction>
+%   </xs:simpleType>
+% 
+%   <xs:complexType name="trajectoryDescriptionType">
+%     <xs:sequence>
+%       <xs:element maxOccurs="1" minOccurs="1" name="identifier" type="xs:string"/>
+%       <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterLong" type="userParameterLongType"/>
+%       <xs:element maxOccurs="unbounded" minOccurs="0" name="userParameterDouble" type="userParameterDoubleType"/>
+%       <xs:element maxOccurs="1" minOccurs="0" name="comment" type="xs:string"/>
+%     </xs:sequence>
+%   </xs:complexType>
 
-% ----- Subfunction parseUserParameters -----
-function userParameters = parseUserParameters(theNode)
-    userParameters = struct;
-end
+% 
+%   <xs:complexType name="userParameterLongType">
+%     <xs:all>
+%       <xs:element name="name" type="xs:string"/>
+%       <xs:element name="value" type="xs:long"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="userParameterDoubleType">
+%     <xs:all>
+%       <xs:element name="name" type="xs:string"/>
+%       <xs:element name="value" type="xs:double"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="userParameterStringType">
+%     <xs:all>
+%       <xs:element name="name" type="xs:string"/>
+%       <xs:element name="value" type="xs:string"/>
+%     </xs:all>
+%   </xs:complexType>
+% 
+%   <xs:complexType name="userParameterBase64Type">
+%     <xs:all>
+%       <xs:element name="name" type="xs:string"/>
+%       <xs:element name="value" type="xs:base64Binary"/>
+%     </xs:all>
+%   </xs:complexType>

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