-
Notifications
You must be signed in to change notification settings - Fork 75
Description
Describe the bug
(Note: This is my first issue report in a public repository, I apologise in advance for any mistakes.)
1.
Line 205 in add_gradients returns an error because of dimension inconsistency.

I changed line 205 from
waveforms[ii] = np.concatenate(([t_delay], waveforms[ii]))
to
waveforms[ii] = np.concatenate((t_delay, waveforms[ii]))
to resolve the error (waveforms[ii] should always have shape (N,) - I think-)
When adding gradients, sometimes too many gradient raster times are added as a delay in add_gradients.
The returned gradient waveform has a jump to zero and back when connecting the individual gradients.
With add_gradients():

Gradients in single blocks:

To Reproduce
run this script:
from math import ceil, isclose
from math import pi as PI
import numpy as np
import pypulseq as pp
# Set up system
system = pp.Opts(
grad_unit='mT/m', max_grad=50, slew_unit='T/m/s',
max_slew=180, grad_raster_time=10e-6)
Seq = pp.Sequence(system=system)
Seq1 = pp.Sequence(system=system)
amplitudes = np.linspace(0.003, 0.04, 15) # [T/m]
readout_dur = 4e-3 # [s]
readout_tps = np.arange(0, readout_dur, system.grad_raster_time)
for ampl in amplitudes:
# Create readout gradient
waveform = ampl * np.cos(2*PI/readout_dur * readout_tps)
g_read = pp.make_arbitrary_grad(
channel='x', waveform=waveform*system.gamma, system=system)
# Create rampup gradient
ramp_dur = g_read.waveform[0]/system.max_slew
ramp_dur = ceil(
ramp_dur/system.grad_raster_time
) * system.grad_raster_time
g_ramp = pp.make_extended_trapezoid(
channel='x', amplitudes=[0, g_read.waveform[-1]],
times=[0, ramp_dur], system=system)
# Create moment nulling gradient for rampup
g_nullmom = pp.make_trapezoid(
channel='x', area=-g_ramp.area, system=system)
single_grads_duration = (
pp.calc_duration(g_nullmom)
+ pp.calc_duration(g_ramp)
+ pp.calc_duration(g_read)
)
# Add native gradients to sequence
Seq.add_block(g_nullmom)
Seq.add_block(g_ramp)
Seq.add_block(g_read)
Seq.add_block(pp.make_delay(1e-3))
# Add gradients
g_ramp.delay = pp.calc_duration(g_nullmom)
g_read.delay = pp.calc_duration(g_ramp)
g_new = pp.add_gradients(
grads=[g_nullmom, g_ramp, g_read],
max_slew=np.inf, # Otherwise slew rate conflict
system=system
)
# Add gradients to sequences
Seq1.add_block(g_new)
Seq1.add_block(pp.make_delay(1e-3))
# Check if gradient timing has changed
if single_grads_duration == pp.calc_duration(g_new):
print(f'Duration does not change with added gradients for amplitude {ampl:.4f}')
else:
print(f'Duration DOES change with added gradients for amplitude {ampl:.4f}')
# add_gradients() calc:
t_delay = np.arange(0, g_read.delay-0.0, step=system.grad_raster_time)
if t_delay.size != round(g_read.delay/system.grad_raster_time):
print('\t GRT added for delay in add_gradients():', t_delay.size)
print('\t Delay to add in units of GRT:', g_read.delay/system.grad_raster_time)
# Show sequence diagramms
dur_seq = Seq.duration()[0]
dur_seq1 = Seq.duration()[0]
Seq.plot(
show_blocks=False, time_range=(0, dur_seq),
time_disp='ms', grad_disp='mT/m', plot_now=True)
Seq1.plot(
show_blocks=False, time_range=(0, dur_seq),
time_disp='ms', grad_disp='mT/m', plot_now=True)
Expected behavior
Added gradients without a jump at the connection point.
Desktop (please complete the following information):
- OS: macOS
- OS Version: Sonoma 14.5
pypulseqversion: 1.4.2 and 1.4.0
Additional context
The numpy.arange() can add one zero too many to the gradient waveform in some cases due to rounding errors.
In the script above, this happens to some of the readouts (e.g. readout two and five).
I'm still kind of a newbie to pulseq so it might be an issue with my code instead of pypulseq itself.
Other than that, I have fixed the rounding issue in my pypulseq installation and can create a PR if you want.