Skip to content
Snippets Groups Projects
Unverified Commit a05cbde5 authored by Michiel Cottaar's avatar Michiel Cottaar
Browse files

Add I/O for meaningful extensions

parent 1ea539f8
No related branches found
No related tags found
1 merge request!3Add InstantPulse and InstantGradient pulseq extension support
......@@ -15,13 +15,13 @@ struct PulseqComponents
pulses:: Dict{Int, PulseqRFPulse}
grads:: Dict{Int, AnyPulseqGradient}
adc:: Dict{Int, PulseqADC}
extensions:: Dict{Int, PulseqExtension}
extensions:: Dict{Int, Any}
PulseqComponents(shapes, pulses, grads, adc, extensions) = new(
_convert_to_dict(shapes, PulseqShape),
_convert_to_dict(pulses, PulseqRFPulse),
_convert_to_dict(grads, AnyPulseqGradient),
_convert_to_dict(adc, PulseqADC),
_convert_to_dict(extensions, PulseqExtension),
_convert_to_dict(extensions, Any),
)
end
......
"""
Defines the Pulseq IO extension interface with default implementations
"""
module Extensions
import ..Types: PulseqExtension, PulseqExtensionDefinition
struct UnknownExtensionMapper
ext::PulseqExtensionDefinition
end
Base.getindex(mapper::UnknownExtensionMapper, i::Int) = PulseqExtension(mapper.ext, i)
"""
parse_extension(ext::PulseqExtensionDefinition{name})
Parse a Pulseq extension definition into a dictionary-like object
that maps integer reference IDs to any object describing the extension.
This can be overriden to support the reading of a specific extension type.
For example, to define a parser for an extension with the name "LABELSET":
```
function PulseqIO.parse_extension(ext::PulseqExtensionDefinition{:LABELSET})
...
end
```
"""
function parse_extension(ext::PulseqExtensionDefinition{N}) where {N}
@warn "Parsing unknown extension: {N}"
return UnknownExtensionMapper(ext)
end
"""
get_extension_name(obj)
Get the name under which the given `obj` should be stored in a Pulseq extension.
To write an object to a Pulseq file extension,
one needs to define both this function and [`add_extension_definition`](@ref).
"""
get_extension_name(ext::PulseqExtension{N}) where {N} = N
"""
add_extension_definition!(content::Vector{String}, obj)
Add the object to the extension definition and returns the reference index.
The extension definition is passed on as a vector of strings.
This vector can be appended to, when adding a new object.
If the object is already in the `definition` the reference index of the already existing object should be returned instead.
"""
add_extension_definition!(content::Vector{String}, ext::PulseqExtension) = ext.index
end
\ No newline at end of file
import ..Extensions: parse_extension, get_extension_name, add_extension_definition!
function parse_section(section::PulseqSection{:extensions}; kwargs...)
current_extension = -1
pre_amble = true
linked_list = Dict{Int, NTuple{3, Int}}()
extensions = Dict{Int, PulseqExtension}()
extensions = Dict{Int, PulseqExtensionDefinition}()
for line in section.content
if startswith(line, "extension ")
pre_amble = false
(_, name, str_id) = split(line)
current_extension = int(str_id)
extensions[current_extension] = PulseqExtension(name, String[])
extensions[current_extension] = PulseqExtensionDefinition{name}(String[])
elseif pre_ample
(id, type, ref, next) = int.(split(line))
linked_list[id] = (type=type, ref=ref, next=next)
......@@ -17,15 +19,69 @@ function parse_section(section::PulseqSection{:extensions}; kwargs...)
end
end
extension_mappers = Dict(key => parse_extension(ext) for (key, ext) in extensions)
function get_extension_list(key::Int)
if iszero(key)
return Tuple{PulseqExtension, Int}[]
else
base = get_extension_list(linked_list[key].next)
pushfirst!(base, (extensions[linked_list[key].type], linked_list[key].ref))
pushfirst!(base, extension_mappers[linked_list[key].type][linked_list[key].ref])
return base
end
end
return Dict(key => get_extension_list(key) for key in keys(linked_list))
end
function gen_section(comp:: PulseqComponents, ::Val{:extensions})
definitions = Dict{Symbol, PulseqExtensionDefinition}()
extensions_ref_id = Dict{Any, Int}()
for ext_vec in comp.extensions
for ext in ext_vec
name = get_extension_name(ext)
if !(name in keys(definitions))
definitions[name] = PulseqExtensionDefinition{name}(String[])
end
extensions_ref_id[ext] = add_extension_definition!(definitions[name].content, ext)
end
end
definitions_order = [keys(definitions)...]
extension_vec_id = Dict{Vector, Int}()
labels = Tuple{Int, Int, Int}[]
function add_extension_vec!(ext_vec::Vector)
if length(ext_vec) == 0
return 0
end
next_id = add_extension_vec!(ext_vec[2:end])
ext = ext_vec[1]
type_id = findfirst(get_extension_name(ext), definitions_order)
ref_id = extensions_ref_id[ext]
all_ids = (type_id, ref_id, next_id)
if all_ids in labels
extension_vec_id[ext_vec] = findfirst(lables, all_ids)
else
push!(labels, all_ids)
extension_vec_id[ext_vec] = length(lables)
end
end
add_extension_definition!.(values(comp.extensions))
content = String[]
for (id0, (id1, id2, id3)) in enumerate(labels)
push!(content, "$id0 $id1 $id2 $id3")
end
push!(content, "")
for (index, name) in enumerate(definitions_order)
def = definitions[name]
push!(content, "extension $(string(name)) $(string(index))")
append!(content, def.content)
push!(content, "")
end
return PulseqSection{:extensions}(content)
end
\ No newline at end of file
......@@ -6,6 +6,7 @@ The translation of these types into MRIBuilder types is defined in "../pulseq.jl
"""
module PulseqIO
include("types.jl")
include("extensions.jl")
include("basic_parsers.jl")
include("sections_io.jl")
include("components.jl")
......@@ -13,6 +14,7 @@ include("parsers/parsers.jl")
include("parse_sections.jl")
import .Types: PulseqSequence
import .Extensions: parse_extension, get_extension_name, add_extension_definition!
"""
......
......@@ -94,18 +94,17 @@ end
Abstract definition of an unknown Pulseq extension.
"""
struct PulseqExtensionDefinition
name :: String
struct PulseqExtensionDefinition{N}
content :: Vector{String}
end
"""
PulseqExtension(definition::PulseqExtensionDefinition, id::Int)
Reference to a specific implementation of the [`PulseqExtensionDefinition`](@ref).
Reference to a specific implementation of a [`PulseqExtensionDefinition`](@ref).
"""
struct PulseqExtension <: AnyPulseqComponent
definition::PulseqExtensionDefinition
struct PulseqExtension{N} <: AnyPulseqComponent
definition::PulseqExtensionDefinition{N}
id :: Int
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment