Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pulse Designer #305

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
26 changes: 26 additions & 0 deletions KomaMRIBase/src/sequences/ADC/design.jl
Copy link
Member

@cncastillo cncastillo Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate functions in different files. All of them, not only the ones in ADC.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
"""
function make_adc(num_samles; Δtadc=0, duration=0, delay=0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo num_samles to num_samples

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function will be completelly replaced

freq_offset=0, phase_offset=0, dead_time=0, sys=nothing)

if !isnothing(sys)
dead_time = sys.ADC_dead_time_T
Δtadc = sys.ADC_Δt

Check warning on line 8 in KomaMRIBase/src/sequences/ADC/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/ADC/design.jl#L7-L8

Added lines #L7 - L8 were not covered by tests
end
Comment on lines +6 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be required, set the default for optional parameter sys = Scanner()


if (Δtadc == 0 && duration == 0) || (Δtadc > 0 && duration > 0)
@error "Either dwell or duration must be defined"

Check warning on line 12 in KomaMRIBase/src/sequences/ADC/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/ADC/design.jl#L12

Added line #L12 was not covered by tests
end
if duration > 0
Δtadc = duration / num_samles
elseif Δtadc > 0
duration = Δtadc * num_samles;

Check warning on line 17 in KomaMRIBase/src/sequences/ADC/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/ADC/design.jl#L16-L17

Added lines #L16 - L17 were not covered by tests
end
Comment on lines +11 to +18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use multiple dispatch

if dead_time > delay
delay = dead_time; # adcDeadTime is added before the actual sampling (and also second time after the sampling period)

Check warning on line 20 in KomaMRIBase/src/sequences/ADC/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/ADC/design.jl#L20

Added line #L20 was not covered by tests
end

adc = ADC(num_samles, duration, delay, freq_offset, phase_offset)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should output a Sequence

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function will be completelly replaced, all the outpus will be of type Sequence


return adc
end
116 changes: 116 additions & 0 deletions KomaMRIBase/src/sequences/Grad/design.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""
"""
function trapezoid(; duration=0, amplitude=0, area=0, flat_area=0,
flat_time=0, rise_time=0, fall_time=0, delay=0,
max_grad=Inf, max_slew=Inf, Δtgr=1e-3, sys=nothing)

if !isnothing(sys)
max_grad = sys.Gmax
max_slew = sys.Smax
Δtgr = sys.GR_Δt

Check warning on line 10 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L8-L10

Added lines #L8 - L10 were not covered by tests
end
Comment on lines +7 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be required, set the default for optional parameter sys = Scanner()


if area == 0 && flat_area == 0 && amplitude == 0
@error "trapezoid: invalid keywords. Must supply either 'area', 'flat_area' or 'amplitude'"

Check warning on line 14 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L14

Added line #L14 was not covered by tests
end
if fall_time > 0 && rise_time == 0
@error "trapezoid: invalid keywords. Must always supply 'rise_time' if 'fall_time' is specified explicitly."

Check warning on line 17 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L17

Added line #L17 was not covered by tests
end

if flat_time > 0
if amplitude == 0
if flat_area == 0
@error "trapezoid: invalid keyworks. When 'flat_time' is provided either 'flat_area' or 'amplitude' must be provided as well; you may consider providing 'duration', 'area' and optionally ramp times instead."

Check warning on line 23 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L23

Added line #L23 was not covered by tests
end
amplitude = flat_area / flat_time
end
if rise_time == 0
rise_time = abs(amplitude) / max_slew;
rise_time = ceil(rise_time / Δtgr) * Δtgr;
if rise_time == 0
rise_time = Δtgr
end
end
if fall_time == 0
fall_time = rise_time
end
elseif duration > 0
if amplitude == 0
if rise_time == 0
dC = 1 / abs(2 * max_slew) + 1 / abs(2 * max_slew)
possible = duration^2 > 4 * abs(area) * dC;
@assert possible "Requested area is too large for this gradient. Minimum required duration (assuming triangle gradient can be realized) is $(round(sqrt(4 * abs(area) * dC) * 1e6)) us"
amplitude = (duration - sqrt(duration^2 - 4 * abs(area) * dC)) / (2 * dC)

Check warning on line 43 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L39-L43

Added lines #L39 - L43 were not covered by tests
else
if fall_time == 0
fall_time = rise_time

Check warning on line 46 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L45-L46

Added lines #L45 - L46 were not covered by tests
end
amplitude = area / (duration - 0.5 * rise_time - 0.5 * fall_time)
possible = duration > (rise_time + fall_time) && abs(amplitude) < max_grad
@assert possible "Requested area is too large for this gradient. Probably amplitude is violated ($(round(abs(amplitude) / max_grad * 100))%)"

Check warning on line 50 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L48-L50

Added lines #L48 - L50 were not covered by tests
end
end
if rise_time == 0
rise_time = ceil(abs(amplitude) / max_slew / Δtgr) * Δtgr
if rise_time == 0
rise_time = Δtgr
end
end
if fall_time == 0
fall_time = rise_time
end
flat_time = duration - rise_time - fall_time
if amplitude == 0
# Adjust amplitude (after rounding) to achieve given area
amplitude = area / (rise_time / 2 + fall_time / 2 + flat_time)

Check warning on line 65 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L65

Added line #L65 was not covered by tests
end
else
if area == 0
@error "trapezoid: invalid keywords. Must supply area or duration"

Check warning on line 69 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L69

Added line #L69 was not covered by tests
else
# find the shortest possible duration
# first check if the area can be realized as a triangle
# if not we calculate a trapezoid
rise_time = ceil(sqrt(abs(area) / max_slew) / Δtgr) * Δtgr
if rise_time < Δtgr # the "area" was probably 0 or almost 0 ...
rise_time = Δtgr;
end
amplitude = area / rise_time
t_eff = rise_time
if abs(amplitude) > max_grad
t_eff = ceil(abs(area) / max_grad / Δtgr) * Δtgr
amplitude = area / t_eff
if rise_time == 0
rise_time = Δtgr

Check warning on line 84 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L81-L84

Added lines #L81 - L84 were not covered by tests
end
end
flat_time = t_eff - rise_time
fall_time = rise_time
end
end
Comment on lines +13 to +90
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use multiple dispatch to simplify this, the code is too convoluted


@assert abs(amplitude) <= max_grad "trapezoid: invalid amplitude. Amplitude violation ($(round(abs(amplitude) / max_grad * 100))%)"
Copy link
Member

@cncastillo cncastillo Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use functions to check hardware limits for the input sys.


return Grad(amplitude, flat_time, rise_time, fall_time, delay)
end

"""
"""
function arbitrary_grad(waveform; delay=0,
max_grad=Inf, max_slew=Inf, Δtgr=1e-3, sys=nothing)

if !isnothing(sys)
max_grad = sys.Gmax
max_slew = sys.Smax
Δtgr = sys.GR_Δt

Check warning on line 105 in KomaMRIBase/src/sequences/Grad/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/Grad/design.jl#L103-L105

Added lines #L103 - L105 were not covered by tests
end
Comment on lines +102 to +106
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required


slew = (waveform[2:end] - waveform[1:end-1]) / Δtgr
if !isempty(slew)
@assert maximum(abs.(slew)) <= max_slew "Slew rate violation ($(maximum(abs.(slew)) / max_slew * 100)%)"
end
@assert maximum(abs.(waveform)) <= max_grad "Gradient amplitude violation ($(maximum(abs.(waveform)) / max_grad * 100)%)"
Comment on lines +108 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use functions to check this.


duration = (length(waveform)-1) * Δtgr
return Grad(waveform, duration, 0, 0, delay)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should output a Sequence

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function will be completelly replaced, all the outpus will be of type Sequence

end
4 changes: 4 additions & 0 deletions KomaMRIBase/src/sequences/PulseDesigner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ A module to define different pulse sequences.
module PulseDesigner
using ..KomaMRIBase

include("Grad/design.jl")
include("RF/design.jl")
include("ADC/design.jl")

"""
seq = RF_hard(B1, T, sys; G=[0, 0, 0], Δf=0)

Expand Down
152 changes: 152 additions & 0 deletions KomaMRIBase/src/sequences/RF/design.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"""
"""
function block_pulse(flip_angle; duration=0, freq_offset=0, phase_offset=0,
time_bw_product=0, bandwidth=0, delay=0,
dead_time=0, ring_down_time=0, sys=nothing)

if !isnothing(sys)
dead_time = sys.RF_dead_time_T
ring_down_time = sys.RF_ring_down_T

Check warning on line 9 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L8-L9

Added lines #L8 - L9 were not covered by tests
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required


if duration == 0
if time_bw_product > 0
duration = time_bw_product / bandwidth
elseif bandwidth > 0
duration = 1 / (4 * bandwidth)

Check warning on line 16 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L13-L16

Added lines #L13 - L16 were not covered by tests
else
@error "Either bandwidth or duration must be defined"

Check warning on line 18 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L18

Added line #L18 was not covered by tests
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mulitiple dispatch

amplitude = flip_angle / (2π * γ * duration) * cis(phase_offset)

if dead_time > delay
delay = dead_time

Check warning on line 24 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L24

Added line #L24 was not covered by tests
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delay = max(dead_time, delay)


dly = Delay(0)
if ring_down_time > 0
dly = Delay(delay + duration + ring_down_time) # I NEED a review

Check warning on line 29 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L29

Added line #L29 was not covered by tests
end

return RF(amplitude, duration, freq_offset, delay), dly
Copy link
Member

@cncastillo cncastillo Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should output a Sequence. The DUR variable is not set using Delay objects, we may need to change that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea now is to add a duration to the ouput Sequence

Copy link
Member

@cncastillo cncastillo Mar 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seq.DUR needs to be a vector of Delay's. To be able to combine them as we talked #4

end

"""
"""
function sinc_pulse(flip_angle; duration=0, freq_offset=0, phase_offset=0,
time_bw_product=0, apodization=0.5, centerpos=0.5, delay=0, slice_thickness=0,
dead_time=0, ring_down_time=0, Δtrf=1e-5, Δtgr=1e-3, sys=nothing)

if !isnothing(sys)
dead_time = sys.RF_dead_time_T
ring_down_time = sys.RF_ring_down_T
Δtrf = sys.RF_Δt
Δtgr = sys.GR_Δt

Check warning on line 45 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L42-L45

Added lines #L42 - L45 were not covered by tests
end
Comment on lines +7 to +12
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required.


if duration <= 0
@error "rf pulse duration must be positive"

Check warning on line 49 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L49

Added line #L49 was not covered by tests
end
if Δtrf <= 0
@error "the Δtrf gradient raster time must be positive"

Check warning on line 52 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L52

Added line #L52 was not covered by tests
end

BW = time_bw_product / duration
N = Integer(ceil(duration / Δtrf))
t = range(0, duration; length=N)
window = (1 - apodization) .+ apodization * cos.(2π * ((t .- (centerpos * duration)) / duration))
signal = window .* sinc.(BW * (t .- (centerpos * duration)))
flip = 0.5 * sum(signal[2:end] + signal[1:end-1]) * Δtrf * 2π
Copy link
Member

@cncastillo cncastillo Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use get_flip_angle function, I think this assumes that signal is in a particular unit. Is missing the multiplication by gamma.

signal = signal * flip_angle / flip * cis(phase_offset)
if dead_time > delay
delay = dead_time

Check warning on line 63 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L63

Added line #L63 was not covered by tests
end
Comment on lines +28 to +30
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delay = max(delay, dead_time)

rf = RF(signal, duration, freq_offset, delay)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation problem.


@assert slice_thickness > 0 "slice_thickness must be provided"

amplitude = BW / slice_thickness
area = amplitude * duration
gz = trapezoid(; flat_time=duration, flat_area=area, sys=sys);
gz_area = gz.A * (gz.T + gz.rise / 2 + gz.fall / 2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need a function to calculate the area of a Grad (get_kspace almost does this)

gzr_area = -area*(1 - centerpos) - 0.5*(gz_area - area)
gzr = trapezoid(; sys=sys, area=gzr_area)
if rf.delay > gz.rise
gz.delay = ceil((rf.delay - gz.rise) / Δtgr) * Δtgr # round-up to gradient raster

Check warning on line 76 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L76

Added line #L76 was not covered by tests
end
if rf.delay < gz.rise + gz.delay
rf.delay = gz.rise + gz.delay # these are on the grad raster already which is coarser
end

dly = Delay(0)
if ring_down_time > 0
dly = Delay(rf.delay + rf.T + ring_down_time) # I NEED a review

Check warning on line 84 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L84

Added line #L84 was not covered by tests
end

return rf, gz, gzr, dly
Copy link
Member

@cncastillo cncastillo Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should output a Sequence. The Delay should be the DUR.

end

"""
"""
function arbitrary_rf(signal, flip; freq_offset=0, phase_offset=0,
time_bw_product=0, bandwidth=0, delay=0, slice_thickness=0,
dead_time=0, ring_down_time=0, Δtrf=1e-5, Δtgr=1e-3, sys=nothing)

if !isnothing(sys)
dead_time = sys.RF_dead_time_T
ring_down_time = sys.RF_ring_down_T
Δtrf = sys.RF_Δt
Δtgr = sys.GR_Δt

Check warning on line 100 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L97-L100

Added lines #L97 - L100 were not covered by tests
end

signal = signal / abs(sum(signal * Δtrf)) * flip / 2π * cis(phase_offset)

N = length(signal)
duration = (N-1) * Δtrf
t = range(0, duration; length=N)
Copy link
Member

@cncastillo cncastillo Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this even being used? ( t = range(0, duration; length=N))


if dead_time > delay
delay = dead_time;

Check warning on line 110 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L110

Added line #L110 was not covered by tests
end

rf = RF(signal, duration, freq_offset, delay)

if time_bw_product > 0
if bandwidth > 0
@error "Both 'bandwidth' and 'time_bw_product' cannot be specified at the same time"

Check warning on line 117 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L117

Added line #L117 was not covered by tests
else
bandwidth = time_bw_product / duration
end
end

@assert slice_thickness > 0 "SliceThickness must be provided"
@assert bandwidth > 0 "Bandwidth of pulse must be provided"

BW = bandwidth
if time_bw_product > 0
BW = time_bw_product / duration
end

amplitude = BW / slice_thickness
area = amplitude * duration
gz = trapezoid(; flat_time=duration, flat_area=area, sys=sys)
gz_area = gz.A * (gz.T + gz.rise / 2 + gz.fall / 2)
gzr_area = -area*(1 - KomaMRIBase.get_RF_center(rf) / rf.T) - 0.5*(gz_area - area)
gzr = trapezoid(; sys=sys, area=gzr_area)


if rf.delay > gz.rise
gz.delay = ceil((rf.delay - gz.rise) / Δtgr) * Δtgr # round-up to gradient raster

Check warning on line 140 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L140

Added line #L140 was not covered by tests
end
if rf.delay < gz.rise + gz.delay
rf.delay = gz.rise + gz.delay # these are on the grad raster already which is coarser
end
Comment on lines +108 to +110
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delay = max(...)


dly = Delay(0)
if ring_down_time > 0
dly = Delay(rf.delay + rf.T + ring_down_time) # I NEED a review

Check warning on line 148 in KomaMRIBase/src/sequences/RF/design.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRIBase/src/sequences/RF/design.jl#L148

Added line #L148 was not covered by tests
end
Comment on lines +112 to +115
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if ring_down_time is not > 0, it must be zero, therefore dly = Delay(rf.delay + rf.T + ring_down_time) is always correct


return rf, gz, gzr, delay
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should output a Sequence

end
54 changes: 54 additions & 0 deletions KomaMRIBase/test/runtests.jl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests should verify that the gradient/rf/adc satisfies the design inputs (area of the gradiet, duration, etc)

Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,60 @@ end
spoke = PulseDesigner.radial_base(FOV, N, sys)
@test spoke.DEF["Δθ"] ≈ π / Nspokes
end
@testset "design" begin
# trapezoid
duration = 10
amplitude = 5
grad = PulseDesigner.trapezoid(; duration, amplitude)
seq = Sequence()
seq += grad
@test true

# arbitrary_grad
t = range(0, 1; length=20)
waveform = sin.(2π * t)
grad = PulseDesigner.arbitrary_grad(waveform)
seq = Sequence()
seq += grad
@test true

# block_pulse
flip_angle = π / 2
duration = 0.001
rf, delay = PulseDesigner.block_pulse(flip_angle; duration)
seq = Sequence()
seq += rf
@test true

# sinc_pulse
flip_angle = π / 2
duration = 0.001
slice_thickness = 0.001
time_bw_product = 4
rf, gz, gzr, dly = PulseDesigner.sinc_pulse(flip_angle; duration, time_bw_product, slice_thickness)
seq = Sequence([Grad(0,0); Grad(0,0); gz;;], [rf;;])
seq += Sequence([Grad(0,0); Grad(0,0); gzr;;])
@test true

# arbitrary_rf
flip = π / 2
slice_thickness = 0.001
time_bw_product = 4
t = range(0, 0.5; length=20)
signal = sin.(2π * t)
rf, gz, gzr, dly = PulseDesigner.arbitrary_rf(signal, flip; time_bw_product, slice_thickness)
seq = Sequence([Grad(0,0); Grad(0,0); gz;;], [rf;;])
seq += Sequence([Grad(0,0); Grad(0,0); gzr;;])
@test true

# make_adc
num_samles = 10
duration = 0.001
adc = PulseDesigner.make_adc(num_samles; duration)
seq = Sequence()
seq += adc
@test true
end
end

@testitem "Phantom" tags=[:base] begin
Expand Down
Loading