Repository: PTB-MR/mrpro
Pull request #795: Add FastMRI Dataset
Author: login: fzimmermann89
Created: 2025-05-02T23:30:16Z | Merged: 2025-05-12T14:13:28Z

Files need to be donwloaded beforehand (as terms and conditions have to be accepted)

There are two datasets:

### FastMRIKDataset
This Dataset just returns a KData object of a single slice or a full volme
The kdata in fastmri is already zero padded. We remove this padding.

Usage example:
```
dataset = FastMRIDataset('/echo/allgemein/resources/publicTrainingData/fastmri/brain_multicoil_train')

kdata = dataset[0]
reco = mrpro.algorithms.reconstruction.DirectReconstruction(kdata)
img = reco(kdata)
```
### FastMRIImageDataset
Returns either coilweise or inati-coil-combined image tensors (320x320).
Skips a few files of the dataset and changes the matrix size of some, keeping resolution and FOV.
This is needed to have a constant image size for batching.


### Example
![image](https://github.com/user-attachments/assets/b9cac4c3-78d6-4e35-b863-d37e9c01bf33)



Diff:
diff --git a/src/mrpro/phantoms/__init__.py b/src/mrpro/phantoms/__init__.py
index 54e46cf29..db193ee0e 100644
--- a/src/mrpro/phantoms/__init__.py
+++ b/src/mrpro/phantoms/__init__.py
@@ -3,5 +3,12 @@
 from mrpro.phantoms.EllipsePhantom import EllipsePhantom
 from mrpro.phantoms.phantom_elements import EllipseParameters
 from mrpro.phantoms import brainweb
+from mrpro.phantoms.fastmri import FastMRIKDataDataset, FastMRIImageDataset
 
-__all__ = ["EllipseParameters", "EllipsePhantom", "brainweb"]
+__all__ = [
+    "EllipseParameters",
+    "EllipsePhantom",
+    "FastMRIImageDataset",
+    "FastMRIKDataDataset",
+    "brainweb"
+]
\ No newline at end of file
diff --git a/src/mrpro/phantoms/fastmri.py b/src/mrpro/phantoms/fastmri.py
new file mode 100644
index 000000000..522a5b22b
--- /dev/null
+++ b/src/mrpro/phantoms/fastmri.py
@@ -0,0 +1,215 @@
+"""FastMRI dataset."""
+
+from collections.abc import Callable, Sequence
+from os import PathLike
+from pathlib import Path
+from warnings import warn
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+from mrpro.algorithms.csm.inati import inati
+from mrpro.data.AcqInfo import AcqInfo
+from mrpro.data.KData import KData
+from mrpro.data.KHeader import KHeader
+from mrpro.data.traj_calculators.KTrajectoryCartesian import KTrajectoryCartesian
+from mrpro.utils.interpolate import apply_lowres
+from mrpro.utils.pad_or_crop import pad_or_crop
+from mrpro.utils.reshape import unsqueeze_left
+
+
+class FastMRIKDataDataset(torch.utils.data.Dataset):
+    """FastMRI KData Dataset.
+
+    This dataset returns KData objects for single slices or stacks of slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, path: PathLike | str | Sequence[PathLike | str], single_slice: bool = True):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Either a path to a directory containing the FastMRI data as .h5 files or a sequence of paths of
+            individual files.
+        single_slice : bool
+            Whether to return single slices or stacks of slices.
+        """
+        self._filenames = []
+        slices = []
+        for fn in Path(path).rglob('*.h5') if isinstance(path, str | Path | PathLike) else path:
+            try:
+                with h5py.File(fn, 'r') as file:
+                    n_slices = file['kspace'].shape[0]
+                    slices.append(n_slices)
+                    self._filenames.append(fn)
+            except (KeyError, FileNotFoundError, OSError):
+                warn(f'Invalid file: {fn}. Skipping.', stacklevel=2)
+        self._accum_slices = torch.tensor(slices).cumsum(dim=0) if single_slice else None
+
+    def __len__(self) -> int:
+        """Get length (number of slices or stacks of slices) of the dataset."""
+        if self._accum_slices is None:
+            return len(self._filenames)
+        if len(self._accum_slices) == 0:
+            return 0
+        return int(self._accum_slices[-1])
+
+    def __getitem__(self, idx: int) -> KData:
+        """Get a single slice or stack of slices."""
+        if not -len(self) <= idx < len(self):
+            raise IndexError(f'Index {idx} is out of bounds for the dataset of size {len(self)}')
+        if idx < 0:
+            idx += len(self)
+        if self._accum_slices is None:  # return stack
+            file_idx = idx
+            slice_idx: int | slice = slice(None)
+        else:
+            file_idx = int(torch.searchsorted(self._accum_slices, idx + 1))
+            slice_idx = idx - self._accum_slices[file_idx]
+        with h5py.File(self._filenames[file_idx], 'r') as file:
+            # data is sometimes zero-padded, we remove the padding
+            data = torch.as_tensor(np.array(file['kspace'][slice_idx]))
+            data = unsqueeze_left(data, 4 - data.ndim)
+            nonzero = data[0, 0, 0, :].abs() > 1e-12
+            first, last = nonzero.nonzero().flatten()[[0, -1]]
+            data = data[..., first : last + 1]
+            data = rearrange(data, 'slices coils k0 k1 -> slices coils 1 k1 k0')
+            n_k1, n_k0 = data.shape[-2:]
+            info = AcqInfo()
+            info.idx.k1 = torch.arange(first, last + 1)[None, None, None, :, None]
+            header = KHeader.from_ismrmrd(
+                ismrmrd.xsd.CreateFromDocument(file['ismrmrd_header'][()].decode('utf-8')), info
+            )
+            traj = KTrajectoryCartesian()(
+                n_k0=n_k0,
+                k0_center=n_k0 // 2,
+                k1_idx=info.idx.k1,
+                k1_center=n_k1 // 2,
+                k2_idx=torch.tensor(0),
+                k2_center=0,
+            )
+            kdata = KData(
+                data=data,
+                header=header,
+                traj=traj,
+            )
+            return kdata
+
+
+class FastMRIImageDataset(torch.utils.data.Dataset):
+    """FastMRI Image Dataset.
+
+    This dataset returns image tensors for single slices of the FastMRI brain or knee dataset.
+    It filteres and resamples the files such that the returned images have a consistent shape
+    of 320x320 before augmentations.
+
+    The returned images are complex valued and will have shape ``(1, 1, 1, 320, 320)`` if coil combined or
+    ``(1, n_coils, 1, 320, 320)`` otherwise.
+
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(
+        self,
+        path: str | PathLike | Sequence[str | PathLike],
+        coil_combine: bool = False,
+        augment: Callable[[torch.Tensor, int], torch.Tensor] | None = None,
+        allowed_n_coils: Sequence[int] | None = (16, 15),
+    ):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Either a path to a directory containing the FastMRI data as .h5 files or a sequence of paths of
+            individual files.
+        coil_combine : bool
+            Whether to perform coil combination sensitivity maps obtained using the Inati method.
+            Note that this is **not** comonly used as the target for FastMRI challenges. Instead,
+            as target the RSS combination of the coil images is used.
+        augment
+            Augmentation function. Will be called with the image and the index of the slices.
+            If `coil_combine` is `True`, the function will be called with the complex valued coil combined image
+            with shape (1, 320, 320) otherwise with the complex valued coil images with shape (n_coils, 320, 320).
+            `None` means no augmentation.
+        allowed_n_coils
+            List of allowed number of coils. If `None`, all coils are allowed.
+            The knee training set has 15 coils consistently, while the brain dataset has
+            roughly 1300 files with 16 coils, 1100 files with 20 coils and 800 files with 4 coils.
+            Only used if `coil_combine` is `False`.
+        """
+        slices = []
+        self._filenames = []
+        for fn in Path(path).rglob('*.h5') if isinstance(path, str | Path | PathLike) else path:
+            try:
+                with h5py.File(fn, 'r') as file:
+                    acquisition: str = file.attrs['acquisition']
+                    n_slices, n_coils = file['kspace'].shape[:2]
+                    header = KHeader.from_ismrmrd(
+                        ismrmrd.xsd.CreateFromDocument(file['ismrmrd_header'][()].decode('utf-8')), AcqInfo()
+                    )
+                    if acquisition.startswith('AX'):  # brain
+                        if (
+                            (not coil_combine and allowed_n_coils is not None and n_coils not in allowed_n_coils)
+                            or header.recon_matrix.x not in (320, 384)
+                            or round(header.recon_fov.y, 2) != 0.22
+                        ):
+                            continue
+                    elif acquisition.endswith('FBK'):  # knee
+                        if (
+                            (not coil_combine and allowed_n_coils is not None and n_coils not in allowed_n_coils)
+                            or header.recon_matrix.x != 320
+                            or round(header.recon_fov.y, 2) != 0.14
+                        ):
+                            continue
+                    else:
+                        raise ValueError(f'Unknown acquisition: {acquisition}')
+                    slices.append(n_slices)
+                    self._filenames.append(fn)
+            except (KeyError, FileNotFoundError, OSError):
+                warn(f'Invalid file: {fn}. Skipping.', stacklevel=2)
+        self._accum_slices = torch.tensor(slices).cumsum(dim=0)
+        self._coil_combine = coil_combine
+        self.augment = augment
+
+    def __len__(self) -> int:
+        """Get length (number of slices) of the dataset."""
+        return int(self._accum_slices[-1])
+
+    def __getitem__(self, idx: int) -> torch.Tensor:
+        """Get a single slice."""
+        if not -len(self) <= idx < len(self):
+            raise IndexError(f'Index {idx} is out of bounds for the dataset of size {len(self)}')
+        if idx < 0:
+            idx += len(self)
+        file_idx = torch.searchsorted(self._accum_slices, idx + 1)
+        slice_idx = idx - self._accum_slices[file_idx]
+        with h5py.File(self._filenames[file_idx], 'r') as file:
+            data = torch.as_tensor(np.array(file['kspace'][slice_idx]))
+            header = KHeader.from_ismrmrd(
+                ismrmrd.xsd.CreateFromDocument(file['ismrmrd_header'][()].decode('utf-8')), AcqInfo()
+            )
+            # recon_matrix can be >320, but FOV is always constant. We crop in k-space to get the same resolution.
+            data = pad_or_crop(
+                data,
+                (int(data.shape[-2] * 320 / header.recon_matrix.y), int(data.shape[-1] * 320 / header.recon_matrix.y)),
+                dim=(-2, -1),
+            )
+            # we use an fft instead of ifft to already flip the image
+            img = torch.fft.fftshift(torch.fft.fft2(torch.fft.fftshift(data, dim=(-2, -1))), dim=(-2, -1))
+            # finally, we crop to the new recon_fov of 320x320 to remove oversampling
+            img = pad_or_crop(img, (320, 320), dim=(-2, -1))
+            if self._coil_combine:
+                csm = apply_lowres(
+                    lambda x: inati(x.unsqueeze(1), smoothing_width=5).squeeze(1), (32, 32), dim=(-2, -1)
+                )(img)
+                csm /= (csm * csm.conj()).sum(0, keepdim=True).sqrt()
+                img = (img * csm.conj()).sum(dim=0, keepdim=True)
+            if self.augment is not None:
+                img = self.augment(img, idx)
+            return rearrange(img, 'coils y x -> 1 coils 1 y x')  # , rearrange(csm, 'coils y x -> 1 coils 1 y x')
diff --git a/tests/phantoms/test_fastmri.py b/tests/phantoms/test_fastmri.py
new file mode 100644
index 000000000..5480d3dd3
--- /dev/null
+++ b/tests/phantoms/test_fastmri.py
@@ -0,0 +1,207 @@
+"""Test FastMRI dataset"""
+
+import h5py
+import pytest
+import torch
+from mrpro.data import KData
+from mrpro.phantoms import FastMRIImageDataset, FastMRIKDataDataset
+from mrpro.utils import RandomGenerator
+
+N_COILS_BRAIN = 16
+N_COILS_KNEE = 15
+N_K0 = 640
+N_K1_BRAIN = 322
+N_K1_KNEE = 368
+N_SLICES_BRAIN = 2
+N_SLICES_KNEE = 3
+
+
+@pytest.fixture(scope='session')
+def mock_fastmri_brain_data(tmp_path_factory):
+    """Create temporary HDF5 files mimicking FastMRI brain data."""
+    test_dir = tmp_path_factory.mktemp('fastmri_brain_test_data')
+    rng = RandomGenerator(0)
+    header = r"""<?xml version="1.0" encoding="utf-8"?>
+    <ismrmrdHeader xmlns="http://www.ismrm.org/ISMRMRD" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ismrm.org/ISMRMRD ismrmrd.xsd">
+        <experimentalConditions>
+        <H1resonanceFrequency_Hz>63646310</H1resonanceFrequency_Hz>
+    </experimentalConditions>
+    <encoding>
+        <encodedSpace>
+            <matrixSize>
+                <x>640</x>
+                <y>322</y>
+                <z>1</z>
+            </matrixSize>
+            <fieldOfView_mm>
+                <x>440</x>
+                <y>221.98</y>
+                <z>7.5</z>
+            </fieldOfView_mm>
+        </encodedSpace>
+        <reconSpace>
+            <matrixSize>
+                <x>320</x>
+                <y>320</y>
+                <z>1</z>
+            </matrixSize>
+            <fieldOfView_mm>
+                <x>220</x>
+                <y>220</y>
+                <z>5</z>
+            </fieldOfView_mm>
+        </reconSpace>
+    </encoding>
+    </ismrmrdHeader>
+"""
+    with h5py.File(test_dir / 'brain_file.h5', 'w') as f:
+        kspace_brain = rng.complex64_tensor((N_SLICES_BRAIN, N_COILS_BRAIN, N_K0, N_K1_BRAIN)).numpy()
+        f.create_dataset('kspace', data=kspace_brain)
+        f.attrs['acquisition'] = 'AXT2_FLAIR'
+        f.create_dataset('ismrmrd_header', data=header.encode('utf-8'))
+
+    return test_dir
+
+
+@pytest.fixture(scope='session')
+def mock_fastmri_knee_data(tmp_path_factory):
+    """Create temporary HDF5 files mimicking FastMRI knee data."""
+    test_dir = tmp_path_factory.mktemp('fastmri_knee_test_data')
+    rng = RandomGenerator(1)
+    header = r"""<?xml version="1.0" encoding="utf-8"?>
+    <ismrmrdHeader xmlns="http://www.ismrm.org/ISMRMRD" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ismrm.org/ISMRMRD ismrmrd.xsd">
+        <experimentalConditions>
+        <H1resonanceFrequency_Hz>63646310</H1resonanceFrequency_Hz>
+    </experimentalConditions>
+    <encoding>
+        <encodedSpace>
+            <matrixSize>
+                <x>640</x>
+                <y>368</y>
+                <z>1</z>
+            </matrixSize>
+            <fieldOfView_mm>
+                <x>280</x>
+                <y>161</y>
+                <z>4.5</z>
+            </fieldOfView_mm>
+        </encodedSpace>
+        <reconSpace>
+            <matrixSize>
+                <x>320</x>
+                <y>320</y>
+                <z>1</z>
+            </matrixSize>
+            <fieldOfView_mm>
+                <x>140</x>
+                <y>140</y>
+                <z>3</z>
+            </fieldOfView_mm>
+        </reconSpace>
+    </encoding>
+    </ismrmrdHeader>
+    """
+    with h5py.File(test_dir / 'knee_file.h5', 'w') as f:
+        kspace_knee = rng.complex64_tensor((N_SLICES_KNEE, N_COILS_KNEE, N_K0, N_K1_KNEE)).numpy()
+        f.create_dataset('kspace', data=kspace_knee)
+        f.attrs['acquisition'] = 'CORPDFS_FBK'
+        f.create_dataset('ismrmrd_header', data=header.encode('utf-8'))
+
+    return test_dir
+
+
+@pytest.mark.parametrize(
+    ('data_fixture', 'n_slices', 'n_coils', 'n_k1'),
+    [
+        ('mock_fastmri_brain_data', N_SLICES_BRAIN, N_COILS_BRAIN, N_K1_BRAIN),
+        ('mock_fastmri_knee_data', N_SLICES_KNEE, N_COILS_KNEE, N_K1_KNEE),
+    ],
+)
+def test_fastmri_kdata_dataset_single_slice(request, data_fixture, n_slices, n_coils, n_k1):
+    """Test KDataDataset for both brain and knee data."""
+    data_path = request.getfixturevalue(data_fixture)
+    dataset = FastMRIKDataDataset(path=data_path, single_slice=True)
+    assert len(dataset) == n_slices
+
+    kdata = dataset[n_slices // 2]
+    assert isinstance(kdata, KData)
+    assert kdata.shape == (1, n_coils, 1, n_k1, N_K0)
+
+    kdata_last = dataset[-1]
+    assert kdata_last.data.shape == (1, n_coils, 1, n_k1, N_K0)
+
+
+@pytest.mark.parametrize(
+    ('data_fixture', 'n_slices', 'n_coils', 'n_k1'),
+    [
+        ('mock_fastmri_brain_data', N_SLICES_BRAIN, N_COILS_BRAIN, N_K1_BRAIN),
+        ('mock_fastmri_knee_data', N_SLICES_KNEE, N_COILS_KNEE, N_K1_KNEE),
+    ],
+)
+def test_fastmri_kdata_dataset_stack_of_slices(request, data_fixture, n_slices, n_coils, n_k1):
+    """Test KDataDataset for both brain and knee data."""
+    data_path = request.getfixturevalue(data_fixture)
+    dataset = FastMRIKDataDataset(path=data_path, single_slice=False)
+    assert len(dataset) == 1
+
+    kdata = dataset[0]
+    assert isinstance(kdata, KData)
+    assert kdata.shape == (n_slices, n_coils, 1, n_k1, N_K0)
+
+
+@pytest.mark.parametrize(
+    ('data_fixture', 'n_slices', 'n_coils'),
+    [
+        ('mock_fastmri_brain_data', N_SLICES_BRAIN, N_COILS_BRAIN),
+        ('mock_fastmri_knee_data', N_SLICES_KNEE, N_COILS_KNEE),
+    ],
+)
+@pytest.mark.parametrize('coil_combine', [False, True])
+def test_fastmri_image_dataset(request, data_fixture, n_slices: int, n_coils: int, coil_combine: bool):
+    """Test ImageDataset for both brain and knee data, with and without coil combination."""
+    data_path = request.getfixturevalue(data_fixture)
+    dataset = FastMRIImageDataset(path=data_path, coil_combine=coil_combine)
+    expected_coils = 1 if coil_combine else n_coils
+    assert len(dataset) == n_slices
+
+    img = dataset[n_slices // 2]
+    assert img.shape == (1, expected_coils, 1, 320, 320)
+    assert img.dtype == torch.complex64
+    assert not torch.isnan(img).any()
+
+
+@pytest.mark.parametrize(
+    ('data_fixture', 'n_coils'),
+    [
+        ('mock_fastmri_brain_data', N_COILS_BRAIN),
+        ('mock_fastmri_knee_data', N_COILS_KNEE),
+    ],
+)
+def test_fastmri_image_dataset_augment(request, data_fixture, n_coils: int):
+    """Test ImageDataset augmentation for both brain and knee data."""
+
+    def mock_augment(x, idx):
+        return x * 2.0  # Simple multiplication augmentation
+
+    data_path = request.getfixturevalue(data_fixture)
+    dataset = FastMRIImageDataset(
+        path=data_path,
+        coil_combine=False,  # Test augmentation with multi-coil data
+        augment=mock_augment,
+    )
+
+    img = dataset[0]
+    assert img.shape == (1, n_coils, 1, 320, 320)
+    img_no_aug = FastMRIImageDataset(path=data_path, coil_combine=False)[0]
+    assert torch.allclose(img, img_no_aug * 2.0)
+
+
+def test_fastmri_dataset_getitem_out_of_bounds(mock_fastmri_brain_data):
+    """Test that accessing invalid indices raises IndexError."""
+    dataset = FastMRIImageDataset(path=mock_fastmri_brain_data)
+    with pytest.raises(IndexError):
+        _ = dataset[100]
+    with pytest.raises(IndexError):
+        _ = dataset[-100]


Reviews:
user: login: cubic-dev-ai[bot]
body: mrge found 7 issues across 3 files. View them in [mrge.io](https://mrge.io/pr/PTB-MR/mrpro/pull/795)
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-02T23:33:18Z
user: login: lrlunin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T14:36:33Z
user: login: lrlunin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T14:27:08Z
user: login: lrlunin
body: LGTM! 🚀🚀🚀
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T14:46:17Z

Review comments:
diff_hunk: @@ -0,0 +1,86 @@
+"""FastMRI dataset."""
path: src/mrpro/phantoms/fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":8,"steps":[{"text":"I'll review the changed lines in `src/mrpro/phantoms/fastmri.py` against the rule about comments. The rule requires that comments should explain why steps are done rather than merely describing what is being done or obvious behavior.\n\nLet me analyze the file systematically:\n\n1. First, I'll examine the file to understand its structure and identify any comments\n2. Then I'll evaluate each comment against the rule\n3. Finally, I'll report any violations","toolCalls":[{"args":{"pattern":"src/mrpro/phantoms/fastmri.py"},"toolName":"listFiles"}]}]} -->
Rule violated: **comments**
      
      Module docstring is too brief and only describes what the file is about without explaining its purpose or why it exists
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,86 @@
+"""FastMRI dataset."""
+
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+import mrpro
+from mrpro.data.KData import KData
+from mrpro.utils.typing import PathLike
+
+
+class FastMRIDataset(torch.utils.data.Dataset):
+    """FastMRI T(Training) Dataset.
+
+    This dataset returns KData objects for single slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, data_path: PathLike):
+        """Initialize the dataset.
path: src/mrpro/phantoms/fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":9,"steps":[{"text":"I'll review the changed lines in `src/mrpro/phantoms/fastmri.py` against the rule about comments. The rule requires that comments should explain why steps are done rather than merely describing what is being done or obvious behavior.\n\nLet me analyze the file systematically:\n\n1. First, I'll examine the file to understand its structure and identify any comments\n2. Then I'll evaluate each comment against the rule\n3. Finally, I'll report any violations","toolCalls":[{"args":{"pattern":"src/mrpro/phantoms/fastmri.py"},"toolName":"listFiles"}]}]} -->
Rule violated: **comments**
      
      Method docstring only describes what the method does without explaining why certain steps are taken
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,86 @@
+"""FastMRI dataset."""
+
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+import mrpro
+from mrpro.data.KData import KData
+from mrpro.utils.typing import PathLike
+
+
+class FastMRIDataset(torch.utils.data.Dataset):
+    """FastMRI T(Training) Dataset.
+
+    This dataset returns KData objects for single slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, data_path: PathLike):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        data_path : PathLike
+            Path to the data directory.
+        """
+        self.file_list = list(Path(data_path).rglob('*.h5'))
+        slices = []
+        self.shapes = []
+        for fn in self.file_list:
+            with h5py.File(fn, 'r') as file:
+                acquisition: str = file.attrs['acquisition']
+                if acquisition.startswith('AX'):  # brain
+                    slices.append(file['kspace'].shape[1])
+                elif acquisition.endswith('FBK'):  # knee
+                    slices.append(file['kspace'].shape[0])
+                else:
+                    raise ValueError(f'Unknown acquisition: {acquisition}')
+                self.shapes.append(file['kspace'].shape)
+        self._accum_slices = torch.tensor(slices).cumsum(dim=0)
+
+    def __len__(self) -> int:
+        """Get length (number of slices) of the dataset."""
path: src/mrpro/phantoms/fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":8,"steps":[{"text":"I'll review the changed lines in `src/mrpro/phantoms/fastmri.py` against the rule about comments. The rule requires that comments should explain why steps are done rather than merely describing what is being done or obvious behavior.\n\nLet me analyze the file systematically:\n\n1. First, I'll examine the file to understand its structure and identify any comments\n2. Then I'll evaluate each comment against the rule\n3. Finally, I'll report any violations","toolCalls":[{"args":{"pattern":"src/mrpro/phantoms/fastmri.py"},"toolName":"listFiles"}]}]} -->
Rule violated: **comments**
      
      Method docstring merely describes the obvious behavior without explaining implementation details
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,86 @@
+"""FastMRI dataset."""
+
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+import mrpro
+from mrpro.data.KData import KData
+from mrpro.utils.typing import PathLike
+
+
+class FastMRIDataset(torch.utils.data.Dataset):
+    """FastMRI T(Training) Dataset.
+
+    This dataset returns KData objects for single slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, data_path: PathLike):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        data_path : PathLike
+            Path to the data directory.
+        """
+        self.file_list = list(Path(data_path).rglob('*.h5'))
+        slices = []
+        self.shapes = []
+        for fn in self.file_list:
+            with h5py.File(fn, 'r') as file:
+                acquisition: str = file.attrs['acquisition']
+                if acquisition.startswith('AX'):  # brain
+                    slices.append(file['kspace'].shape[1])
+                elif acquisition.endswith('FBK'):  # knee
+                    slices.append(file['kspace'].shape[0])
+                else:
+                    raise ValueError(f'Unknown acquisition: {acquisition}')
+                self.shapes.append(file['kspace'].shape)
+        self._accum_slices = torch.tensor(slices).cumsum(dim=0)
+
+    def __len__(self) -> int:
+        """Get length (number of slices) of the dataset."""
+        return self._accum_slices[-1].item()
+
+    def __getitem__(self, idx: int) -> KData:
+        """Get a single slice."""
path: src/mrpro/phantoms/fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":9,"steps":[{"text":"I'll review the changed lines in `src/mrpro/phantoms/fastmri.py` against the rule about comments. The rule requires that comments should explain why steps are done rather than merely describing what is being done or obvious behavior.\n\nLet me analyze the file systematically:\n\n1. First, I'll examine the file to understand its structure and identify any comments\n2. Then I'll evaluate each comment against the rule\n3. Finally, I'll report any violations","toolCalls":[{"args":{"pattern":"src/mrpro/phantoms/fastmri.py"},"toolName":"listFiles"}]}]} -->
Rule violated: **comments**
      
      Method docstring is too simplistic and doesn't explain the complex indexing logic or data transformation
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,86 @@
+"""FastMRI dataset."""
+
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+import mrpro
+from mrpro.data.KData import KData
+from mrpro.utils.typing import PathLike
+
+
+class FastMRIDataset(torch.utils.data.Dataset):
+    """FastMRI T(Training) Dataset.
+
+    This dataset returns KData objects for single slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, data_path: PathLike):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        data_path : PathLike
path: src/mrpro/phantoms/fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":9,"steps":[{"text":"I'll review the changed code for violations of the docstring rule. The rule requires using numpy docstring style with some modifications, specifically not repeating the type and \"optional\" or default values in the docstring as they should be in the type annotation.\n\nLet me analyze the file systematically:","toolCalls":[{"args":{"pattern":"src/mrpro/phantoms/fastmri.py"},"toolName":"listFiles"}]}]} -->
Rule violated: **docstring**
      
      Docstring repeats type information that is already in the type annotation
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,187 @@
+"""Test FastMRI dataset"""
+
+import h5py
+import pytest
+from mrpro.data import KData
+from mrpro.phantoms.fastmri import FastMRIDataset
+from mrpro.utils import RandomGenerator
+
+MINIMAL_HEADER_XML = r"""<?xml version="1.0" encoding="utf-8"?>
+<ismrmrdHeader xmlns="http://www.ismrm.org/ISMRMRD" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ismrm.org/ISMRMRD ismrmrd.xsd">
+   <studyInformation>
+      <studyTime>15:05:07</studyTime>
+   </studyInformation>
+   <measurementInformation>
+      <measurementID>25077_449075862_449075873_819</measurementID>
+      <patientPosition>HFS</patientPosition>
+      <protocolName>AX</protocolName>
+      <frameOfReferenceUID>1.3.12.2.1107.5.2.30.25077.1.20180401144405156.0.0.4998</frameOfReferenceUID>
+   </measurementInformation>
+   <acquisitionSystemInformation>
+      <systemVendor>SIEMENS</systemVendor>
+      <systemModel>Avanto</systemModel>
+      <systemFieldStrength_T>1.494</systemFieldStrength_T>
+      <relativeReceiverNoiseBandwidth>0.793</relativeReceiverNoiseBandwidth>
+      <receiverChannels>4</receiverChannels>
+      <institutionName>NYU</institutionName>
+   </acquisitionSystemInformation>
+   <experimentalConditions>
+      <H1resonanceFrequency_Hz>63646310</H1resonanceFrequency_Hz>
+   </experimentalConditions>
+   <encoding>
+      <encodedSpace>
+         <matrixSize>
+            <x>640</x>
+            <y>322</y>
+            <z>1</z>
+         </matrixSize>
+         <fieldOfView_mm>
+            <x>440</x>
+            <y>221.98</y>
+            <z>7.5</z>
+         </fieldOfView_mm>
+      </encodedSpace>
+      <reconSpace>
+         <matrixSize>
+            <x>320</x>
+            <y>320</y>
+            <z>1</z>
+         </matrixSize>
+         <fieldOfView_mm>
+            <x>220</x>
+            <y>220</y>
+            <z>5</z>
+         </fieldOfView_mm>
+      </reconSpace>
+      <trajectory>cartesian</trajectory>
+      <encodingLimits>
+         <kspace_encoding_step_1>
+            <minimum>0</minimum>
+            <maximum>225</maximum>
+            <center>113</center>
+         </kspace_encoding_step_1>
+         <kspace_encoding_step_2>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </kspace_encoding_step_2>
+         <average>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </average>
+         <slice>
+            <minimum>0</minimum>
+            <maximum>33</maximum>
+            <center>0</center>
+         </slice>
+         <contrast>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </contrast>
+         <phase>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </phase>
+         <repetition>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </repetition>
+         <set>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </set>
+         <segment>
+            <minimum>0</minimum>
+            <maximum>0</maximum>
+            <center>0</center>
+         </segment>
+      </encodingLimits>
+      <parallelImaging>
+         <accelerationFactor>
+            <kspace_encoding_step_1>1</kspace_encoding_step_1>
+            <kspace_encoding_step_2>1</kspace_encoding_step_2>
+         </accelerationFactor>
+         <calibrationMode>other</calibrationMode>
+         <interleavingDimension>other</interleavingDimension>
+      </parallelImaging>
+   </encoding>
+   <sequenceParameters>
+      <TR>500</TR>
+      <TE>9.3</TE>
+      <TI>100</TI>
+      <flipAngle_deg>140</flipAngle_deg>
+      <sequence_type>TurboSpinEcho</sequence_type>
+      <echo_spacing>9.3</echo_spacing>
+   </sequenceParameters>
+</ismrmrdHeader>
+"""
+
+N_COILS = 2
+N_K0 = 640
+N_K1 = 322
+N_SLICES_BRAIN = 2
+N_SLICES_KNEE = 3
+
+
+@pytest.fixture(scope='session')
+def mock_fastmri_data(tmp_path_factory):
path: tests/phantoms/test_fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":9,"steps":[{"text":"I'll review the changed lines for violations of the numpy docstring style rule. Let me analyze the code carefully.","toolCalls":[{"args":{"pattern":"mrpro/phantoms/fastmri.py"},"toolName":"listFiles"}]},{"text":"Let me check if the FastMRIDataset class is defined elsewhere in the project.","toolCalls":[{"args":{"command":"grep -r \"class FastMRIDataset\" --include=\"*.py\" ."},"toolName":"executeCommand"}]},{"text":"Now I'll examine the FastMRIDataset class to understand its implementation and check for docstring violations.","toolCalls":[{"args":{"command":"cat ./src/mrpro/phantoms/fastmri.py"},"toolName":"executeCommand"}]},{"text":"Now let's look at the test file to understand the context better:","toolCalls":[{"args":{"command":"cat tests/phantoms/test_fastmri.py"},"toolName":"executeCommand"}]},{"text":"Now I'll check the docstring style used in other fixtures in the project to understand the expected format:","toolCalls":[{"args":{"command":"grep -r \"@pytest.fixture\" --include=\"*.py\" . | head -n 5"},"toolName":"executeCommand"}]},{"text":"Let me check one of these fixtures to see the docstring style:","toolCalls":[{"args":{"command":"grep -A 10 \"@pytest.fixture(scope='session')\" ./tests/data/conftest.py"},"toolName":"executeCommand"}]},{"text":"Let me also check some function docstrings in the project:","toolCalls":[{"args":{"command":"grep -A 10 \"def \" ./src/mrpro/phantoms/fastmri.py"},"toolName":"executeCommand"}]}]} -->
Rule violated: **docstring**
      
      Missing proper numpy-style docstring with Parameters section for fixture
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,86 @@
+"""FastMRI dataset."""
+
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+import mrpro
+from mrpro.data.KData import KData
+from mrpro.utils.typing import PathLike
+
+
+class FastMRIDataset(torch.utils.data.Dataset):
+    """FastMRI T(Training) Dataset.
+
+    This dataset returns KData objects for single slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, data_path: PathLike):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        data_path : PathLike
+            Path to the data directory.
+        """
+        self.file_list = list(Path(data_path).rglob('*.h5'))
+        slices = []
+        self.shapes = []
+        for fn in self.file_list:
+            with h5py.File(fn, 'r') as file:
+                acquisition: str = file.attrs['acquisition']
+                if acquisition.startswith('AX'):  # brain
+                    slices.append(file['kspace'].shape[1])
+                elif acquisition.endswith('FBK'):  # knee
+                    slices.append(file['kspace'].shape[0])
+                else:
+                    raise ValueError(f'Unknown acquisition: {acquisition}')
+                self.shapes.append(file['kspace'].shape)
+        self._accum_slices = torch.tensor(slices).cumsum(dim=0)
+
+    def __len__(self) -> int:
+        """Get length (number of slices) of the dataset."""
+        return self._accum_slices[-1].item()
+
+    def __getitem__(self, idx: int) -> KData:
+        """Get a single slice."""
+        if not -len(self) <= idx < len(self):
+            raise IndexError(f'Index {idx} is out of bounds for the dataset of size {len(self)}')
+        if idx < 0:
+            idx += len(self)
+        file_idx = torch.searchsorted(self._accum_slices, idx + 1)
+        slice_idx = idx - self._accum_slices[file_idx]
+        with h5py.File(self.file_list[file_idx], 'r') as file:
+            acquisition: str = file.attrs['acquisition']
+            if acquisition.startswith('AX'):  # brain
+                data = torch.as_tensor(np.array(file['kspace'][:, slice_idx]))
path: src/mrpro/phantoms/fastmri.py
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":8,"steps":[{"text":"I'll review the changed lines in `src/mrpro/phantoms/fastmri.py` against the variable naming rule. Let me analyze the code carefully to identify any significant violations.\n\nFirst, let me understand what the code is doing and check for variable naming issues:","toolCalls":[{"args":{"command":"grep -r \"KData\" --include=\"*.py\" src/mrpro/data/"},"toolName":"executeCommand"}]},{"text":"Let me check the KTrajectoryCartesian class to understand the trajectory calculation:","toolCalls":[{"args":{"command":"grep -r \"KTrajectoryCartesian\" --include=\"*.py\" src/mrpro/"},"toolName":"executeCommand"}]},{"text":"Let me look at the KTrajectoryCartesian implementation to understand the parameters:","toolCalls":[{"args":{"command":"head -n 30 src/mrpro/data/traj_calculators/KTrajectoryCartesian.py"},"toolName":"executeCommand"}]}]} -->
Rule violated: **variabile names**
      
      Variable 'data' is too generic and doesn't clearly indicate it contains k-space data
created_at: 2025-05-02T23:33:18Z
author_association: NONE
diff_hunk: @@ -0,0 +1,208 @@
+"""FastMRI dataset."""
+
+from collections.abc import Callable, Sequence
+from os import PathLike
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+from mrpro.algorithms.csm.inati import inati
+from mrpro.data.AcqInfo import AcqInfo
+from mrpro.data.KData import KData
+from mrpro.data.KHeader import KHeader
+from mrpro.data.traj_calculators.KTrajectoryCartesian import KTrajectoryCartesian
+from mrpro.utils.interpolate import apply_lowres
+from mrpro.utils.pad_or_crop import pad_or_crop
+from mrpro.utils.reshape import unsqueeze_left
+
+
+class FastMRIKDataDataset(torch.utils.data.Dataset):
+    """FastMRI KData Dataset.
+
+    This dataset returns KData objects for single slices or stacks of slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, path: PathLike | str, single_slice: bool = True):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Path to the data directory.
+        single_slice : bool
+            Whether to return single slices or stacks of slices.
+        """
+        self._filenames = list(Path(path).rglob('*.h5'))
path: src/mrpro/phantoms/fastmri.py
user: login: lrlunin
body: Would it make more sense to set the glob mask for the data as default parameter to allow a user to load only T1/T2 weighted acquisitions?
created_at: 2025-05-06T14:26:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,208 @@
+"""FastMRI dataset."""
+
+from collections.abc import Callable, Sequence
+from os import PathLike
+from pathlib import Path
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+from mrpro.algorithms.csm.inati import inati
+from mrpro.data.AcqInfo import AcqInfo
+from mrpro.data.KData import KData
+from mrpro.data.KHeader import KHeader
+from mrpro.data.traj_calculators.KTrajectoryCartesian import KTrajectoryCartesian
+from mrpro.utils.interpolate import apply_lowres
+from mrpro.utils.pad_or_crop import pad_or_crop
+from mrpro.utils.reshape import unsqueeze_left
+
+
+class FastMRIKDataDataset(torch.utils.data.Dataset):
+    """FastMRI KData Dataset.
+
+    This dataset returns KData objects for single slices or stacks of slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, path: PathLike | str, single_slice: bool = True):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Path to the data directory.
+        single_slice : bool
+            Whether to return single slices or stacks of slices.
+        """
+        self._filenames = list(Path(path).rglob('*.h5'))
+        if single_slice:
+            slices = []
+            for fn in self._filenames:
+                with h5py.File(fn, 'r') as file:
+                    n_slices = file['kspace'].shape[0]
+                    slices.append(n_slices)
+            self._accum_slices: torch.Tensor | None = torch.tensor(slices).cumsum(dim=0)
+        else:
+            self._accum_slices = None
+
+    def __len__(self) -> int:
+        """Get length (number of slices or stacks of slices) of the dataset."""
+        if self._accum_slices is None:
+            return len(self._filenames)
+        if len(self._accum_slices) == 0:
+            return 0
+        return int(self._accum_slices[-1])
+
+    def __getitem__(self, idx: int) -> KData:
+        """Get a single slice or stack of slices."""
+        if not -len(self) <= idx < len(self):
+            raise IndexError(f'Index {idx} is out of bounds for the dataset of size {len(self)}')
+        if idx < 0:
+            idx += len(self)
+        if self._accum_slices is None:  # return stack
+            file_idx = idx
+            slice_idx: int | slice = slice(None)
+        else:
+            file_idx = int(torch.searchsorted(self._accum_slices, idx + 1))
+            slice_idx = idx - self._accum_slices[file_idx]
+        with h5py.File(self._filenames[file_idx], 'r') as file:
+            # data is sometimes zero-padded, we remove the padding
+            data = torch.as_tensor(np.array(file['kspace'][slice_idx]))
+            data = unsqueeze_left(data, 4 - data.ndim)
+            nonzero = data[0, 0, 0, :].abs() > 1e-12
+            first, last = nonzero.nonzero().flatten()[[0, -1]]
+            data = data[..., first : last + 1]
+            data = rearrange(data, 'slices coils k0 k1 -> slices coils 1 k1 k0')
+            n_k1, n_k0 = data.shape[-2:]
+            info = AcqInfo()
+            info.idx.k1 = torch.arange(first, last + 1)[None, None, None, :, None]
+            header = KHeader.from_ismrmrd(
+                ismrmrd.xsd.CreateFromDocument(file['ismrmrd_header'][()].decode('utf-8')), info
+            )
+            traj = KTrajectoryCartesian()(
+                n_k0=n_k0,
+                k0_center=n_k0 // 2,
+                k1_idx=info.idx.k1,
+                k1_center=n_k1 // 2,
+                k2_idx=torch.tensor(0),
+                k2_center=0,
+            )
+            kdata = KData(
+                data=data,
+                header=header,
+                traj=traj,
+            )
+            return kdata
+
+
+class FastMRIImageDataset(torch.utils.data.Dataset):
+    """FastMRI Image Dataset.
+
+    This dataset returns image tensors for single slices of the FastMRI brain or knee dataset.
+    It filteres and resamples the files such that the returned images have a consistent shape
+    of 320x320 before augmentations.
+
+    The returned images are complex valued and will have shape ``(1, 1, 1, 320, 320)`` if coil combined or
+    ``(1, n_coils, 1, 320, 320)`` otherwise.
+
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(
+        self,
+        path: str | PathLike,
+        coil_combine: bool = False,
+        augment: Callable[[torch.Tensor, int], torch.Tensor] | None = None,
+        allowed_n_coils: Sequence[int] | None = (16, 15),
+    ):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Path to the data directory.
+        coil_combine : bool
+            Whether to perform coil combination sensitivity maps obtained using the Inati method.
+            Note that this is **not** comonly used as the target for FastMRI challenges. Instead,
+            as target the RSS combination of the coil images is used.
+        augment
+            Augmentation function. Will be called with the image and the index of the slices.
+            If `coil_combine` is `True`, the function will be called with the complex valued coil combined image
+            with shape (1, 320, 320) otherwise with the complex valued coil images with shape (n_coils, 320, 320).
+            `None` means no augmentation.
+        allowed_n_coils
+            List of allowed number of coils. If `None`, all coils are allowed.
+            The knee training set has 15 coils consistently, while the brain dataset has
+            roughly 1300 files with 16 coils, 1100 files with 20 coils and 800 files with 4 coils.
+            Only used if `coil_combine` is `False`.
+        """
+        slices = []
+        self._filenames = []
+        for fn in Path(path).rglob('*.h5'):
path: src/mrpro/phantoms/fastmri.py
user: login: lrlunin
body: Same idea for the glob mask as parameter
created_at: 2025-05-06T14:29:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,215 @@
+"""FastMRI dataset."""
+
+from collections.abc import Callable, Sequence
+from os import PathLike
+from pathlib import Path
+from warnings import warn
+
+import h5py
+import ismrmrd.xsd
+import numpy as np
+import torch
+from einops import rearrange
+
+from mrpro.algorithms.csm.inati import inati
+from mrpro.data.AcqInfo import AcqInfo
+from mrpro.data.KData import KData
+from mrpro.data.KHeader import KHeader
+from mrpro.data.traj_calculators.KTrajectoryCartesian import KTrajectoryCartesian
+from mrpro.utils.interpolate import apply_lowres
+from mrpro.utils.pad_or_crop import pad_or_crop
+from mrpro.utils.reshape import unsqueeze_left
+
+
+class FastMRIKDataDataset(torch.utils.data.Dataset):
+    """FastMRI KData Dataset.
+
+    This dataset returns KData objects for single slices or stacks of slices of the FastMRI brain or knee dataset.
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(self, path: PathLike | str | Sequence[PathLike | str], single_slice: bool = True):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Either a path to a directory containing the FastMRI data as .h5 files or a sequence of paths of
+            individual files.
+        single_slice : bool
+            Whether to return single slices or stacks of slices.
+        """
+        self._filenames = []
+        slices = []
+        for fn in Path(path).rglob('*.h5') if isinstance(path, str | Path | PathLike) else path:
+            try:
+                with h5py.File(fn, 'r') as file:
+                    n_slices = file['kspace'].shape[0]
+                    slices.append(n_slices)
+                    self._filenames.append(fn)
+            except (KeyError, FileNotFoundError, OSError):
+                warn(f'Invalid file: {fn}. Skipping.', stacklevel=2)
+        self._accum_slices = torch.tensor(slices).cumsum(dim=0) if single_slice else None
+
+    def __len__(self) -> int:
+        """Get length (number of slices or stacks of slices) of the dataset."""
+        if self._accum_slices is None:
+            return len(self._filenames)
+        if len(self._accum_slices) == 0:
+            return 0
+        return int(self._accum_slices[-1])
+
+    def __getitem__(self, idx: int) -> KData:
+        """Get a single slice or stack of slices."""
+        if not -len(self) <= idx < len(self):
+            raise IndexError(f'Index {idx} is out of bounds for the dataset of size {len(self)}')
+        if idx < 0:
+            idx += len(self)
+        if self._accum_slices is None:  # return stack
+            file_idx = idx
+            slice_idx: int | slice = slice(None)
+        else:
+            file_idx = int(torch.searchsorted(self._accum_slices, idx + 1))
+            slice_idx = idx - self._accum_slices[file_idx]
+        with h5py.File(self._filenames[file_idx], 'r') as file:
+            # data is sometimes zero-padded, we remove the padding
+            data = torch.as_tensor(np.array(file['kspace'][slice_idx]))
+            data = unsqueeze_left(data, 4 - data.ndim)
+            nonzero = data[0, 0, 0, :].abs() > 1e-12
+            first, last = nonzero.nonzero().flatten()[[0, -1]]
+            data = data[..., first : last + 1]
+            data = rearrange(data, 'slices coils k0 k1 -> slices coils 1 k1 k0')
+            n_k1, n_k0 = data.shape[-2:]
+            info = AcqInfo()
+            info.idx.k1 = torch.arange(first, last + 1)[None, None, None, :, None]
+            header = KHeader.from_ismrmrd(
+                ismrmrd.xsd.CreateFromDocument(file['ismrmrd_header'][()].decode('utf-8')), info
+            )
+            traj = KTrajectoryCartesian()(
+                n_k0=n_k0,
+                k0_center=n_k0 // 2,
+                k1_idx=info.idx.k1,
+                k1_center=n_k1 // 2,
+                k2_idx=torch.tensor(0),
+                k2_center=0,
+            )
+            kdata = KData(
+                data=data,
+                header=header,
+                traj=traj,
+            )
+            return kdata
+
+
+class FastMRIImageDataset(torch.utils.data.Dataset):
+    """FastMRI Image Dataset.
+
+    This dataset returns image tensors for single slices of the FastMRI brain or knee dataset.
+    It filteres and resamples the files such that the returned images have a consistent shape
+    of 320x320 before augmentations.
+
+    The returned images are complex valued and will have shape ``(1, 1, 1, 320, 320)`` if coil combined or
+    ``(1, n_coils, 1, 320, 320)`` otherwise.
+
+    The data has to be downloaded beforehand. See https://fastmri.med.nyu.edu/ for more information.
+    """
+
+    def __init__(
+        self,
+        path: str | PathLike | Sequence[str | PathLike],
+        coil_combine: bool = False,
+        augment: Callable[[torch.Tensor, int], torch.Tensor] | None = None,
+        allowed_n_coils: Sequence[int] | None = (16, 15),
+    ):
+        """Initialize the dataset.
+
+        Parameters
+        ----------
+        path : PathLike
+            Either a path to a directory containing the FastMRI data as .h5 filesor a Sequence of paths of
path: src/mrpro/phantoms/fastmri.py
user: login: lrlunin
body: ```suggestion
            Either a path to a directory containing the FastMRI data as .h5 files or a sequence of paths of
```
fixed typo
created_at: 2025-05-07T14:27:07Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-02T23:32:07Z
body: <!-- Pytest Coverage Comment: coverage_report_pr -->
<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/README.md"><img alt="Coverage" src="https://img.shields.io/badge/Coverage-92%25-brightgreen.svg" /></a><details><summary>Coverage Report </summary><table><tr><th>File</th><th>Stmts</th><th>Miss</th><th>Cover</th><th>Missing</th></tr><tbody><tr><td colspan="5"><b>src/mrpro</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/_version.py">_version.py</a></td><td>6</td><td>2</td><td>67%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/_version.py#L7-L8">7&ndash;8</a></td></tr><tr><td colspan="5"><b>src/mrpro/algorithms/csm</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/csm/inati.py">inati.py</a></td><td>24</td><td>1</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/csm/inati.py#L42">42</a></td></tr><tr><td colspan="5"><b>src/mrpro/algorithms/dcf</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/dcf/dcf_voronoi.py">dcf_voronoi.py</a></td><td>55</td><td>4</td><td>93%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/dcf/dcf_voronoi.py#L15">15</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/dcf/dcf_voronoi.py#L55-L56">55&ndash;56</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/dcf/dcf_voronoi.py#L89">89</a></td></tr><tr><td colspan="5"><b>src/mrpro/algorithms/optimizers</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/adam.py">adam.py</a></td><td>30</td><td>6</td><td>80%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/adam.py#L108">108</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/adam.py#L125-L129">125&ndash;129</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/cg.py">cg.py</a></td><td>56</td><td>1</td><td>98%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/cg.py#L139">139</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/pdhg.py">pdhg.py</a></td><td>81</td><td>3</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/pdhg.py#L178-L179">178&ndash;179</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/pdhg.py#L185">185</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/pgd.py">pgd.py</a></td><td>53</td><td>4</td><td>92%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/pgd.py#L107">107</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/optimizers/pgd.py#L152-L155">152&ndash;155</a></td></tr><tr><td colspan="5"><b>src/mrpro/algorithms/reconstruction</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/DirectReconstruction.py">DirectReconstruction.py</a></td><td>28</td><td>6</td><td>79%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/DirectReconstruction.py#L62">62</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/DirectReconstruction.py#L65">65</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/DirectReconstruction.py#L70">70</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/DirectReconstruction.py#L77-L79">77&ndash;79</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/IterativeSENSEReconstruction.py">IterativeSENSEReconstruction.py</a></td><td>13</td><td>1</td><td>92%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/IterativeSENSEReconstruction.py#L79">79</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/Reconstruction.py">Reconstruction.py</a></td><td>50</td><td>13</td><td>74%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/Reconstruction.py#L54-L56">54&ndash;56</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/Reconstruction.py#L80-L87">80&ndash;87</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/Reconstruction.py#L109">109</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/Reconstruction.py#L112">112</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/RegularizedIterativeSENSEReconstruction.py">RegularizedIterativeSENSEReconstruction.py</a></td><td>50</td><td>26</td><td>48%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/RegularizedIterativeSENSEReconstruction.py#L103-L107">103&ndash;107</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/algorithms/reconstruction/RegularizedIterativeSENSEReconstruction.py#L121-L158">121&ndash;158</a></td></tr><tr><td colspan="5"><b>src/mrpro/data</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/AcqInfo.py">AcqInfo.py</a></td><td>141</td><td>5</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/AcqInfo.py#L42">42</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/AcqInfo.py#L120-L121">120&ndash;121</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/AcqInfo.py#L123">123</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/AcqInfo.py#L229">229</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/CsmData.py">CsmData.py</a></td><td>45</td><td>5</td><td>89%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/CsmData.py#L17-L19">17&ndash;19</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/CsmData.py#L229-L231">229&ndash;231</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py">Dataclass.py</a></td><td>227</td><td>20</td><td>91%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L40">40</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L296">296</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L312">312</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L378">378</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L436-L438">436&ndash;438</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L451">451</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L533">533</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L553-L554">553&ndash;554</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L556">556</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L571-L572">571&ndash;572</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L574">574</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L608">608</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L621-L622">621&ndash;622</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Dataclass.py#L627-L628">627&ndash;628</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/DcfData.py">DcfData.py</a></td><td>35</td><td>2</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/DcfData.py#L15">15</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/DcfData.py#L62">62</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/EncodingLimits.py">EncodingLimits.py</a></td><td>81</td><td>3</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/EncodingLimits.py#L33">33</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/EncodingLimits.py#L123">123</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/EncodingLimits.py#L126">126</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IData.py">IData.py</a></td><td>52</td><td>2</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IData.py#L119">119</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IData.py#L133">133</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IHeader.py">IHeader.py</a></td><td>127</td><td>7</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IHeader.py#L68-L71">68&ndash;71</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IHeader.py#L250">250</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IHeader.py#L254">254</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IHeader.py#L258">258</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/IHeader.py#L262">262</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py">KData.py</a></td><td>191</td><td>23</td><td>88%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L113-L114">113&ndash;114</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L129">129</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L136">136</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L147-L158">147&ndash;158</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L167">167</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L175">175</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L184">184</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L218">218</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L240-L242">240&ndash;242</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L286-L287">286&ndash;287</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L468">468</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L470">470</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KData.py#L541">541</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py">KHeader.py</a></td><td>134</td><td>16</td><td>88%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L23">23</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L107-L113">107&ndash;113</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L140">140</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L188">188</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L195-L196">195&ndash;196</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L199">199</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L206">206</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KHeader.py#L223-L230">223&ndash;230</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KNoise.py">KNoise.py</a></td><td>22</td><td>1</td><td>95%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KNoise.py#L44">44</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KTrajectory.py">KTrajectory.py</a></td><td>95</td><td>3</td><td>97%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KTrajectory.py#L163">163</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KTrajectory.py#L165">165</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/KTrajectory.py#L185">185</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/QData.py">QData.py</a></td><td>32</td><td>1</td><td>97%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/QData.py#L43">43</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py">Rotation.py</a></td><td>737</td><td>37</td><td>95%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L103">103</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L201">201</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L338">338</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L436">436</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L480">480</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L498">498</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L585">585</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L587">587</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L596">596</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L630">630</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L632">632</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L695">695</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L772">772</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L777">777</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L780">780</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L795">795</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L812">812</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L817">817</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L893">893</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1081">1081</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1086">1086</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1089">1089</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1113">1113</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1117">1117</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1245">1245</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1247">1247</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1255-L1256">1255&ndash;1256</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1320">1320</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1402">1402</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1647">1647</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1731">1731</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1883">1883</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1918">1918</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L1922">1922</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L2098">2098</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/Rotation.py#L2119">2119</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py">SpatialDimension.py</a></td><td>240</td><td>20</td><td>92%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L34">34</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L103">103</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L146">146</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L152">152</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L158">158</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L278-L280">278&ndash;280</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L293-L295">293&ndash;295</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L329">329</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L347">347</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L360">360</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L373">373</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L386">386</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L399">399</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L408-L409">408&ndash;409</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/SpatialDimension.py#L437">437</a></td></tr><tr><td colspan="5"><b>src/mrpro/data/traj_calculators</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryCalculator.py">KTrajectoryCalculator.py</a></td><td>29</td><td>2</td><td>93%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryCalculator.py#L84">84</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryCalculator.py#L96">96</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryCartesian.py">KTrajectoryCartesian.py</a></td><td>31</td><td>4</td><td>87%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryCartesian.py#L107-L110">107&ndash;110</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryCartesian.py#L114">114</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryIsmrmrd.py">KTrajectoryIsmrmrd.py</a></td><td>19</td><td>1</td><td>95%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectoryIsmrmrd.py#L57">57</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py">KTrajectorySpiral2D.py</a></td><td>57</td><td>13</td><td>77%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L63-L66">63&ndash;66</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L69">69</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L71">71</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L73">73</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L75">75</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L77">77</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L105">105</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L107">107</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/data/traj_calculators/KTrajectorySpiral2D.py#L134-L136">134&ndash;136</a></td></tr><tr><td colspan="5"><b>src/mrpro/operators</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/AveragingOp.py">AveragingOp.py</a></td><td>34</td><td>2</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/AveragingOp.py#L53">53</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/AveragingOp.py#L78">78</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/CartesianSamplingOp.py">CartesianSamplingOp.py</a></td><td>107</td><td>4</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/CartesianSamplingOp.py#L142">142</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/CartesianSamplingOp.py#L181">181</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/CartesianSamplingOp.py#L256">256</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/CartesianSamplingOp.py#L360">360</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ConstraintsOp.py">ConstraintsOp.py</a></td><td>79</td><td>4</td><td>95%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ConstraintsOp.py#L78">78</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ConstraintsOp.py#L80">80</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ConstraintsOp.py#L211">211</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ConstraintsOp.py#L216">216</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/EndomorphOperator.py">EndomorphOperator.py</a></td><td>32</td><td>2</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/EndomorphOperator.py#L52">52</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/EndomorphOperator.py#L58">58</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FiniteDifferenceOp.py">FiniteDifferenceOp.py</a></td><td>27</td><td>2</td><td>93%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FiniteDifferenceOp.py#L40">40</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FiniteDifferenceOp.py#L105">105</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FourierOp.py">FourierOp.py</a></td><td>90</td><td>3</td><td>97%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FourierOp.py#L185">185</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FourierOp.py#L257">257</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/FourierOp.py#L262">262</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Functional.py">Functional.py</a></td><td>77</td><td>9</td><td>88%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Functional.py#L20-L22">20&ndash;22</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Functional.py#L117">117</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Functional.py#L119">119</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Functional.py#L226-L228">226&ndash;228</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Functional.py#L242">242</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py">GridSamplingOp.py</a></td><td>136</td><td>9</td><td>93%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py#L71-L72">71&ndash;72</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py#L81-L82">81&ndash;82</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py#L89-L90">89&ndash;90</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py#L93">93</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py#L95">95</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/GridSamplingOp.py#L97">97</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py">LinearOperator.py</a></td><td>201</td><td>8</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L107">107</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L217">217</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L244">244</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L251">251</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L292">292</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L301">301</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L309">309</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperator.py#L326">326</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py">LinearOperatorMatrix.py</a></td><td>162</td><td>19</td><td>88%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L82">82</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L119">119</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L152">152</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L161">161</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L166">166</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L175-L178">175&ndash;178</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L191-L194">191&ndash;194</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L202-L203">202&ndash;203</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L208-L209">208&ndash;209</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L221">221</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L310">310</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L340">340</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/LinearOperatorMatrix.py#L367">367</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/MultiIdentityOp.py">MultiIdentityOp.py</a></td><td>13</td><td>2</td><td>85%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/MultiIdentityOp.py#L43">43</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/MultiIdentityOp.py#L48">48</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py">NonUniformFastFourierOp.py</a></td><td>190</td><td>10</td><td>95%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L69">69</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L96">96</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L206">206</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L208">208</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L242">242</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L244">244</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L321">321</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L379">379</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L429">429</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/NonUniformFastFourierOp.py#L434">434</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Operator.py">Operator.py</a></td><td>79</td><td>2</td><td>97%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Operator.py#L32">32</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/Operator.py#L88">88</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/PatchOp.py">PatchOp.py</a></td><td>47</td><td>3</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/PatchOp.py#L81">81</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/PatchOp.py#L112">112</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/PatchOp.py#L127">127</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ProximableFunctionalSeparableSum.py">ProximableFunctionalSeparableSum.py</a></td><td>39</td><td>3</td><td>92%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ProximableFunctionalSeparableSum.py#L50">50</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ProximableFunctionalSeparableSum.py#L103">103</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ProximableFunctionalSeparableSum.py#L110">110</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py">SliceProjectionOp.py</a></td><td>178</td><td>10</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L45">45</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L62">62</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L64">64</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L70">70</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L153">153</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L179">179</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L215">215</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L236">236</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L269">269</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/SliceProjectionOp.py#L309">309</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/WaveletOp.py">WaveletOp.py</a></td><td>119</td><td>5</td><td>96%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/WaveletOp.py#L151">151</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/WaveletOp.py#L169">169</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/WaveletOp.py#L204">204</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/WaveletOp.py#L209">209</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/WaveletOp.py#L232">232</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ZeroPadOp.py">ZeroPadOp.py</a></td><td>16</td><td>1</td><td>94%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/ZeroPadOp.py#L30">30</a></td></tr><tr><td colspan="5"><b>src/mrpro/operators/functionals</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/functionals/SSIM.py">SSIM.py</a></td><td>71</td><td>7</td><td>90%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/functionals/SSIM.py#L60-L80">60&ndash;80</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/functionals/SSIM.py#L82">82</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/functionals/SSIM.py#L86">86</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/functionals/SSIM.py#L115">115</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/functionals/SSIM.py#L148">148</a></td></tr><tr><td colspan="5"><b>src/mrpro/operators/models</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py">EPG.py</a></td><td>202</td><td>41</td><td>80%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L85-L97">85&ndash;97</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L145-L149">145&ndash;149</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L169-L172">169&ndash;172</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L193-L198">193&ndash;198</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L261">261</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L266">266</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L282-L284">282&ndash;284</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L304-L305">304&ndash;305</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L310">310</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L334">334</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L339">339</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L364">364</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L369">369</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L423">423</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L480">480</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L581">581</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/operators/models/EPG.py#L608">608</a></td></tr><tr><td colspan="5"><b>src/mrpro/phantoms</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py">brainweb.py</a></td><td>276</td><td>31</td><td>89%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L326-L336">326&ndash;336</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L372">372</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L428-L431">428&ndash;431</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L453-L454">453&ndash;454</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L459-L460">459&ndash;460</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L462-L463">462&ndash;463</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L467">467</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L475">475</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L482-L483">482&ndash;483</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L521">521</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L587-L588">587&ndash;588</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L607-L610">607&ndash;610</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L621">621</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L623">623</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L656-L657">656&ndash;657</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/brainweb.py#L670">670</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py">fastmri.py</a></td><td>106</td><td>10</td><td>91%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L50-L51">50&ndash;51</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L59">59</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L65">65</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L162">162</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L169-L171">169&ndash;171</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L174-L175">174&ndash;175</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/phantoms/fastmri.py#L189">189</a></td></tr><tr><td colspan="5"><b>src/mrpro/utils</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py">RandomGenerator.py</a></td><td>152</td><td>14</td><td>91%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L23-L24">23&ndash;24</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L36">36</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L38">38</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L170">170</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L194">194</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L410">410</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L428">428</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L510">510</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L793-L796">793&ndash;796</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L859">859</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/RandomGenerator.py#L862">862</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/filters.py">filters.py</a></td><td>62</td><td>2</td><td>97%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/filters.py#L44">44</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/filters.py#L49">49</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/indexing.py">indexing.py</a></td><td>182</td><td>1</td><td>99%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/indexing.py#L321">321</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py">pad_or_crop.py</a></td><td>31</td><td>6</td><td>81%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py#L26">26</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py#L30">30</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py#L58">58</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py#L61">61</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py#L64">64</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/pad_or_crop.py#L67">67</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/reshape.py">reshape.py</a></td><td>101</td><td>2</td><td>98%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/reshape.py#L111">111</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/reshape.py#L305">305</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/slice_profiles.py">slice_profiles.py</a></td><td>49</td><td>6</td><td>88%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/slice_profiles.py#L21">21</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/slice_profiles.py#L37">37</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/slice_profiles.py#L119-L122">119&ndash;122</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/slice_profiles.py#L155">155</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/split_idx.py">split_idx.py</a></td><td>10</td><td>2</td><td>80%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/split_idx.py#L43">43</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/split_idx.py#L47">47</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/summarize.py">summarize.py</a></td><td>57</td><td>7</td><td>88%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/summarize.py#L40-L41">40&ndash;41</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/summarize.py#L70-L73">70&ndash;73</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/summarize.py#L77">77</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/summarize.py#L81">81</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/typing.py">typing.py</a></td><td>73</td><td>56</td><td>23%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/typing.py#L9-L236">9&ndash;236</a></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py">unit_conversion.py</a></td><td>60</td><td>14</td><td>77%</td><td><a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L32">32</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L40">40</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L42">42</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L49">49</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L51">51</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L58">58</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L60">60</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L69">69</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L80">80</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L82">82</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L101">101</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L103">103</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L124">124</a>, <a href="https://github.com/PTB-MR/mrpro/blob/9f4ac3eed3083ca62a4173d5b5ad9e79e8625f69/src/mrpro/utils/unit_conversion.py#L126">126</a></td></tr><tr><td><b>TOTAL</b></td><td><b>6962</b></td><td><b>529</b></td><td><b>92%</b></td><td>&nbsp;</td></tr></tbody></table></details>

| Tests | Skipped | Failures | Errors | Time |
| ----- | ------- | -------- | -------- | ------------------ |
| 2915 | 0 :zzz: | 0 :x: | 0 :fire: | 1m 57s :stopwatch: |

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-02T23:44:27Z
body: <!-- documentation build 795 -->
### :books: Documentation
:file_folder: [Download as zip](https://github.com/PTB-MR/mrpro/actions/runs/14974489886/artifacts/3106718113)
:mag: [View online](https://zimf.de/zipserve/https://github.com/PTB-MR/mrpro/actions/runs/14974489886/artifacts/3106718113/)
author_association: CONTRIBUTOR