API Reference
Entry Point
MRITwixTools.read_twix — Function
read_twix(filename; kwargs...) -> TwixObj or Vector{TwixObj}Read a Siemens twix (.dat) file. Returns a TwixObj for single-raid files or a Vector{TwixObj} for multi-raid (VD+) files.
Keyword Arguments
verbose::Bool=true: show progress bars during reading and data retrievalbReadHeader::Bool=true: whether to read the headerbReadMDH::Bool=true: whether to read MDH data
The following flags are forwarded to each RawData object and control how data is processed when read via getdata / unsorted:
removeOS::Bool=false: remove 2× readout oversampling via FFT cropregrid::Bool=false: regrid non-Cartesian (ramp-sampled) readoutsdoAverage::Bool=false: average across theAvedimensionaverageReps::Bool=false: average across theRepdimensionaverageSets::Bool=false: average across theSetdimensionignoreSeg::Bool=false: collapse theSegdimensionsqueeze::Bool=false: drop singleton dimensions from returned arraysdisableReflect::Bool=false: skip readout reflection correctionignoreROoffcenter::Bool=false: ignore readout off-center shifts during regridding
Data Access
MRITwixTools.getdata — Function
getdata(s::RawData; key=nothing)Retrieve data from the RawData. Pass key=nothing for all data, or a tuple of ranges for slicing.
MRITwixTools.unsorted — Function
unsorted(s::RawData, ival=nothing)Return unsorted data [NCol, NCha, #samples].
MRITwixTools.fullSize — Function
fullSize(s::RawData) -> Vector{Int}Return the full 16-element dimension size vector.
MRITwixTools.dataSize — Function
dataSize(s::RawData) -> Vector{Int}Return data size accounting for OS removal and averaging flags.
MRITwixTools.sqzSize — Function
sqzSize(s::RawData) -> Vector{Int}Return data sizes with singleton dimensions removed.
MRITwixTools.sqzDims — Function
sqzDims(s::RawData) -> Vector{String}Return dimension names for non-singleton dimensions.
MRITwixTools.MDH_flags — Function
MDH_flags(t::TwixObj)Return list of populated scan type names. Only entries whose value is a RawData object are considered scan types; auxiliary entries such as "hdr" (a TwixHdr) or "syncdata" (raw MDH_SYNCDATA payloads, a Vector{Vector{UInt8}}) are excluded.
Processing Flag Setters
These are exported convenience functions that set processing flags on a MRITwixTools.RawData object. Direct field access (e.g., obj.removeOS = true) is preferred for new code.
| Function | Equivalent |
|---|---|
set_flagRemoveOS!(obj, val) | obj.removeOS = val |
set_flagRampSampRegrid!(obj, val) | obj.regrid = val (errors if no trajectory) |
set_flagDoAverage!(obj, val) | obj.doAverage = val |
set_flagAverageReps!(obj, val) | obj.averageReps = val |
set_flagAverageSets!(obj, val) | obj.averageSets = val |
set_flagIgnoreSeg!(obj, val) | obj.ignoreSeg = val |
set_flagSkipToFirstLine!(obj, val) | obj.skipToFirstLine = val |
set_flagDisableReflect!(obj, val) | obj.disableReflect = val |
SYNCDATA Introspection
These utilities help discover the ASCII tags embedded in an MDH_SYNCDATA packet and locate the start of the binary payload that follows a tag. See the SYNCDATA Payloads guide for context.
MRITwixTools.syncdata_strings — Function
syncdata_strings(pkt::AbstractVector{UInt8}; min_length::Int = 4)
-> Vector{@NamedTuple{offset::Int, length::Int, str::String}}Return every run of ≥ min_length consecutive printable-ASCII bytes in pkt. Each entry is a NamedTuple with fields
offset— 0-based byte offset of the first character inpkt,length— number of characters in the run,str— the run itself as aString.
SYNCDATA packets typically contain a small number of short ASCII field names (Siemens SEQData framing, such as "SQ", "AdjCoilSensSeq", "PMUData") followed by one or more sequence-specific tags (e.g. "MyCustomTag_v1") that mark the beginning of a binary payload. A call like
syncdata_strings(pkt; min_length = 16)typically hides the framing noise and shows only the meaningful tag(s).
The byte-level is_printable_ascii predicate can produce short-but-not-meaningful runs in two situations:
- Fragments of the ASCII XProtocol header may bleed into fixed-size SEQData framing packets. Because the string spans packet boundaries, only ~10–20 characters survive as a run inside any one packet.
- Small-magnitude
Float32values pack their exponent bytes into0x3E..0x3F(bytes>/?), so vectors of small floats occasionally produce ASCII runs up to ~12 characters long.
A min_length of 16 or above hides both. If you don't know the tag length in advance, sweep min_length downwards — genuine tags appear in exactly one packet at a stable offset, while noise fluctuates.
MRITwixTools.payload_offset — Function
payload_offset(pkt::AbstractVector{UInt8}, tag::AbstractString;
min_padding::Int = 0, max_padding::Int = 256)
-> Union{Int, Nothing}Locate the ASCII tag inside pkt and return the 1-based byte offset of the first non-printable byte after it (i.e. the first byte that is not ASCII 0x20..0x7E). This is a good proxy for "where the binary payload starts" when the tag is followed by some padding of NUL bytes / framing.
min_padding / max_padding bound how far to search past the tag; the search stops as soon as a non-printable byte is found. Returns nothing if tag is not present in pkt or the packet ends before a non-printable byte is encountered.
Because Siemens sometimes inserts a variable number of framing/padding bytes between an ASCII tag and the actual binary header, callers that know the exact binary layout usually still want to slide forward a few bytes past this offset until the parsed fields look plausible — see the SYNCDATA Payloads user guide for the recommended pattern.
MRITwixTools.summarize_syncdata — Function
summarize_syncdata(sync::AbstractVector{<:AbstractVector{UInt8}};
min_length::Int = 4,
max_start_frac::Float64 = 0.5,
show_empty::Bool = false,
io::IO = stdout)Print a human-readable summary of the packets in sync (as returned by TwixObj.syncdata): the packet index, total size in bytes, and every ASCII run of length ≥ min_length together with its offset.
Many SYNCDATA streams are dominated by:
- Framing packets (PMU telemetry, timing frames, …) that carry no printable-ASCII content at all, and
- XProtocol-fragment packets — fixed-size Siemens SEQData frames whose trailing bytes contain a slice of the ASCII XProtocol header, producing short ASCII runs at offsets near the end of the packet.
Both kinds of noise are hidden by default:
- Packets with no qualifying ASCII run are omitted (this handles case 1).
- Packets whose runs all start past
max_start_frac × length(pkt)are omitted as "late-only" runs (this handles case 2). Custom tags identifying a payload are almost always near the start of their packet, somax_start_frac = 0.5(the default) keeps them visible while dropping trailing XProtocol fragments.
A single aggregate line at the end reports how many packets were hidden and for what reason. Set max_start_frac = 1.0 to disable the "late-only" filter, and show_empty = true to list every packet individually.
twx = read_twix("meas.dat")
MRITwixTools.summarize_syncdata(twx.syncdata; min_length = 16)Header Navigation
MRITwixTools.NestedDict — Type
NestedDictA recursively nested dictionary with property-style access for navigating Siemens MRI header data. Supports:
- Dot access:
hdr.MeasYaps.sKSpace.lBaseResolution - Path strings:
hdr["MeasYaps.sKSpace.lBaseResolution"] - Tab completion: at every level via
propertynames - Search:
search(hdr, "sTXSPEC", "Nucleus")finds all matching paths - Iteration: standard
keys,values,pairs,length
Implementation note
Subtrees (NestedDict children) are stored separately from leaf values in a typed dict, enabling Julia's REPL to infer the return type of getproperty for chained tab-completion.
MRITwixTools.search — Function
search(n::NestedDict, terms...; regex=true, leaves_only=true, search_values=false) -> Vector{Pair{String,Any}}Search all paths in the tree for entries whose full dotted path matches all given terms. Returns a vector of "dotted.path" => value pairs.
Keyword Arguments
regex::Bool=true: treat each term as a case-insensitive regex (otherwise plain substring match)leaves_only::Bool=true: only return leaf values, not intermediate subtree nodessearch_values::Bool=false: also match terms against the string representation of leaf values
Examples
search(hdr, "sTXSPEC", "Nucleus") # match path components
search(hdr, "lBaseRes") # find all keys containing "lBaseRes"
search(hdr, "1H", search_values=true) # find leaves whose value contains "1H"
search(hdr, "Nucleus", "1H", search_values=true) # path contains "Nucleus" AND value contains "1H"MRITwixTools.leaves — Function
leaves(n::NestedDict) -> Vector{Pair{String,Any}}Return all leaf (non-NestedDict) values with their full dotted paths.
MRITwixTools.setpath! — Function
setpath!(n::NestedDict, path::Vector{String}, value)Insert a value at a dotted path, creating intermediate NestedDict nodes as needed. E.g., setpath!(n, ["sKSpace", "lBaseResolution"], 256).
Types
MRITwixTools.TwixObj — Type
TwixObjResult object from read_twix. Contains header and scan data objects accessible via attribute-style access (e.g., obj.image, obj.hdr).
MRITwixTools.TwixHdr — Type
TwixHdrHeader object for Siemens twix files. Wraps a NestedDict with top-level sections (e.g., "Meas", "MeasYaps", "Phoenix") each containing parsed ASCCONV and XProtocol data as nested trees.
Access patterns
hdr.MeasYaps.sKSpace.lBaseResolution # dot-access with tab-completion
hdr["MeasYaps.sKSpace.lBaseResolution"] # path string
search(hdr, "lBaseRes") # search all pathsMRITwixTools.RawData — Type
RawDataMain data object for one scan type (image, noise, refscan, etc.). Stores MDH metadata and provides lazy data loading from the twix file.
flags: mutable processing flagsmeta: per-acquisition metadata (Nothing until MDH is read)dims: computed dimension sizes (Nothing untilcompute_dims!is called)
MRITwixTools.ReadInfo — Type
ReadInfoBinary layout parameters for reading channel data from a twix file. Determined by software version (VB vs VD).
MRITwixTools.AcquisitionMeta — Type
AcquisitionMetaPer-acquisition metadata extracted from MDH headers. All loop counters are stored as Int32; positions as Float32. Populated by readMDH!.
MRITwixTools.DimSizes — Type
DimSizesComputed dimension extents and skip offsets, all as concrete Int. Immutable — recomputed when flags change.