Learn Sampling pattern for multi-coil MRI#

A small pytorch example to showcase learning k-space sampling patterns. This example showcases the auto-diff capabilities of the NUFFT operator wrt to k-space trajectory in mri-nufft.

Briefly, in this example we try to learn the k-space samples \(\mathbf{K}\) for the following cost function:

\[\mathbf{\hat{K}} = arg \min_{\mathbf{K}} || \sum_{\ell=1}^LS_\ell^* \mathcal{F}_\mathbf{K}^* D_\mathbf{K} \mathcal{F}_\mathbf{K} x_\ell - \mathbf{x}_{sos} ||_2^2\]

where \(S_\ell\) is the sensitivity map for the \(\ell\)-th coil, \(\mathcal{F}_\mathbf{K}\) is the forward NUFFT operator and \(D_\mathbf{K}\) is the density compensators for trajectory \(\mathbf{K}\), \(\mathbf{x}_\ell\) is the image for the \(\ell\)-th coil, and \(\mathbf{x}_{sos} = \sqrt{\sum_{\ell=1}^L x_\ell^2}\) is the sum-of-squares image as target image to be reconstructed.

In this example, the forward NUFFT operator \(\mathcal{F}_\mathbf{K}\) is implemented with model.operator while the SENSE operator model.sense_op models the term \(\mathbf{A} = \sum_{\ell=1}^LS_\ell^* \mathcal{F}_\mathbf{K}^* D_\mathbf{K}\). For our data, we use a 2D slice of a 3D MRI image from the BrainWeb dataset, and the sensitivity maps are simulated using the birdcage_maps function from sigpy.mri.

Note

To showcase the features of mri-nufft, we use `` “cufinufft”`` backend for model.operator without density compensation and "gpunufft" backend for model.sense_op with density compensation.

Warning

This example only showcases the autodiff capabilities, the learned sampling pattern is not scanner compliant as the scanner gradients required to implement it violate the hardware constraints. In practice, a projection \(\Pi_\mathcal{Q}(\mathbf{K})\) into the scanner constraints set \(\mathcal{Q}\) is recommended (see [Proj]). This is implemented in the proprietary SPARKLING package [Sparks]. Users are encouraged to contact the authors if they want to use it.

Imports#

import os

import brainweb_dl as bwdl
import matplotlib.pyplot as plt
import numpy as np
import torch
import matplotlib.animation as animation

from mrinufft import get_operator
from mrinufft.extras import get_smaps
from mrinufft.trajectories import initialize_2D_radial
from sigpy.mri import birdcage_maps
/volatile/github-ci-mind-inria/gpu_mind_runner/_work/mri-nufft/mri-nufft/.venv/lib/python3.12/site-packages/cupyx/jit/_interface.py:247: FutureWarning: cupyx.jit.rawkernel is experimental. The interface can change in the future.
  cupy._util.experimental('cupyx.jit.rawkernel')

Setup a simple class to learn trajectory#

Note

While we are only learning the NUFFT operator, we still need the gradient wrt_data=True to have all the gradients computed correctly. See [Projector] for more details.

BACKEND = os.environ.get("MRINUFFT_BACKEND", "cufinufft")
plt.rcParams["animation.embed_limit"] = 2**30  # 1GiB is very large.


class Model(torch.nn.Module):
    def __init__(self, inital_trajectory, n_coils, img_size=(256, 256)):
        super(Model, self).__init__()
        self.trajectory = torch.nn.Parameter(
            data=torch.Tensor(inital_trajectory),
            requires_grad=True,
        )
        sample_points = inital_trajectory.reshape(-1, inital_trajectory.shape[-1])
        # A simple acquisition model simulated with a forward NUFFT operator. We dont need density compensation here.
        # The trajectory is scaled by 2*pi for cufinufft backend.
        self.operator = get_operator(BACKEND, wrt_data=True, wrt_traj=True)(
            sample_points * 2 * np.pi,
            shape=img_size,
            n_coils=n_coils,
            squeeze_dims=False,
        )
        # A simple density compensated adjoint SENSE operator with sensitivity maps `smaps`.
        self.sense_op = get_operator(BACKEND, wrt_data=True, wrt_traj=True)(
            sample_points,
            shape=img_size,
            density=True,
            n_coils=n_coils,
            smaps=np.ones(
                (n_coils, *img_size), dtype=np.complex64
            ),  # Dummy smaps, this is updated in forward pass
            squeeze_dims=False,
        )
        self.img_size = img_size

    def forward(self, x):
        """Forward pass of the model."""
        # Update the trajectory in the NUFFT operator.
        # The trajectory is scaled by 2*pi for cufinufft backend.
        # Note that the re-computation of density compensation happens internally.
        self.operator.samples = self.trajectory.clone() * 2 * np.pi
        self.sense_op.samples = self.trajectory.clone()

        # Simulate the acquisition process
        kspace = self.operator.op(x)

        # Recompute the sensitivity maps for the updated trajectory.
        self.sense_op.smaps = get_smaps("low_frequency")(
            self.trajectory.detach().numpy(),
            self.img_size,
            kspace.detach(),
            backend=BACKEND,
            density=self.sense_op.density,
            blurr_factor=20,
        )
        # Reconstruction using the sense operator
        adjoint = self.sense_op.adj_op(kspace).abs()
        return adjoint / torch.mean(adjoint)

Setup model and optimizer#

num_epochs = 100

n_coils = 6
init_traj = (
    initialize_2D_radial(32, 256).astype(np.float32).reshape(-1, 2).astype(np.float32)
)
model = Model(init_traj, n_coils=n_coils, img_size=(256, 256))
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
schedulder = torch.optim.lr_scheduler.LinearLR(
    optimizer,
    start_factor=1,
    end_factor=0.1,
    total_iters=num_epochs,
)
/volatile/github-ci-mind-inria/gpu_mind_runner/_work/mri-nufft/mri-nufft/.venv/lib/python3.12/site-packages/torch/cuda/__init__.py:1074: UserWarning: Can't initialize NVML
  raw_cnt = _raw_device_count_nvml()

Setup data#

mri_2D = torch.from_numpy(np.flipud(bwdl.get_mri(4, "T1")[80, ...]).astype(np.float32))
mri_2D = mri_2D / torch.mean(mri_2D)
smaps_simulated = torch.from_numpy(birdcage_maps((n_coils, *mri_2D.shape)))
mcmri_2D = mri_2D[None].to(torch.complex64) * smaps_simulated


model.eval()
recon = model(mcmri_2D)
W0707 00:36:16.307000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.

  0%|          | 0/10 [00:00<?, ?it/s]
 30%|███       | 3/10 [00:00<00:00, 24.41it/s]
 80%|████████  | 8/10 [00:00<00:00, 34.36it/s]
100%|██████████| 10/10 [00:00<00:00, 34.95it/s]

Training and plotting#

fig, axs = plt.subplots(2, 2, figsize=(10, 10))
fig.suptitle("Training Starting")
axs = axs.flatten()

axs[0].imshow(np.abs(mri_2D), cmap="gray")
axs[0].axis("off")
axs[0].set_title("MR Image")

traj_scat = axs[1].scatter(*init_traj.T, s=0.5)
axs[1].set_title("Trajectory")

recon_im = axs[2].imshow(np.abs(recon.squeeze().detach().cpu().numpy()), cmap="gray")
axs[2].axis("off")
axs[2].set_title("Reconstruction")
(loss_curve,) = axs[3].plot([], [])
axs[3].grid()
axs[3].set_xlabel("epochs")
axs[3].set_ylabel("loss")

fig.tight_layout()


def train():
    """Train loop."""
    losses = []
    for i in range(num_epochs):
        out = model(mcmri_2D)
        loss = torch.nn.functional.mse_loss(out, mri_2D[None, None])  # Compute loss

        optimizer.zero_grad()  # Zero gradients
        loss.backward()  # Backward pass
        optimizer.step()  # Update weights
        with torch.no_grad():
            # clamp the value of trajectory between [-0.5, 0.5]
            for param in model.parameters():
                param.clamp_(-0.5, 0.5)
        schedulder.step()
        losses.append(loss.item())
        yield (
            out.detach().cpu().numpy().squeeze(),
            model.trajectory.detach().cpu().numpy(),
            losses,
        )


def plot_epoch(data):
    img, traj, losses = data

    cur_epoch = len(losses)
    recon_im.set_data(abs(img))
    loss_curve.set_xdata(np.arange(cur_epoch))
    loss_curve.set_ydata(losses)
    traj_scat.set_offsets(traj)

    axs[3].set_xlim(0, cur_epoch)
    axs[3].set_ylim(0, 1.1 * max(losses))
    axs[2].set_title(f"Reconstruction, frame {cur_epoch}/{num_epochs}")
    axs[1].set_title(f"Trajectory, frame {cur_epoch}/{num_epochs}")

    if cur_epoch < num_epochs:
        fig.suptitle("Training in progress " + "." * (1 + cur_epoch % 3))
    else:
        fig.suptitle("Training complete !")


