Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fraction masks raises error #344

Open
osbm opened this issue Jul 1, 2024 · 1 comment
Open

Fraction masks raises error #344

osbm opened this issue Jul 1, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@osbm
Copy link

osbm commented Jul 1, 2024

Here is the minimal code that reproduces the error.

from fastmri.data.subsample import create_mask_for_mask_type
from fastmri.data.transforms import apply_mask, to_tensor, center_crop
import numpy as np

mask_func =create_mask_for_mask_type(
    mask_type_str="magic_fraction",
    center_fractions=[0.37],
    accelerations=[4]
)

kspace = np.load("data/prostate1_kspace.npy")
print(kspace.shape) # (34, 14, 640, 451)
kspace = to_tensor(kspace)
print(kspace.shape) # torch.Size([34, 14, 640, 451, 2])
subsampled_kspace, mask, num_low_frequencies = apply_mask(
    kspace,
    mask_func,
    seed=1
)

The error:

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    subsampled_kspace, mask, num_low_frequencies = apply_mask(
                                                   ^^^^^^^^^^^
  File ".venv/lib/python3.12/site-packages/fastmri/data/transforms.py", line 77, in apply_mask
    mask, num_low_frequencies = mask_func(shape, offset, seed)
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv/lib/python3.12/site-packages/fastmri/data/subsample.py", line 105, in __call__
    center_mask, accel_mask, num_low_frequencies = self.sample_mask(
                                                   ^^^^^^^^^^^^^^^^^
  File ".venv/lib/python3.12/site-packages/fastmri/data/subsample.py", line 469, in sample_mask
    self.calculate_acceleration_mask(
  File ".venv/lib/python3.12/site-packages/fastmri/data/subsample.py", line 384, in calculate_acceleration_mask
    offset = self.rng.randint(0, high=acceleration)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "numpy/random/mtrand.pyx", line 798, in numpy.random.mtrand.RandomState.randint
  File "numpy/random/_bounded_integers.pyx", line 1334, in numpy.random._bounded_integers._rand_int64
ValueError: high <= 0

But this works fine when mask_type_str is equal to the equispaced, random, magic but not the equispaced_fraction or magic_fraction.

I might be missing something as i dont understand what adding "fraction" changes in the behaviour of the masking function.

@osbm osbm added the bug Something isn't working label Jul 1, 2024
@mmuckley
Copy link
Contributor

Hello @osbm, the "fraction" option adjusts the spacing so that the actual sampling rate should match the target rate. If you pick 4 with equispaced then the actual sampling rate will be a value lower than 4, equispaced_fraction tries to fix that. You can see the logic here:

class EquispacedMaskFractionFunc(MaskFunc):
"""
Equispaced mask with approximate acceleration matching.
The mask selects a subset of columns from the input k-space data. If the
k-space data has N columns, the mask picks out:
1. N_low_freqs = (N * center_fraction) columns in the center
corresponding to low-frequencies.
2. The other columns are selected with equal spacing at a proportion
that reaches the desired acceleration rate taking into consideration
the number of low frequencies. This ensures that the expected number
of columns selected is equal to (N / acceleration)
It is possible to use multiple center_fractions and accelerations, in which
case one possible (center_fraction, acceleration) is chosen uniformly at
random each time the EquispacedMaskFunc object is called.
Note that this function may not give equispaced samples (documented in
https://github.com/facebookresearch/fastMRI/issues/54), which will require
modifications to standard GRAPPA approaches. Nonetheless, this aspect of
the function has been preserved to match the public multicoil data.
"""
def calculate_acceleration_mask(
self,
num_cols: int,
acceleration: int,
offset: Optional[int],
num_low_frequencies: int,
) -> np.ndarray:
"""
Produce mask for non-central acceleration lines.
Args:
num_cols: Number of columns of k-space (2D subsampling).
acceleration: Desired acceleration rate.
offset: Offset from 0 to begin masking. If no offset is specified,
then one is selected randomly.
num_low_frequencies: Number of low frequencies. Used to adjust mask
to exactly match the target acceleration.
Returns:
A mask for the high spatial frequencies of k-space.
"""
# determine acceleration rate by adjusting for the number of low frequencies
adjusted_accel = (acceleration * (num_low_frequencies - num_cols)) / (
num_low_frequencies * acceleration - num_cols
)
if offset is None:
offset = self.rng.randint(0, high=round(adjusted_accel))
mask = np.zeros(num_cols)
accel_samples = np.arange(offset, num_cols - 1, adjusted_accel)
accel_samples = np.around(accel_samples).astype(np.uint)
mask[accel_samples] = 1.0
return mask

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants