Beispiel #1
0
def add_gradients(grads: list, system=None):
    """
    Adds up gradient events
    """
    from pypulseq.make_arbitrary_grad import make_arbitrary_grad

    if system == None:
        raise ValueError('Provide the MR System limits.')

    # First gradient defines channel
    channel = grads[0].channel

    # read in gradient waveforms
    grad_length = []
    grad_list = []
    for grad in grads:
        w = waveform_from_seqblock(grad)
        grad_list.append(w)
        grad_length.append(len(w))

    # prolong waveforms to maximum length and add them up
    length = max(grad_length)
    added_grad = np.array(np.zeros(length))
    for grad in grad_list:
        grad = np.append(grad, np.zeros(length - len(grad)))
        added_grad += grad

    return make_arbitrary_grad(channel=channel,
                               waveform=added_grad,
                               system=system)
def make_extended_trapezoid(channel: str, times: np.ndarray = np.zeros(1), amplitudes: np.ndarray = np.zeros(1),
                            system: Opts = Opts(), max_grad: float = 0, max_slew: float = 0, skip_check: bool = False):
    """
    Creates an extend trapezoidal gradient event by defined by amplitude values in `amplitudes` at time indices in
    `times`.

    Parameters
    ----------
    channel : str
        Orientation of extended trapezoidal gradient event. Must be one of x, y or z.
    times : numpy.ndarray, optional
        Time points at which `amplitudes` defines amplitude values. Default is 0.
    amplitudes : numpy.ndarray, optional
        Values defined at `times` time indices. Default is 0.
    system : Opts, optional
        System limits. Default is a system limits object initialised to default values.
    max_grad : float, optional
        Maximum gradient strength. Default is 0.
    max_slew : float, optional
        Maximum slew rate. Default is 0.
    skip_check : bool, optional
        Perform check. Default is false.

    Returns
    -------
    grad : SimpleNamespace
        Extended trapezoid gradient event.
    """
    if channel not in ['x', 'y', 'z']:
        raise ValueError()

    if not np.any(times):
        raise ValueError('At least one of the given times must be non-zero')

    if np.any(np.diff(times) <= 0):
        raise ValueError('Times must be in ascending order and all times must be distinct')

    if not np.any(amplitudes):
        raise ValueError('At least one of the given amplitudes must be non-zero')

    if skip_check is False and times[0] > 0 and amplitudes[0] != 0:
        raise ValueError('If first amplitude of a gradient is non-zero, it must connect to previous block')

    if max_grad <= 0:
        max_grad = system.max_grad

    if max_slew <= 0:
        max_slew = system.max_slew

    waveform = points_to_waveform(times=times, amplitudes=amplitudes, grad_raster_time=system.grad_raster_time)
    grad = make_arbitrary_grad(channel=channel, waveform=waveform, system=system, max_grad=max_grad, max_slew=max_slew,
                               delay=times[0])
    grad.first = amplitudes[0]
    grad.last = amplitudes[-1]

    return grad
def make_extended_trapezoid(channel,
                            times=0,
                            amplitudes=0,
                            system=Opts(),
                            max_grad=0,
                            max_slew=0,
                            skip_check=False):
    if channel not in ['x', 'y', 'z']:
        raise ValueError()

    if not np.any(times):
        raise ValueError('At least one of the given times must be non-zero')

    if np.any(np.diff(times) <= 0):
        raise ValueError(
            'Times must be in ascending order and all times mut be distinct')

    if not np.any(amplitudes):
        raise ValueError(
            'At least one of the given amplitudes must be non-zero')

    if skip_check is False and times[0] > 0 and amplitudes[0] != 0:
        raise ValueError(
            'If first amplitude of a gradient is non-zero, it must connect to previous block'
        )

    if max_grad <= 0:
        max_grad = system.max_grad

    if max_slew <= 0:
        max_slew = system.max_slew

    waveform = points_to_waveform(times=times,
                                  amplitudes=amplitudes,
                                  grad_raster_time=system.grad_raster_time)
    grad = make_arbitrary_grad(channel=channel,
                               waveform=waveform,
                               system=system,
                               max_grad=max_grad,
                               max_slew=max_slew,
                               delay=times[0])
    grad.first = amplitudes[0]
    grad.last = amplitudes[-1]

    return grad