ani = animation.FuncAnimation(
    fig, plot_epoch, train, save_count=num_epochs, repeat=False
)
plt.show()
/volatile/github-ci-mind-inria/gpu_mind_runner/_work/mri-nufft/mri-nufft/examples/GPU/example_learn_samples_multicoil.py:151: DeprecationWarning: __array_wrap__ must accept context and return_scalar arguments (positionally) in the future. (Deprecated NumPy 2.0)
  axs[0].imshow(np.abs(mri_2D), cmap="gray")
W0707 00:36:17.194000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:17.937000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:18.939000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:19.856000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:20.963000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:22.125000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:23.089000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:24.249000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:25.218000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:26.228000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:27.213000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:28.176000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:29.120000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:30.079000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:31.042000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:31.998000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:32.965000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:33.923000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:34.875000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:35.834000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:36.794000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:37.762000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:38.735000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:39.704000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:40.653000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:41.478000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:42.368000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:43.382000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:44.360000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:45.346000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:46.344000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:47.340000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:48.361000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:49.355000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:50.337000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:51.284000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:52.204000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:53.049000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:53.845000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:54.642000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:55.431000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:56.262000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:57.077000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:57.926000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:58.741000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:36:59.541000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:00.391000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:01.196000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:02.011000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:02.836000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:03.648000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:04.470000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:05.257000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:06.080000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:06.888000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:07.758000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:08.576000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:09.435000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:10.260000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:11.085000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:11.915000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:12.714000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:13.567000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:14.382000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:15.209000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:16.096000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:16.957000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:17.802000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:18.675000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:19.502000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:20.322000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:21.182000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:22.044000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:22.926000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:23.835000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:24.727000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:25.594000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:26.520000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:27.404000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:28.280000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:29.151000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:30.074000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:30.980000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:31.902000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:32.792000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:33.706000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:34.593000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:35.462000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:36.409000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:37.301000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:38.177000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:39.111000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:40.010000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:40.871000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:41.785000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:42.706000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:43.572000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:44.442000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:45.315000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:46.216000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:47.123000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:48.328000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:48.957000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:49.956000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:50.900000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:51.899000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:52.832000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:53.773000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:54.732000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:55.666000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:56.543000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:57.511000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:58.380000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:37:59.261000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:00.227000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:01.112000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:02.060000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:03.012000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:03.953000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:04.848000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:05.790000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:06.692000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:07.619000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:08.522000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:09.437000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:10.339000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:11.261000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:12.212000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:13.115000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:14.048000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:14.913000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:15.802000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:16.740000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:17.676000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:18.561000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:19.536000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:20.451000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:21.351000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:22.280000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:23.169000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:24.080000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:25.044000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:26.047000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:26.955000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:27.849000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:28.771000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:29.714000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:30.586000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:31.530000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:32.426000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:33.337000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:34.265000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:35.153000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:36.002000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:36.880000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:37.725000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:38.600000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:39.443000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:40.276000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:41.198000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:42.057000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:42.898000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:43.792000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:44.685000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:45.527000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:46.436000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:47.288000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:48.130000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:49.061000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:49.911000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:50.767000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:51.664000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:52.544000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:53.400000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:54.305000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:55.160000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:56.020000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:56.913000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:57.790000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:58.636000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:38:59.552000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:00.433000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:01.279000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:02.201000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:03.071000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:03.929000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:04.826000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:05.705000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:06.557000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:07.455000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:08.337000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:09.189000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:10.100000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:10.951000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:11.798000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:12.701000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:13.554000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:14.403000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:15.276000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:16.159000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:16.997000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0707 00:39:17.886000 3207562 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.

References#

[Proj]

N. Chauffert, P. Weiss, J. Kahn and P. Ciuciu, “A Projection Algorithm for Gradient Waveforms Design in Magnetic Resonance Imaging,” in IEEE Transactions on Medical Imaging, vol. 35, no. 9, pp. 2026-2039, Sept. 2016, doi: 10.1109/TMI.2016.2544251.

[Sparks]

G. R. Chaithya, P. Weiss, G. Daval-Frérot, A. Massire, A. Vignaud and P. Ciuciu, “Optimizing Full 3D SPARKLING Trajectories for High-Resolution Magnetic Resonance Imaging,” in IEEE Transactions on Medical Imaging, vol. 41, no. 8, pp. 2105-2117, Aug. 2022, doi: 10.1109/TMI.2022.3157269.

[Projector]

Chaithya GR, and Philippe Ciuciu. 2023. “Jointly Learning Non-Cartesian k-Space Trajectories and Reconstruction Networks for 2D and 3D MR Imaging through Projection” Bioengineering 10, no. 2: 158. https://doi.org/10.3390/bioengineering10020158

Total running time of the script: (3 minutes 8.851 seconds)

Gallery generated by Sphinx-Gallery