[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