spirals = [{'deph': [None, None], 'spiral': [None, None], 'reph': [None, None]} for k in range(Nintl)]
reph_dur = []
save_sp = np.zeros((Nintl, 2, N_spiral)) # save gradients for reco
rot_angle = np.linspace(0, max_rot, Nintl, endpoint=False)
for k in range(Nintl):
    # rotate spiral gradients for shot selection
    sp_x, sp_y = ph.rot_grad(spiral_x, spiral_y, rot_angle[k])

    save_sp[k,0,:] = sp_x
    save_sp[k,1,:] = sp_y

    # unit to [Hz/m], make spiral gradients
    sp_x *= system.gamma
    sp_y *= system.gamma

    spirals[k]['spiral'][0] = make_arbitrary_grad(channel='x', waveform=sp_x, delay=system.adc_dead_time, system=system)
    spirals[k]['spiral'][1] = make_arbitrary_grad(channel='y', waveform=sp_y, delay=system.adc_dead_time, system=system)

    if spiraltype==1:
        # calculate rephaser area
        area_x = sp_x.sum()*system.grad_raster_time
        area_y = sp_y.sum()*system.grad_raster_time

        # calculate rephasers and make gradients
        amp_x, ftop_x, ramp_x = ph.trap_from_area(-area_x, system, slewrate = 100) # reduce slew rate to 100 T/m/s to avoid stimulation
        amp_y, ftop_y, ramp_y = ph.trap_from_area(-area_y, system, slewrate = 100)
        spirals[k]['reph'][0] = make_trapezoid(channel='x', system=system, amplitude=amp_x, flat_time=ftop_x, rise_time=ramp_x)
        spirals[k]['reph'][1] = make_trapezoid(channel='y', system=system, amplitude=amp_y, flat_time=ftop_y, rise_time=ramp_y)
        reph_dur.append(max(ftop_x+2*ramp_x, ftop_y+2*ramp_y))

Beispiel #5
0
def add_gradients(grads: Union[list, tuple],
                  system=Opts(),
                  max_grad: int = 0,
                  max_slew: int = 0) -> SimpleNamespace:
    """
    Superpose several gradient events.

    Parameters
    ----------
    grads : list or tuple
        List or tuple of 'SimpleNamespace' gradient events.
    system : Opts, optional, default=Opts()
        System limits.
    max_grad : float, optional, default=0
        Maximum gradient amplitude.
    max_slew : float, optional, default=0
        Maximum slew rate.

    Returns
    -------
    grad : SimpleNamespace
        Superimposition of gradient events from `grads`.
    """
    max_grad = max_grad if max_grad > 0 else system.max_grad
    max_slew = max_slew if max_slew > 0 else system.max_slew

    if len(grads) < 2:
        raise Exception()

    # First gradient defines channel
    channel = grads[0].channel

    # Find out the general delay of all gradients and other statistics
    delays, firsts, lasts, durs = [], [], [], []
    for ii in range(len(grads)):
        delays.append(grads[ii].delay)
        firsts.append(grads[ii].first)
        lasts.append(grads[ii].last)
        durs.append(calc_duration(grads[ii]))

    # Convert to numpy.ndarray for fancy-indexing later on
    firsts, lasts = np.array(firsts), np.array(lasts)

    common_delay = min(delays)
    total_duration = max(durs)

    waveforms = dict()
    max_length = 0
    for ii in range(len(grads)):
        g = grads[ii]
        if g.type == 'grad':
            waveforms[ii] = g.waveform
        elif g.type == 'trap':
            if g.flat_time > 0:  # Triangle or trapezoid
                times = [
                    g.delay - common_delay,
                    g.delay - common_delay + g.rise_time,
                    g.delay - common_delay + g.rise_time + g.flat_time,
                    g.delay - common_delay + g.rise_time + g.flat_time +
                    g.fall_time
                ]
                amplitudes = [0, g.amplitude, g.amplitude, 0]
            else:
                times = [
                    g.delay - common_delay,
                    g.delay - common_delay + g.rise_time,
                    g.delay - common_delay + g.rise_time + g.flat_time
                ]
                amplitudes = [0, g.amplitude, 0]
            waveforms[ii] = points_to_waveform(
                times=times,
                amplitudes=amplitudes,
                grad_raster_time=system.grad_raster_time)
        else:
            raise ValueError('Unknown gradient type')

        if g.delay - common_delay > 0:
            # Stop for numpy.arange is not g.delay - common_delay - system.grad_raster_time like in Matlab
            # so as to include the endpoint
            t_delay = np.arange(0,
                                g.delay - common_delay,
                                step=system.grad_raster_time)
            waveforms[ii] = np.insert(waveforms[ii], 0, t_delay)

        num_points = len(waveforms[ii])
        max_length = num_points if num_points > max_length else max_length

    w = np.zeros(max_length)
    for ii in range(len(grads)):
        wt = np.zeros(max_length)
        wt[0:len(waveforms[ii])] = waveforms[ii]
        w += wt

    grad = make_arbitrary_grad(channel,
                               w,
                               system,
                               max_slew=max_slew,
                               max_grad=max_grad,
                               delay=common_delay)
    grad.first = np.sum(firsts[np.array(delays) == common_delay])
    grad.last = np.sum(lasts[np.where(durs == total_duration)])

    return grad
            flip_angle=rf_fatsat['flip'] * 180 / pi,
            system=system,
            signal=np.squeeze(rf_fs_wav),
            freq_offset=-440,
            phase_offset=rfphs)  #, time_bw_product=1.5)

        seq.add_block(rf_fs)

        # Slab excitation + PRESTO gradients block
        rf_td, _ = make_arbitrary_rf(flip_angle=rf_tipdown['flip'] * 180 / pi,
                                     system=system,
                                     signal=np.squeeze(rf_td_wav),
                                     phase_offset=rfphs)  #,time_bw_product=8)

        gx_td = make_arbitrary_grad(channel='x',
                                    system=system,
                                    waveform=np.squeeze(gx_td_wav))

        gz_td = make_arbitrary_grad(channel='z',
                                    system=system,
                                    waveform=np.squeeze(gz_td_wav))

        seq.add_block(rf_td, gx_td, gz_td)

        # Read out block
        slice = iz
        ileaf = (
            ((iframe % fmri['nLeafs']) + iz) %
            fmri['nLeafs']) + 1  # rotate leaf every frame and every kz platter
        phi = 2 * pi * (ileaf -
                        1) / fmri['nLeafs']  # leaf rotation angle in radians
Beispiel #7
0
def add_gradients(grads, system=Opts(), max_grad=0, max_slew=0):
    max_grad = max_grad if max_grad > 0 else system.max_grad
    max_slew = max_slew if max_slew > 0 else system.max_slew

    if len(grads) < 2:
        raise Exception()

    # First gradient defines channel
    channel = grads[0].channel

    # Find out the general delay of all gradients and other statistics
    delays, firsts, lasts, durs = [], [], [], []
    for ii in range(len(grads)):
        delays.append(grads[ii].delay)
        firsts.append(grads[ii].first)
        lasts.append(grads[ii].last)
        durs.append(calc_duration(grads[ii]))

    common_delay = min(delays)
    total_duration = max(durs)

    waveforms = dict()
    max_length = 0
    for ii in range(len(grads)):
        g = grads[ii]
        if g.type == 'grad':
            waveforms[ii] = g.waveform
        elif g.type == 'trap':
            if g.flat_time > 0:  # Triangle or trapezoid
                times = [
                    g.delay - common_delay,
                    g.delay - common_delay + g.rise_time,
                    g.delay - common_delay + g.rise_time + g.flat_time,
                    g.delay - common_delay + g.rise_time + g.flat_time +
                    g.fall_time
                ]
                amplitudes = [0, g.amplitude, g.amplitude, 0]
            else:
                times = [
                    g.delay - common_delay,
                    g.delay - common_delay + g.rise_time,
                    g.delay - common_delay + g.rise_time + g.flat_time
                ]
                amplitudes = [0, g.amplitude, 0]
            waveforms[ii] = points_to_waveform(
                times=times,
                amplitudes=amplitudes,
                grad_raster_time=system.grad_raster_time)
        else:
            raise ValueError('Unknown gradient type')

        if g.delay - common_delay > 0:
            t_delay = list(
                range(0, g.delay - common_delay - system.grad_raster_time,
                      system.grad_raster_time))
            waveforms[ii] = waveforms[ii].insert(0, t_delay)

        num_points = len(waveforms[ii])
        max_length = num_points if num_points > max_length else max_length

    w = np.zeros((max_length, 1))
    for ii in range(len(grads)):
        wt = np.zeros((max_length, 1))
        wt[0:len(waveforms[ii])] = waveforms[ii]
        w += wt

    grad = make_arbitrary_grad(channel,
                               w,
                               system,
                               max_slew=max_slew,
                               max_grad=max_grad,
                               delay=common_delay)
    grad.first = np.sum(firsts[np.where(delays == common_delay)])
    grad.last = np.sum(lasts[np.where(durs == total_duration)])

    return grad
