Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
204 commits
Select commit Hold shift + click to select a range
e7490cf
Coil-sens on Scanner
cncastillo Jul 15, 2024
8470a70
Delete unintended and unnecesary elements
Stockless Mar 14, 2025
be1d62b
coil_sens removal from Phantom structure
Stockless Mar 14, 2025
4dbf3d1
remove unnecesary example file, remove unnecesary packages call and …
Stockless Mar 17, 2025
821f765
add a get_n_coils function, re-add KomaMRI subpackages to KomaMRI [co…
Stockless Mar 17, 2025
71c20e3
remove sphere_fields.mat
Stockless Mar 17, 2025
766cb48
redefined get_n_coils function: 1 for abstract type and size of coil …
Stockless Mar 17, 2025
1e6a65d
Merge branch 'master' into scanner-develop
cncastillo Mar 17, 2025
ddb81c8
Correction of Scanner argument at run_spin_precession functions
Stockless Mar 20, 2025
bbee076
adding specific dispatch for CPU
Stockless Mar 26, 2025
033fef8
Using intended acquire_signal for BlochCPU (not working on multiple c…
Stockless Mar 27, 2025
627d81d
Fixed BlochCPU with multiple coils
Stockless Mar 27, 2025
9fa397a
add setpropery to directly define hardware limitations on the scanner…
Stockless Mar 31, 2025
bbbb559
remove type conversion and using HardwareLimitations as Float
Stockless Mar 31, 2025
dbe6175
Fix sys.Smax to be Float in KomaMRICore/runtest
Stockless Mar 31, 2025
6c92be7
admission of ArbitraryRFCoils simulation without interpolation (only …
Stockless May 26, 2025
47bc15c
Moved coils_sens interpolation to SimulatorCore
Stockless May 28, 2025
63750c4
Fix sys::Scanner -> sys::Scanner{T}
Stockless May 28, 2025
add1344
Interpolation Incorporation
Stockless Jun 17, 2025
36313f2
add coil_sens view
Stockless Jun 19, 2025
2b35082
initialize interpolated_coil_sens with similar()
Stockless Jun 24, 2025
fab91dd
simulate with interpolation (reconstruction missing)
Stockless Jun 30, 2025
7e61fba
re-organize coils definition example
Stockless Jul 1, 2025
5bec3cf
change coil_sens_recon
Stockless Jul 3, 2025
b84c69a
Modified `center-images.css` to avoid centering badges.
cncastillo Mar 24, 2025
a0ca145
restrict PlutoPlotly to version 0.5
Stockless Apr 7, 2025
afeed97
trivial change to test documentation
Stockless Apr 8, 2025
f3594b9
bump KomaMRIPlots to version 0.9.2
Stockless Apr 8, 2025
0a5dcd3
Notebook Update
Stockless Apr 9, 2025
fea5f52
hide reproducibility raw md text
Stockless Apr 9, 2025
15ab1fc
update Bloch_RF_accuracy test to use DiffEq instead of pre-calculated…
Stockless May 19, 2025
4c1adb0
delete debugging test
Stockless May 19, 2025
f40e515
Bloch_RF_accuracy NRMSE improve to be > 0.1
Stockless Jul 2, 2025
0ba68b7
rm println
Stockless Jul 2, 2025
ce1b266
Bump julia-actions/julia-format from 3 to 4
dependabot[bot] May 1, 2025
953bfdd
Initial commit
rkierulf Jan 23, 2025
0579294
add -g2 to AMD and CUDA tests to see error
rkierulf Jan 24, 2025
da4926e
synchronize immediately after kernels finish
rkierulf Jan 24, 2025
31ced37
change synchronization back
rkierulf Jan 24, 2025
a5e3037
remove -g2
rkierulf Jan 27, 2025
bec150d
fix sequence indexing issue
rkierulf Jan 27, 2025
7c43608
Adapt to KernelAbstractions 0.9.34 + clean up code
rkierulf Mar 13, 2025
38f1e5b
Use shuffle_down intrinsic for faster reduction
rkierulf Mar 14, 2025
004eb5e
Fix typo
rkierulf Mar 15, 2025
965126c
fix warp reduction
rkierulf Mar 20, 2025
8fd6a8c
change default precession groupsize to 256
rkierulf Mar 20, 2025
be83906
Is warp reduction actually faster?
rkierulf Mar 21, 2025
0ff4f04
Continue using warp reduction
rkierulf Mar 21, 2025
50a8310
Update docs
rkierulf Mar 21, 2025
99942be
Debug AMDGPU error
rkierulf Mar 23, 2025
2a64124
Undo debug statements skip benchmarks skip ci
rkierulf Mar 23, 2025
6e45beb
Temporarily add HIP_LAUNCH_BLOCKING
rkierulf Mar 23, 2025
d6efa82
Print matrix values skip benchmarks
rkierulf Mar 26, 2025
3dc5f22
Remove suppress
rkierulf Mar 26, 2025
b5e9ed0
Remove debug statements skip benchmarks skip ci
rkierulf Mar 26, 2025
c4fe53e
Update Phantom use on examples
Stockless Jun 10, 2025
b71bc79
Update Phantom use on tests
Stockless Jun 10, 2025
e6d561f
Update Phantom use on definitions (UI,Base,Core)
Stockless Jun 10, 2025
7287de3
add tags to PR
Stockless Jun 10, 2025
a6dfc99
Remove Kaleido_jll compat entry
cncastillo Dec 31, 2024
a99b2b5
Add "How to test contributions" in "How to contribute to Koma" docume…
Stockless Mar 24, 2025
003cd3e
Instructions less verbose
Stockless Mar 25, 2025
97bdcf0
How to add a new test
Stockless Mar 27, 2025
fa4245c
Redaction corrections
Stockless Jun 5, 2025
f878028
julia code block correction
Stockless Jun 5, 2025
4dfb553
Generate preview
Stockless Jun 9, 2025
9a2e781
Corrected redaction according to review
Stockless Jun 10, 2025
9e397f4
Improve test-komamricore image resolution
Stockless Jun 11, 2025
e57f73d
Improved redaction based on review
Stockless Jun 13, 2025
93cb77d
add space after images
Stockless Jun 17, 2025
1268ec2
Remove unnecesary itemization
Stockless Jun 18, 2025
52f35ec
Remove CSS specification to generate space after image
Stockless Jun 18, 2025
deb36b2
First commit
pvillacorta Oct 9, 2024
513ab04
Commit of the following:
pvillacorta Oct 9, 2024
fb7375b
Commit of the following:
pvillacorta Oct 11, 2024
17fc909
Solve bugs:
pvillacorta Oct 11, 2024
4377a7f
Commit of the following:
pvillacorta Oct 11, 2024
d858cf1
Commit with the following:
pvillacorta Oct 11, 2024
395d441
Correct docstring
pvillacorta Nov 26, 2024
04054b9
Fix formatting of the '.phantom' file extension in documentation
pvillacorta May 2, 2025
5b9628f
Merge branch `master` into `docs-phantom`
pvillacorta Apr 2, 2025
217d94f
Adapt current docs to the new v0.9.1 `Phantom`
pvillacorta Apr 2, 2025
ef5c414
Update image source in Phantom format documentation
pvillacorta Apr 2, 2025
a6b402f
Write the motion section and minor changes in other related sections
pvillacorta Apr 4, 2025
c9fb091
Fix typos in lit-2-motion.jl
pvillacorta Apr 4, 2025
b7556ac
Hide lines in lit-2-motion.jl and plot entire phantom
pvillacorta Apr 4, 2025
774486d
Fix relative paths in lit-2-motion.jl for correct navigation
pvillacorta Apr 4, 2025
a346711
Definitely fix relative paths in lit-2-motion.jl
pvillacorta Apr 4, 2025
450554d
Update references and adjust plot heights in lit-2-motion.jl and 2-ko…
pvillacorta Apr 4, 2025
85c7707
Fix erroneous semicolons in lit-2-motion.jl
pvillacorta Apr 4, 2025
a8858c6
Fix cross-reference links to `KomaMRIBase.TimeCurve`
pvillacorta Apr 4, 2025
585d7a6
Fix comment line
pvillacorta Apr 7, 2025
bb060a5
Add section on Phantom File I/O and clarify .phantom format description
pvillacorta Apr 7, 2025
b1dac4a
Extend "Create your own Phantom" section
pvillacorta Apr 10, 2025
bfac231
Reduce plots height and improve introductive paragraph.
pvillacorta Apr 10, 2025
7366e08
Remove unnecessary example output
pvillacorta Apr 10, 2025
047deef
Add sequence scripts folder and new `lit-07-RRVariability.jl` tutorial
pvillacorta Jun 11, 2025
fe73645
Remove CUDA import from `examples/3.tutorials/lit-07-RRVariability.jl`
pvillacorta Jun 11, 2025
1f55f1b
Rename bSSFP_cine.jl and fix include functions
pvillacorta Jun 11, 2025
69595ec
Update docs/Project.toml to include Plots and Printf
pvillacorta Jun 11, 2025
220fb12
Utils file redistribution and correct bugs that difficulted docs build
pvillacorta Jun 12, 2025
59f9cb1
Make struct definitions mutable for TimeCurve, AllSpins, SpinRange, F…
pvillacorta Jun 12, 2025
d2b7676
Finish lit-07 tutorial and redistribute /utils files
pvillacorta Jun 12, 2025
2671dd1
Fix commands tagged with `#nb` and `#jl`
pvillacorta Jun 12, 2025
6fecc2a
Apply suggested changes, add phantom plot, resize figures
pvillacorta Jun 12, 2025
16432c2
Refactor displacement functions to center coordinates before rotation…
pvillacorta Apr 4, 2025
fffe233
Update rotation tests for KomaMRIBase
pvillacorta Apr 4, 2025
ca07a7a
Remove `mutable` from all the motion-related structs
pvillacorta Jun 13, 2025
9344b5f
Correct lit-07-RRVariability.jl to modify non-mutable structs
pvillacorta Jun 13, 2025
6dca86d
Commit of the following:
pvillacorta Jun 15, 2025
757ece3
News 16.Jun.2025
Stockless Jun 17, 2025
54e53c2
Update README.md
cncastillo Jun 18, 2025
3fbe173
Add files via upload
cncastillo Jun 18, 2025
916834d
Delete assets/OSI2Logo.svg
cncastillo Jun 18, 2025
76fd028
Add files via upload
cncastillo Jun 18, 2025
aaa61b4
Rename DIN SPEC 3105_ OSI² CAB_ 1.svg to DIN_SPEC_3105_OSI2_CAB_1.svg
cncastillo Jun 18, 2025
3949fb6
Added OSI2 badge
cncastillo Jun 18, 2025
da6efa9
Added OSI2 badge properly
cncastillo Jun 19, 2025
0e99bd0
Delete assets/DIN_SPEC_3105_OSI2_CAB_1.svg
cncastillo Jun 19, 2025
0a9d32e
fix tabulation errors
Stockless Jun 19, 2025
ff752b7
Fixed inconsistencies in header capitalization, found and fixed vario…
KookiesNKareem Jun 23, 2025
fe53e61
Fixed more capitalization inconsistencies and typos. Clarified the sy…
KookiesNKareem Jun 23, 2025
bdef96c
Unsafe_blink macro implementation
Stockless Apr 9, 2025
3d9f46f
test new function instead of macro
Stockless Jun 23, 2025
b61bcbd
using blink outside linux condition
Stockless Jun 23, 2025
8fd9d15
"static if" and rm innecesary export
Stockless Jun 24, 2025
95e2e40
include macos in temporary fix
Stockless Jun 24, 2025
fa5d934
add sleep after window generation
Stockless Jun 24, 2025
daf3a46
temporary change
Stockless Jun 24, 2025
6cbd002
Always return window.
cncastillo Jun 24, 2025
eb72bbe
Just import Blink.
cncastillo Jun 24, 2025
d004e2f
Always return window.
cncastillo Jun 24, 2025
c52a2e3
test using Blink.Window directly
Stockless Jun 24, 2025
2658ff0
window without arguments
Stockless Jun 24, 2025
d188299
replace setup-julia@v2 with latest
Stockless Jun 24, 2025
1dabb2f
Add lynx for debugging electron
Stockless Jun 24, 2025
16cf2a0
test sleep on ExportUIFunctions.jl
Stockless Jun 24, 2025
bf1d97a
add actions to test
Stockless Jun 25, 2025
47ec522
sleep closer to window generation
Stockless Jun 25, 2025
7eee81e
skip macos ui tests
Stockless Jun 25, 2025
93f8bb2
fix if statement
Stockless Jun 25, 2025
f614459
using Blink outside condition
Stockless Jun 26, 2025
b578ee6
restablish commented sections of tests
Stockless Jun 26, 2025
37255e7
comment unnecesary "include"s
Stockless Jun 26, 2025
3d9b7c8
final changes to temporary fix
Stockless Jun 26, 2025
fe5e5f6
Update lit-01-FID.jl
cncastillo Jul 1, 2025
88e9e55
modified duration = dur(seq)
Stockless Jul 2, 2025
5b3ce79
Reformat test
cncastillo Jul 2, 2025
1ab4951
Coil-sens on Scanner
cncastillo Jul 15, 2024
fcee2e2
Delete unintended and unnecesary elements
Stockless Mar 14, 2025
1b17302
remove unnecesary example file, remove unnecesary packages call and …
Stockless Mar 17, 2025
eac6dbc
add a get_n_coils function, re-add KomaMRI subpackages to KomaMRI [co…
Stockless Mar 17, 2025
776f4cf
Correction of Scanner argument at run_spin_precession functions
Stockless Mar 20, 2025
46314f2
Moved coils_sens interpolation to SimulatorCore
Stockless May 28, 2025
ae03455
Fix sys::Scanner -> sys::Scanner{T}
Stockless May 28, 2025
ce83f1c
Interpolation Incorporation
Stockless Jun 17, 2025
686647e
rebase remaining fixes
Stockless Jul 3, 2025
f123855
Merge branch 'master' into scanner-develop
Stockless Jul 3, 2025
fcebd64
complete rebase
Stockless Jul 3, 2025
386e141
3D interpolation
Stockless Jul 4, 2025
02708b8
CompatHelper: bump compat for oneAPI in [weakdeps] to 2 for package K…
Jan 9, 2025
7753c94
Update README.md [skip CI]
cncastillo Jul 3, 2025
7a3c672
Update README.md [skip CI]
cncastillo Jul 3, 2025
15aaa40
CompatHelper: bump compat for AcceleratedKernels to 0.4 for package K…
Jun 4, 2025
d097b8a
Update runbenchmarks.jl
Stockless Jul 9, 2025
8bcee51
update enviroments for buildkite test
Stockless Jul 9, 2025
345823c
Fix environment in which tests are run
cncastillo Jul 10, 2025
4b05b76
Test environment change
cncastillo Jul 10, 2025
dbd0635
Update test environment setup (again)
cncastillo Jul 10, 2025
bfb78b0
Last update to test environment setup
cncastillo Jul 10, 2025
69431b9
Add GPU backend to test environment
cncastillo Jul 10, 2025
840fbfa
Fix GPU tests re-resolving test environment
cncastillo Jul 10, 2025
3828d14
KomaMRIBase dev'ed in project environment
cncastillo Jul 10, 2025
27fc2a3
Dev packages to test environment
cncastillo Jul 10, 2025
f377494
Only use tests environment for GPU tests
cncastillo Jul 10, 2025
73609df
Test environment setup different for 1.10
cncastillo Jul 10, 2025
ff96ccf
Fix oneAPI bool indexing issues
cncastillo Jul 10, 2025
d1c2359
CompatHelper: bump compat for PlutoPlotly in [weakdeps] to 0.6 for pa…
Apr 9, 2025
7a54b51
Update runbenchmarks.jl
Stockless Jul 9, 2025
af5bea3
update enviroments for buildkite test
Stockless Jul 9, 2025
4274f79
Fix environment in which tests are run
cncastillo Jul 10, 2025
b3f685a
Test environment change
cncastillo Jul 10, 2025
e66c2e8
Update test environment setup (again)
cncastillo Jul 10, 2025
2e4df52
Last update to test environment setup
cncastillo Jul 10, 2025
8dc1168
Add GPU backend to test environment
cncastillo Jul 10, 2025
89a8f69
Fix GPU tests re-resolving test environment
cncastillo Jul 10, 2025
35f00a6
KomaMRIBase dev'ed in project environment
cncastillo Jul 10, 2025
9c92cc3
Dev packages to test environment
cncastillo Jul 10, 2025
5f961f5
Only use tests environment for GPU tests
cncastillo Jul 10, 2025
93828c6
Test environment setup different for 1.10
cncastillo Jul 10, 2025
225b9b7
Fixes oneAPI indexing issues.
cncastillo Jul 11, 2025
3274207
Add tags to Buildkite codecov process
cncastillo Jul 14, 2025
bc64dc3
CompatHelper: bump compat for Interpolations to 0.16 for package Koma…
May 16, 2025
99b6965
CompatHelper: bump compat for Interpolations to 0.16 for package Koma…
May 16, 2025
83d7631
Update README.md [skip CI]
cncastillo Jul 15, 2025
8f75a06
Flags added to official julia-coverage
cncastillo Jul 16, 2025
168ca57
Update README.md [skip CI]
cncastillo Jul 15, 2025
7b038c5
interpolate 2D/3D cases
Stockless Jul 23, 2025
2435ca2
Replace coil_tange example definition
Stockless Jul 30, 2025
9e666d1
`sig[1]` fill correction
Stockless Aug 18, 2025
06e81fe
Merge branch 'master' into scanner-develop
Stockless Aug 28, 2025
ebd047a
aquire_signal on GPU
Stockless Aug 28, 2025
ea26352
phantom with complex rho
Stockless Sep 1, 2025
dddd87c
Merge branch 'master' into scanner-develop
Stockless Sep 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions KomaMRIBase/src/datatypes/Phantom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ julia> obj.ρ
x::AbstractVector{T} = @isdefined(T) ? T[] : Float64[]
y::AbstractVector{T} = zeros(eltype(x), size(x))
z::AbstractVector{T} = zeros(eltype(x), size(x))
ρ::AbstractVector{T} = ones(eltype(x), size(x))
ρ::Union{AbstractVector{T}, AbstractVector{Complex{T}}} = ones(eltype(x), size(x))
T1::AbstractVector{T} = ones(eltype(x), size(x)) * 1_000_000
T2::AbstractVector{T} = ones(eltype(x), size(x)) * 1_000_000
T2s::AbstractVector{T} = ones(eltype(x), size(x)) * 1_000_000
Expand Down Expand Up @@ -124,7 +124,7 @@ end
heart_rate, asymmetry
)

Heart-like LV 2D phantom. The variable `circumferential_strain` and `radial_strain` are for streching (if positive)
Heart-like LV 2D phantom. The variable `circumferential_strain` and `radial_strain` are for streching (if positive)
or contraction (if negative). `rotation_angle` is for rotation.

# Keywords
Expand Down Expand Up @@ -227,7 +227,7 @@ julia> plot_phantom_map(obj, :ρ)
```
"""
function brain_phantom2D(; axis="axial", ss=4, us=1)
# check and filter input
# check and filter input
ssx, ssy, ssz, usx, usy, usz = check_phantom_arguments(2, ss, us)

# Get data from .mat file
Expand Down Expand Up @@ -323,7 +323,7 @@ end
obj = brain_phantom3D(; ss=4, us=1, start_end=[160,200])

Creates a three-dimentional brain Phantom struct.
Default ss=4 sample spacing is 2 mm. Original file (ss=1) sample spacing is .5 mm.
Default ss=4 sample spacing is 2 mm. Original file (ss=1) sample spacing is .5 mm.

# References
- B. Aubert-Broche, D.L. Collins, A.C. Evans: "A new improved version of the realistic
Expand All @@ -350,7 +350,7 @@ julia> plot_phantom_map(obj, :ρ)
```
"""
function brain_phantom3D(; ss=4, us=1, start_end=[160, 200])
# check and filter input
# check and filter input
ssx, ssy, ssz, usx, usy, usz = check_phantom_arguments(3, ss, us)

# Get data from .mat file
Expand Down Expand Up @@ -473,7 +473,7 @@ julia> pelvis_phantom2D(obj, :ρ)
```
"""
function pelvis_phantom2D(; ss=4, us=1)
# check and filter input
# check and filter input
ssx, ssy, ssz, usx, usy, usz = check_phantom_arguments(2, ss, us)

# Get data from .mat file
Expand Down Expand Up @@ -556,7 +556,7 @@ julia> ssx, ssy, ssz, usx, usy, usz = check_phantom_arguments(3, 4, [2, 2, 2])
```
"""
function check_phantom_arguments(nd, ss, us)
# check for valid input
# check for valid input
ssz = -9999
usz = -9999
if length(us) > 1 || prod(us) > 1
Expand Down
103 changes: 88 additions & 15 deletions KomaMRIBase/src/datatypes/Scanner.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
# Hardware limits
@with_kw mutable struct HardwareLimits{T}
B0::T = 1.5
B1::T = 10e-6
Gmax::T = 60e-3
Smax::T = 500.0
ADC_Δt::T = 2e-6
seq_Δt::T = 1e-5
GR_Δt::T = 1e-5
RF_Δt::T = 1e-6
RF_ring_down_T::T = 20e-6
RF_dead_time_T::T = 100e-6
ADC_dead_time_T::T = 10e-6
end

# Gradients
abstract type Gradients{T} end
@with_kw mutable struct LinearXYZGradients{T} <: Gradients{T}
Gx::AbstractVector{T} = zeros(T, 1)
Gy::AbstractVector{T} = zeros(T, 1)
Gz::AbstractVector{T} = zeros(T, 1)
end

# RF coils
abstract type RFCoils{T} end
@with_kw mutable struct UniformRFCoils{T} <: RFCoils{T}
coil_sens::AbstractMatrix{Complex{T}} = complex(ones(Complex{T}, 1, 1))
end

struct ArbitraryRFCoils{T} <: RFCoils{T}
x::AbstractVector{T}
y::AbstractVector{T}
z::AbstractVector{T}
coil_sens::AbstractMatrix{Complex{T}}
B1⁺::AbstractMatrix{Complex{T}}
end

struct RFCoilsSensDefinedAtPhantomPositions{T} <: RFCoils{T}
coil_sens::AbstractMatrix{Complex{T}}
end

"""
sys = Scanner(B0, B1, Gmax, Smax, ADC_Δt, seq_Δt, GR_Δt, RF_Δt,
RF_ring_down_T, RF_dead_time_T, ADC_dead_time_T)
Expand Down Expand Up @@ -28,19 +69,51 @@ julia> sys = Scanner()
julia> sys.B0
```
"""
@with_kw mutable struct Scanner
#Main
B0::Real=1.5
B1::Real=10e-6
Gmax::Real=60e-3
Smax::Real=500
#Sampling
ADC_Δt::Real=2e-6
seq_Δt::Real=1e-5
GR_Δt::Real=1e-5
RF_Δt::Real=1e-6
#Secondary
RF_ring_down_T::Real=20e-6
RF_dead_time_T::Real=100e-6
ADC_dead_time_T::Real=10e-6
@with_kw mutable struct Scanner{T}
limits::HardwareLimits{T} = HardwareLimits{Float64}()
gradients::Gradients{T} = LinearXYZGradients{Float64}()
rf_coils::RFCoils{T} = UniformRFCoils{Float64}()
end

function Base.view(sys::Scanner, p)
return Scanner(limits=sys.limits, gradients=sys.gradients, rf_coils=@view(sys.rf_coils[p]))
end

function Base.view(rf_coils::RFCoilsSensDefinedAtPhantomPositions, p)
return RFCoilsSensDefinedAtPhantomPositions(@view rf_coils.coil_sens[p,:])
end

function Base.view(rf_coils::UniformRFCoils, p)
return rf_coils
end

function acquire_signal!(sig, rf_coils::UniformRFCoils, Mxy)
sig .= transpose(sum(Mxy; dims=1))
return nothing
end


function acquire_signal!(sig, rf_coils::RFCoilsSensDefinedAtPhantomPositions, Mxy)
for i in 1:size(rf_coils.coil_sens, 2)
sig[:, i] .= transpose(sum(rf_coils.coil_sens[:, i] .* Mxy; dims=1))
end
return nothing
end

function getproperty(sys::Scanner, key::Symbol)
if key in fieldnames(HardwareLimits)
return getfield(sys.limits, key)
else
return getfield(sys, key)
end
end

function get_n_coils(rf_coils::UniformRFCoils)
return 1
end

function get_n_coils(rf_coils::RFCoils)
return size(rf_coils.coil_sens, 2)
end

export ArbitraryRFCoils, RFCoilsSensDefinedAtPhantomPositions, UniformRFCoils, acquire_signal!, HardwareLimits, LinearXYZGradients, get_n_coils
1 change: 1 addition & 0 deletions KomaMRICore/src/simulation/Functors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ adapt_storage(T::Type{<:Real}, xs::MotionList) = MotionList(paramtype.(T, xs.mot
# Phantom
@functor Phantom
@functor Motion
@functor Scanner
@functor Translate
@functor Rotate
@functor HeartBeat
Expand Down
1 change: 1 addition & 0 deletions KomaMRICore/src/simulation/SimMethods/Bloch/BlochCPU.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ that they can be re-used from block to block.
function run_spin_precession!(
p::Phantom{T},
seq::DiscreteSequence{T},
sys::Scanner{T},
sig::AbstractArray{Complex{T}},
M::Mag{T},
sim_method::Bloch,
Expand Down
3 changes: 2 additions & 1 deletion KomaMRICore/src/simulation/SimMethods/Bloch/BlochGPU.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ end
function run_spin_precession!(
p::Phantom{T},
seq::DiscreteSequence{T},
sys::Scanner{T},
sig::AbstractArray{Complex{T}},
M::Mag{T},
sim_method::Bloch,
Expand Down Expand Up @@ -159,7 +160,7 @@ function run_spin_precession!(
outflow_spin_reset!(pre.Mxy, seq_block.tp_ADC', p.motion; seq_t=seq.t)
end

sig .= transpose(sum(pre.Mxy; dims=1))
acquire_signal!(sig, sys.rf_coils, pre.Mxy)
end

#Mxy precession and relaxation, and Mz relaxation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ precession.
function run_spin_precession!(
p::Phantom{T},
seq::DiscreteSequence{T},
sys::Scanner{T},
sig::AbstractArray{Complex{T}},
M::Mag{T},
sim_method::BlochDict,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ precession.
function run_spin_precession!(
p::Phantom{T},
seq::DiscreteSequence{T},
sys::Scanner,
sig::AbstractArray{Complex{T}},
M::Mag{T},
sim_method::SimulationMethod,
Expand Down Expand Up @@ -51,7 +52,7 @@ function run_spin_precession!(
outflow_spin_reset!(Mxy, seq.t', p.motion)
outflow_spin_reset!(M, seq.t', p.motion; replace_by=p.ρ)
#Acquired signal
sig .= transpose(sum(Mxy[:, findall(seq.ADC)]; dims=1)) #<--- TODO: add coil sensitivities
acquire_signal!(sig, sys.rf_coils, Mxy[:, findall(seq.ADC)])
return nothing
end

Expand Down
4 changes: 3 additions & 1 deletion KomaMRICore/src/simulation/SimMethods/SimulationMethod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ include("Magnetization.jl")
function sim_output_dim(
obj::Phantom{T}, seq::Sequence, sys::Scanner, sim_method::SimulationMethod
) where {T<:Real}
return (sum(seq.ADC.N), 1) #Nt x Ncoils, This should consider the coil info from sys
# Determine the number of coils
n_coils = get_n_coils(sys.rf_coils)
return (sum(seq.ADC.N), n_coils) # Nt x Ncoils
end

"""Magnetization initialization for Bloch simulation method."""
Expand Down
8 changes: 6 additions & 2 deletions KomaMRICore/src/simulation/SimulatorCore.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ separating the spins of the phantom `obj` in `Nthreads`.
function run_spin_precession_parallel!(
obj::Phantom{T},
seq::DiscreteSequence{T},
sys::Scanner,
sig::AbstractArray{Complex{T}},
Xt::SpinStateRepresentation{T},
sim_method::SimulationMethod,
Expand All @@ -91,7 +92,7 @@ function run_spin_precession_parallel!(

ThreadsX.foreach(enumerate(parts)) do (i, p)
run_spin_precession!(
@view(obj[p]), seq, @view(sig[dims..., i]), @view(Xt[p]), sim_method, backend, @view(prealloc[p])
@view(obj[p]), seq, @view(sys[p]), @view(sig[dims..., i]), @view(Xt[p]), sim_method, backend, @view(prealloc[p])
)
end

Expand Down Expand Up @@ -167,6 +168,7 @@ take advantage of CPU parallel processing.
function run_sim_time_iter!(
obj::Phantom,
seq::DiscreteSequence,
sys::Scanner,
sig::AbstractArray{Complex{T}},
Xt::SpinStateRepresentation{T},
sim_method::SimulationMethod,
Expand Down Expand Up @@ -199,7 +201,7 @@ function run_sim_time_iter!(
rfs += 1
else
run_spin_precession_parallel!(
obj, seq_block, @view(sig[acq_samples, dims...]), Xt, sim_method, backend, prealloc_block(prealloc_result, block); Nthreads
obj, seq_block, sys, @view(sig[acq_samples, dims...]), Xt, sim_method, backend, prealloc_block(prealloc_result, block); Nthreads
)
end
samples += Nadc
Expand Down Expand Up @@ -378,6 +380,7 @@ function simulate(
seqd = seqd |> gpu #DiscreteSequence
Xt = Xt |> gpu #SpinStateRepresentation
sig = sig |> gpu #Signal
sys = sys |> gpu #Scanner
precalc = precalc |> gpu #Info calculated prior to simulation
end

Expand All @@ -389,6 +392,7 @@ function simulate(
@time timed_tuple = @timed run_sim_time_iter!(
obj,
seqd,
sys,
sig,
Xt,
sim_params["sim_method"],
Expand Down
57 changes: 57 additions & 0 deletions examples/3.tutorials/lit-07-Coils.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# # Experimental: Simulating with realistic coils

using KomaMRI # hide
obj = brain_phantom2D()
coil_sens1 = exp.(-π * (((obj.x) .+ 0.1) .^ 2 / 0.02) .+ ((obj.y) .^ 2 / 0.02))
coil_sens2 = exp.(-π * (((obj.x) .- 0.1) .^ 2 / 0.02) .+ ((obj.y) .^ 2 / 0.02))
coil_sens3 = exp.(-π * ((obj.x) .^ 2 / 0.02) .+ (((obj.y) .+ 0.1) .^ 2 / 0.02))
coil_sens4 = exp.(-π * ((obj.x) .^ 2 / 0.02) .+ (((obj.y) .- 0.1) .^ 2 / 0.02))
coil_sens = hcat(coil_sens1, coil_sens2, coil_sens3, coil_sens4)
sys = Scanner()
sys.rf_coils = RFCoilsSensDefinedAtPhantomPositions(complex.(coil_sens))
#sys.rf_coils = ArbitraryRFCoils(obj.x, obj.y, obj.z, complex.(coil_sens), complex.(coil_sens))
seq_file = joinpath(
dirname(pathof(KomaMRI)),
"../examples/5.koma_paper/comparison_accuracy/sequences/EPI/epi_100x100_TE100_FOV230.seq",
)
seq = read_seq(seq_file)
# And simulate:

sim_params = KomaMRICore.default_sim_params()
sim_params["sim_method"] = Bloch()
raw = simulate(obj, seq, sys; sim_params)

acq = AcquisitionData(raw) # hide
acq.traj[1].circular = false # hide
Nx, Ny = raw.params["reconSize"][1:2] # hide
# reco parameters
params = Dict{Symbol,Any}()
params[:reco] = "multiCoil"
params[:reconSize] = (Nx, Ny)
params[:iterations] = 40

# Coil sensitivities interpolated to reconstruction points
FOV = 230e-3
xq = range(-FOV / 2, FOV / 2, Nx)
yq = range(-FOV / 2, FOV / 2, Ny)
coil_sens1 = exp.(-π * (((xq) .+ 0.1) .^ 2 / 0.02) .+ ((yq') .^ 2 / 0.02))
coil_sens2 = exp.(-π * (((xq) .- 0.1) .^ 2 / 0.02) .+ ((yq') .^ 2 / 0.02))
coil_sens3 = exp.(-π * ((xq) .^ 2 / 0.1) .+ (((yq') .+ 0.1) .^ 2 / 0.02))
coil_sens4 = exp.(-π * ((xq) .^ 2 / 0.1) .+ (((yq') .- 0.1) .^ 2 / 0.02))
coil_sens_recon = Float32.([coil_sens1[:] coil_sens2[:] coil_sens3[:] coil_sens4[:]])
params[:senseMaps] = reshape(complex.(coil_sens_recon), Nx, Ny, 1, size(coil_sens_recon, 2))

# do reconstruction
Ireco = reconstruction(acq, params)
recon_image = plot_image(abs.(Ireco.data[:, :]))
reconParams = Dict{Symbol,Any}(:reco => "direct", :reconSize => (Nx, Ny)) # hide
image = reconstruction(acq, reconParams) # hide
slice_abs1 = abs.(image[:, :, 1, 1, 1, 1]) # hide
slice_abs2 = abs.(image[:, :, 1, 1, 2, 1]) # hide
slice_abs3 = abs.(image[:, :, 1, 1, 3, 1]) # hide
slice_abs4 = abs.(image[:, :, 1, 1, 4, 1]) # hide
p3 = plot_image(slice_abs1; height=400)
p4 = plot_image(slice_abs2; height=400) # hide
p5 = plot_image(slice_abs3; height=400)
p6 = plot_image(slice_abs4; height=400) # hide
[recon_image; p3 p4 p5 p6]
Loading