Skip to content

Commit f707a63

Browse files
hakkeltclaude
andauthored
MRIFiles: fix waveformName/waveformType parsed as Float64 instead of String (#292)
* MRIFiles: fix waveformName/waveformType parsed as Float64 instead of String waveformInformation fields waveformName and waveformType are XML strings (waveformType is an enum: ECG, NOISE, GADGETRON_TRIGGER, …). They were incorrectly typed as Float64 in addToDict!, causing ArgumentError: cannot parse "ECG" as Float64 for any ISMRMRD file containing a waveformInformation block. Also fixes a pre-existing test bug in the spiral-data section where write(IOBuffer(), ...) discarded writes to anonymous buffers instead of writing to the named io/ioCopy buffers under test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * MRIFiles: parse all waveformInformation entries as a list The ISMRMRD schema allows up to 32 waveformInformation elements per header (maxOccurs="32"). The previous code only read e[1], silently discarding all but the first, and the write path emitted at most one element. Both read and write now handle an arbitrary number of entries. Read: all waveformInformation elements are collected into params["waveformInformation"] as a Vector{Dict{String,Any}}, each dict holding waveformName, waveformType, and optionally userParameters. Write: each entry in the vector produces its own <waveformInformation> element in the output XML. The old flat keys waveformName, waveformType, and waveformUserParameters are replaced by the structured list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f6d2e25 commit f707a63

2 files changed

Lines changed: 53 additions & 12 deletions

File tree

MRIFiles/src/ISMRMRD/Parameters.jl

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,18 @@ function GeneralParameters(xdoc::XMLDocument)
187187
addToDict!(params, e[1], "echo_spacing", Float64)
188188
end
189189

190-
# waveformInformation
190+
# waveformInformation — up to 32 entries per spec (maxOccurs="32")
191191
e = get_elements_by_tagname(LightXML.root(xdoc),"waveformInformation")
192192
if !isempty(e)
193-
addToDict!(params, e[1], "waveformName", Float64)
194-
addToDict!(params, e[1], "waveformType", Float64)
195-
196-
if !isempty(e[1]["userParameters"])
197-
d = e[1]["userParameters"]
193+
waveforms = Vector{Dict{String,Any}}()
194+
for wi in e
195+
w = Dict{String,Any}()
196+
n = wi["waveformName"]
197+
if !isempty(n); w["waveformName"] = content(n[1]); end
198+
t = wi["waveformType"]
199+
if !isempty(t); w["waveformType"] = content(t[1]); end
200+
if !isempty(wi["userParameters"])
201+
d = wi["userParameters"]
198202
y = Dict{String,Any}()
199203
for q in d["userParameterLong"]
200204
y[content(q["name"][1])] = parse(Int,content(q["value"][1]))
@@ -205,8 +209,11 @@ function GeneralParameters(xdoc::XMLDocument)
205209
for q in d["userParameterString"]
206210
y[content(q["name"][1])] = content(q["value"][1])
207211
end
208-
params["waveformUserParameters"] = y
212+
w["userParameters"] = y
213+
end
214+
push!(waveforms, w)
209215
end
216+
params["waveformInformation"] = waveforms
210217
end
211218

212219
# UserParameters
@@ -394,8 +401,14 @@ function GeneralParametersToXML(params::Dict{String,Any})
394401
p = ["TR", "TE", "TI", "flipAngle_deg", "sequence_type", "echo_spacing"]
395402
generateGroup(params, p, xroot, "sequenceParameters")
396403

397-
p = ["waveformName", "waveformType", "waveformUserParameters"]
398-
generateGroup(params, p, xroot, "waveformInformation")
404+
if haskey(params, "waveformInformation")
405+
for w in params["waveformInformation"]
406+
xs = new_child(xroot, "waveformInformation")
407+
if haskey(w, "waveformName"); insertNode(xs, "waveformName", w["waveformName"]); end
408+
if haskey(w, "waveformType"); insertNode(xs, "waveformType", w["waveformType"]); end
409+
if haskey(w, "userParameters"); insertNode(xs, "userParameters", w["userParameters"]); end
410+
end
411+
end
399412

400413
p = ["userParameters"]
401414
generateGroup(params, p, xroot, "userParameters")

MRIFiles/test/testISMRMRD.jl

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ h5open(filenameCopy) do fd
4949
end
5050
end
5151

52+
# Test waveformInformation: single entry, multiple entries, and round-trip
53+
54+
let xml = """<?xml version="1.0"?>
55+
<ismrmrdHeader xmlns="http://www.ismrm.org/ISMRMRD/xsd"
56+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
57+
<waveformInformation>
58+
<waveformName>ecg_trigger</waveformName>
59+
<waveformType>ecg</waveformType>
60+
</waveformInformation>
61+
<waveformInformation>
62+
<waveformName>resp</waveformName>
63+
<waveformType>respiratory</waveformType>
64+
</waveformInformation>
65+
</ismrmrdHeader>"""
66+
p = MRIFiles.GeneralParameters(xml)
67+
@test length(p["waveformInformation"]) == 2
68+
@test p["waveformInformation"][1]["waveformName"] == "ecg_trigger"
69+
@test p["waveformInformation"][1]["waveformType"] == "ecg"
70+
@test p["waveformInformation"][2]["waveformName"] == "resp"
71+
@test p["waveformInformation"][2]["waveformType"] == "respiratory"
72+
# round-trip through XML serialisation
73+
xml2 = MRIFiles.GeneralParametersToXML(p)
74+
p2 = MRIFiles.GeneralParameters(xml2)
75+
@test p2["waveformInformation"] == p["waveformInformation"]
76+
end
77+
5278
# test reconstructing the data
5379
IrecoCopy = reconstruction(AcquisitionData(acqCopy), params)
5480

@@ -81,10 +107,12 @@ save(fCopy, acq)
81107
acqCopy = RawAcquisitionData(f)
82108

83109
io = IOBuffer()
84-
write(IOBuffer(), acq.profiles[1].head)
110+
write(io, acq.profiles[1].head)
85111
ioCopy = IOBuffer()
86-
write(IOBuffer(), acqCopy.profiles[1].head)
87-
@test io.data == ioCopy.data
112+
write(ioCopy, acqCopy.profiles[1].head)
113+
seekstart(io)
114+
seekstart(ioCopy)
115+
@test read(io) == read(ioCopy)
88116
@test acqCopy.profiles[1].traj == acq.profiles[1].traj
89117
@test acqCopy.profiles[1].data == acq.profiles[1].data
90118

0 commit comments

Comments
 (0)