Beispiel #8
0
from pypulseq.Sequence.sequence import Sequence
from pypulseq.opts import Opts
from pypulseq.make_arbitrary_grad import make_arbitrary_grad
import numpy as np

seq = Sequence(system=Opts())

gx = make_arbitrary_grad(channel='x',
                         waveform=np.array([1, 2, 3, 4, 5, 4, 3, 2, 1]))
seq.add_block(gx)

seq.write("hiseq.seq")

seq2 = Sequence()
seq2.read('hiseq.seq')
print(seq2.get_block(1).gx)
gz_reph = make_trapezoid(kwargs_for_gz_reph)

kwargs_for_gz_spoil = {
    "channel": 'z',
    "system": system,
    "area": gz.area * 2,
    "duration": 3 * pre_time
}
gz_spoil = make_trapezoid(kwargs_for_gz_spoil)

kwargs_for_arb_gx = {
    "channel": 'x',
    "system": system,
    "waveform": np.squeeze(np.real(G[:, 0]))
}
gx = make_arbitrary_grad(kwargs_for_arb_gx)

delayTE = TE - calc_duration(gz_reph) - (calc_duration(rf) / 2)
delayTR = TR - calc_duration(gz_reph) - calc_duration(rf) - calc_duration(
    gx) - calc_duration(gz_spoil)
delay1 = make_delay(delayTE)
delay2 = make_delay(delayTR)

for s in range(n_slices):
    w
freq_offset = gz.amplitude * z[s]
rf.freq_offset = freq_offset

for ns in range(n_shots):
    seq.add_block(rf, gz)
    seq.add_block(gz_reph)
def make_extended_trapezoid(channel: str, amplitudes: Iterable = np.zeros(1), max_grad: float = 0,
                            max_slew: float = 0, system: Opts = Opts(), skip_check: bool = False,
                            times: Iterable = np.zeros(1)) -> SimpleNamespace:
    """
    Creates an extend trapezoidal gradient event by defined by amplitude values in `amplitudes` at time indices in
    `times`.

    Parameters
    ----------
    channel : str
        Orientation of extended trapezoidal gradient event. Must be one of 'x', 'y' or 'z'.
    amplitudes : numpy.ndarray, optional, default=09
        Values defined at `times` time indices.
    max_grad : float, optional, default=0
        Maximum gradient strength.
    max_slew : float, optional, default=0
        Maximum slew rate.
    system : Opts, optional, default=Opts()
        System limits.
    skip_check : bool, optional, default=False
        Perform check.
    times : numpy.ndarray, optional, default=np.zeros(1)
        Time points at which `amplitudes` defines amplitude values.

    Returns
    -------
    grad : SimpleNamespace
        Extended trapezoid gradient event.

    Raises
    ------
    ValueError
        If invalid `channel` is passed. Must be one of 'x', 'y' or 'z'.
        If all elements in `times` are zero.
        If elements in `times` are not in ascending order or not distinct.
        If all elements in `amplitudes` are zero.
        If first amplitude of a gradient is non-ero and does not connect to a previous block.
    """
    if channel not in ['x', 'y', 'z']:
        raise ValueError(f"Invalid channel. Must be one of 'x', 'y' or 'z'. Passed: {channel}")

    if not np.any(times):
        raise ValueError('At least one of the given times must be non-zero')

    if np.any(np.diff(times) <= 0):
        raise ValueError('Times must be in ascending order and all times must be distinct')

    if not np.any(amplitudes):
        raise ValueError('At least one of the given amplitudes must be non-zero')

    if skip_check is False and times[0] > 0 and amplitudes[0] != 0:
        raise ValueError('If first amplitude of a gradient is non-zero, it must connect to previous block')

    if max_grad <= 0:
        max_grad = system.max_grad

    if max_slew <= 0:
        max_slew = system.max_slew

    waveform = points_to_waveform(times=times, amplitudes=amplitudes, grad_raster_time=system.grad_raster_time)
    grad = make_arbitrary_grad(channel=channel, waveform=waveform, system=system, max_grad=max_grad, max_slew=max_slew,
                               delay=times[0])
    grad.first = amplitudes[0]
    grad.last = amplitudes[-1]

    return grad