From 808b5a7bf989e8b5503d72af4d50361cc1f26805 Mon Sep 17 00:00:00 2001 From: Carlos Castillo Passi Date: Fri, 1 May 2026 18:28:57 -0700 Subject: [PATCH] Handle raw output for sequences without ADC --- KomaMRICore/src/rawdata/ISMRMRD.jl | 45 +++++++++++++++++++----------- KomaMRICore/test/runtests.jl | 12 ++++++++ 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/KomaMRICore/src/rawdata/ISMRMRD.jl b/KomaMRICore/src/rawdata/ISMRMRD.jl index 65dd5b0a6..ece603f0f 100644 --- a/KomaMRICore/src/rawdata/ISMRMRD.jl +++ b/KomaMRICore/src/rawdata/ISMRMRD.jl @@ -79,27 +79,35 @@ function signal_to_raw_data( signal, seq; phantom_name="Phantom", sys=Scanner(), sim_params=Dict{String,Any}(), ndims=2 ) + Nadcs = sum(is_ADC_on.(seq)) #Number of samples and FOV - _, ktraj = get_kspace(seq) #kspace information - mink = minimum(ktraj, dims=1) - maxk = maximum(ktraj, dims=1) - Wk = maxk .- mink - Δx = 1 ./ Wk[1:2] #[m] Only x-y Nx = get(seq.DEF, "Nx", 1) Ny = get(seq.DEF, "Ny", 1) Nz = get(seq.DEF, "Nz", 1) - if haskey(seq.DEF, "FOV") - FOVx, FOVy, _ = seq.DEF["FOV"] #[m] + if Nadcs == 0 + FOV = get(seq.DEF, "FOV", [Nx, Ny, 1] .* 1e-3) + FOVx, FOVy, _ = FOV if FOVx > 1 FOVx *= 1e-3 end #mm to m, older versions of Pulseq saved FOV in mm if FOVy > 1 FOVy *= 1e-3 end #mm to m, older versions of Pulseq saved FOV in mm - Nx = isnothing(get(seq.DEF, "Nx", nothing)) ? ceil(Int64, FOVx / Δx[1]) : Nx - Ny = isnothing(get(seq.DEF, "Ny", nothing)) ? ceil(Int64, FOVy / Δx[2]) : Ny else - FOVx = Nx * Δx[1] - FOVy = Ny * Δx[2] + _, ktraj = get_kspace(seq) #kspace information + mink = minimum(ktraj, dims=1) + maxk = maximum(ktraj, dims=1) + Wk = maxk .- mink + Δx = 1 ./ Wk[1:2] #[m] Only x-y + if haskey(seq.DEF, "FOV") + FOVx, FOVy, _ = seq.DEF["FOV"] #[m] + if FOVx > 1 FOVx *= 1e-3 end #mm to m, older versions of Pulseq saved FOV in mm + if FOVy > 1 FOVy *= 1e-3 end #mm to m, older versions of Pulseq saved FOV in mm + Nx = isnothing(get(seq.DEF, "Nx", nothing)) ? ceil(Int64, FOVx / Δx[1]) : Nx + Ny = isnothing(get(seq.DEF, "Ny", nothing)) ? ceil(Int64, FOVy / Δx[2]) : Ny + else + FOVx = Nx * Δx[1] + FOVy = Ny * Δx[2] + end + #It needs to be transposed for the raw data + ktraj = maximum(2*abs.(ktraj[:])) == 0 ? transpose(ktraj) : transpose(ktraj)./ maximum(2*abs.(ktraj[:])) end - #It needs to be transposed for the raw data - ktraj = maximum(2*abs.(ktraj[:])) == 0 ? transpose(ktraj) : transpose(ktraj)./ maximum(2*abs.(ktraj[:])) #First we define the ISMRMRD data XML header #userParameters <- sim_params @@ -154,10 +162,11 @@ function signal_to_raw_data( "userParameters" => sim_params, #Dict with parameters ) + Nadcs == 0 && return RawAcquisitionData(params, Profile[]) + #Then, we define the Profiles profiles = Profile[] t_acq = get_adc_sampling_times(seq) - Nadcs = sum(is_ADC_on.(seq)) NadcsPerImage = max(floor(Int, Nadcs / Nz), 1) scan_counter = 0 nz = 0 @@ -237,9 +246,13 @@ function signal_to_raw_data( end Base.show(io::IO, raw::RawAcquisitionData) = begin - Nt, Nc = size(raw.profiles[1].data) compact = get(io, :compact, false) seq_name = get(raw.params, "protocolName", "None") + if isempty(raw.profiles) + print(io, compact ? "RawAcqData[$seq_name | 0 Profile(s)]" : "RawAcquisitionData[SeqName: $seq_name | 0 Profile(s)]") + return nothing + end + Nt, Nc = size(raw.profiles[1].data) if !compact print(io, "RawAcquisitionData[SeqName: $seq_name | $(length(raw.profiles)) Profile(s) of $Nt×$Nc]") else @@ -264,4 +277,4 @@ Base.isapprox(sig1::RawAcquisitionData, sig2::RawAcquisitionData; kwargs...) = b end return true -end \ No newline at end of file +end diff --git a/KomaMRICore/test/runtests.jl b/KomaMRICore/test/runtests.jl index 08d072311..3554bc940 100644 --- a/KomaMRICore/test/runtests.jl +++ b/KomaMRICore/test/runtests.jl @@ -218,6 +218,18 @@ end @test true end +@testitem "raw output without ADC" tags=[:core, :nomotion] begin + seq = Sequence([Grad(0, 1e-3)]) + obj = Phantom(x=[0.0]) + sys = Scanner() + sim_params = Dict{String, Any}("return_type" => "raw", "gpu" => false) + + raw = simulate(obj, seq, sys; sim_params, verbose=false) + @test raw isa RawAcquisitionData + @test isempty(raw.profiles) + show(IOBuffer(), "text/plain", raw) +end + @testitem "Bloch" tags=[:important, :core, :nomotion, :bloch] begin include("initialize_backend.jl") include(joinpath(@__DIR__, "test_files", "utils.jl"))