Source code for cmrseq.utils._diffusion

r"""Utility module contains helpers for diffusion sequence design."""
from pint import Quantity
import numpy as np
import scipy.integrate

from cmrseq import Sequence

[docs] def calculate_diffusion_weighting(seq: Sequence, return_bmatrix: bool = False, return_cumulative: bool = False): r"""Evaluates the b-value or b-matrix of arbitrary gradient waveforms by numerical integration. :param seq: Sequence object, which is gridded to obtain hte waveform :param return_bmatrix: If True returns the b-matrix instead of the scalar b-value :param return_cumulative: if True returns the bvalue on raster-time resolution :return: Quantity of shape (1, ) or (t, ) depending on `return_cumulative` argument """ time, gradient_waveform = seq.gradients_to_grid() # Integrate the waveform to obtain the zeroth oder moment at all times gradient_moment = scipy.integrate.cumulative_trapezoid(gradient_waveform, x=time, initial=True, axis=1) q_of_t = (Quantity(gradient_moment, "mT/m*ms") * seq._system_specs.gamma_rad).to("1/mm") # compute the dot product per time step to obtain the squared gradient moment q_squared = Quantity(np.einsum('it, jt -> ijt', q_of_t.m_as("1/mm"), q_of_t.m_as("1/mm")), "1/mm**2") q_squared = q_squared.reshape(9, -1) if return_cumulative: b_val_unitless = scipy.integrate.cumulative_trapezoid(q_squared.m, x=time, initial=True, axis=-1) else: b_val_unitless = scipy.integrate.trapz(q_squared.m, x=time, axis=-1) if not return_bmatrix: b_val_unitless = np.trace(b_val_unitless.reshape(3, 3, -1), axis1=0, axis2=1) bvals = Quantity(b_val_unitless, f"{q_squared.units} * ms") return bvals.to("s/mm**2")