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:1112: 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)
W0724 16:19:12.888000 656863 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]
 60%|██████    | 6/10 [00:00<00:00, 42.83it/s]
100%|██████████| 10/10 [00:00<00:00, 39.55it/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")
W0724 16:19:13.710000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:14.539000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:15.561000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:16.710000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:17.883000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:18.903000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:19.990000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:20.951000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:21.944000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:22.942000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:23.920000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:24.983000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:26.008000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:27.064000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:28.093000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:29.074000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:30.152000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:31.181000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:32.198000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:33.196000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:34.179000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:35.173000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:36.142000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:37.040000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:37.930000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:38.881000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:39.941000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:40.975000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:41.986000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:42.978000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:44.010000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:45.025000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:46.038000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:46.996000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:47.933000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:48.827000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:49.739000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:50.543000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:51.398000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:52.219000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:53.100000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:53.930000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:54.792000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:55.645000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:56.499000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:57.347000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:58.227000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:59.052000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:19:59.915000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:00.780000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:01.595000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:02.495000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:03.299000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:04.148000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:04.949000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:05.794000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:06.659000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:07.505000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:08.323000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:09.158000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:10.023000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:10.829000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:11.637000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:12.443000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:13.282000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:14.104000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:14.902000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:15.713000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:16.531000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:17.379000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:18.256000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:19.076000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:19.913000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:20.767000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:21.605000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:22.457000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:23.317000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:24.164000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:24.974000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:25.816000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:26.662000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:27.472000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:28.333000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:29.187000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:30.056000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:30.873000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:31.719000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:32.622000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:33.441000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:34.299000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:35.158000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:36.003000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:36.804000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:37.617000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:38.499000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:39.321000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:40.124000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:40.976000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:41.821000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:42.627000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:43.427000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:44.508000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:45.194000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:46.130000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:47.011000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:47.858000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:48.729000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:49.654000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:50.487000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:51.362000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:52.268000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:53.110000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:53.986000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:54.871000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:55.699000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:56.645000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:57.479000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:58.317000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:20:59.205000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:00.084000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:00.934000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:01.821000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:02.661000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:03.566000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:04.458000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:05.280000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:06.133000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:07.014000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:07.836000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:08.658000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:09.502000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:10.369000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:11.202000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:12.073000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:12.948000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:13.776000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:14.657000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:15.566000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:16.394000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:17.230000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:18.105000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:19.010000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:19.840000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:20.684000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:21.589000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:22.416000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:23.262000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:24.129000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:24.958000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:25.820000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:26.670000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:27.532000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:28.363000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:29.160000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:30.000000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:30.839000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:31.627000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:32.418000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:33.204000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:34.040000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:34.847000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:35.640000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:36.471000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:37.267000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:38.068000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:38.902000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:39.747000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:40.557000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:41.355000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:42.149000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:43.011000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:43.800000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:44.611000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:45.465000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:46.257000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:47.059000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:47.869000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:48.693000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:49.500000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:50.332000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:51.129000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:51.956000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:52.757000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:53.558000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:54.406000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:55.210000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:56.024000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:56.842000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:57.659000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:58.457000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:21:59.303000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:00.144000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:00.948000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:01.737000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:02.524000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:03.351000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:04.139000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:04.925000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:05.711000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:06.534000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:07.321000 656863 mri-nufft/src/mrinufft/_array_compat.py:265] _call_impl: data is on gpu, it will be moved to CPU.
W0724 16:22:08.104000 656863 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 2.838 seconds)

Gallery generated by Sphinx-Gallery