예제 #1
0
def test_generate_noise_spatial():

    # Set up the inputs
    dimensions = np.array([10, 5, 10])
    mask = np.ones(dimensions)
    vol = sim._generate_noise_spatial(dimensions, mask)

    # Run the analysis from _calc_FHWM but for th elast step of aggregating
    # across dimensions
    v_count = 0
    v_sum = 0
    v_sq = 0

    d_sum = [0.0, 0.0, 0.0]
    d_sq = [0.0, 0.0, 0.0]
    d_count = [0, 0, 0]

    # Pull out all the voxel coordinates
    coordinates = list(
        product(range(dimensions[0]), range(dimensions[1]),
                range(dimensions[2])))

    # Find the sum of squared error for the non-masked voxels in the brain
    for i in list(range(len(coordinates))):

        # Pull out this coordinate
        x, y, z = coordinates[i]

        # Is this within the mask?
        if mask[x, y, z] > 0:

            # Find the the volume sum and squared values
            v_count += 1
            v_sum += vol[x, y, z]
            v_sq += vol[x, y, z]**2

    # Get the volume variance
    v_var = (v_sq - ((v_sum**2) / v_count)) / (v_count - 1)

    for i in list(range(len(coordinates))):

        # Pull out this coordinate
        x, y, z = coordinates[i]

        # Is this within the mask?
        if mask[x, y, z] > 0:
            # For each xyz dimension calculate the squared
            # difference of this voxel and the next

            in_range = (x < dimensions[0] - 1)
            in_mask = in_range and (mask[x + 1, y, z] > 0)
            included = in_mask and (~np.isnan(vol[x + 1, y, z]))
            if included:
                d_sum[0] += vol[x, y, z] - vol[x + 1, y, z]
                d_sq[0] += (vol[x, y, z] - vol[x + 1, y, z])**2
                d_count[0] += 1

            in_range = (y < dimensions[1] - 1)
            in_mask = in_range and (mask[x, y + 1, z] > 0)
            included = in_mask and (~np.isnan(vol[x, y + 1, z]))
            if included:
                d_sum[1] += vol[x, y, z] - vol[x, y + 1, z]
                d_sq[1] += (vol[x, y, z] - vol[x, y + 1, z])**2
                d_count[1] += 1

            in_range = (z < dimensions[2] - 1)
            in_mask = in_range and (mask[x, y, z + 1] > 0)
            included = in_mask and (~np.isnan(vol[x, y, z + 1]))
            if included:
                d_sum[2] += vol[x, y, z] - vol[x, y, z + 1]
                d_sq[2] += (vol[x, y, z] - vol[x, y, z + 1])**2
                d_count[2] += 1

    # Find the variance
    d_var = np.divide((d_sq - np.divide(np.power(d_sum, 2), d_count)),
                      (np.add(d_count, -1)))

    o_var = np.divide(-1, (4 * np.log(1 - (0.5 * d_var / v_var))))
    fwhm3 = np.sqrt(o_var) * 2 * np.sqrt(2 * np.log(2))

    # Calculate the proportion of std relative to the mean
    std_proportion = np.nanstd(fwhm3) / np.nanmean(fwhm3)
    assert std_proportion < 0.25, 'Variance is inconsistent across dim'
예제 #2
0
def test_generate_noise_spatial():

    # Set up the inputs
    dimensions = np.array([10, 5, 10])
    mask = np.ones(dimensions)
    vol = sim._generate_noise_spatial(dimensions, mask)

    # Run the analysis from _calc_FHWM but for th elast step of aggregating
    # across dimensions
    v_count = 0
    v_sum = 0
    v_sq = 0

    d_sum = [0.0, 0.0, 0.0]
    d_sq = [0.0, 0.0, 0.0]
    d_count = [0, 0, 0]

    # Pull out all the voxel coordinates
    coordinates = list(product(range(dimensions[0]),
                               range(dimensions[1]),
                               range(dimensions[2])))

    # Find the sum of squared error for the non-masked voxels in the brain
    for i in list(range(len(coordinates))):

        # Pull out this coordinate
        x, y, z = coordinates[i]

        # Is this within the mask?
        if mask[x, y, z] > 0:

            # Find the the volume sum and squared values
            v_count += 1
            v_sum += vol[x, y, z]
            v_sq += vol[x, y, z] ** 2

    # Get the volume variance
    v_var = (v_sq - ((v_sum ** 2) / v_count)) / (v_count - 1)

    for i in list(range(len(coordinates))):

        # Pull out this coordinate
        x, y, z = coordinates[i]

        # Is this within the mask?
        if mask[x, y, z] > 0:
            # For each xyz dimension calculate the squared
            # difference of this voxel and the next

            in_range = (x < dimensions[0] - 1)
            in_mask = in_range and (mask[x + 1, y, z] > 0)
            included = in_mask and (~np.isnan(vol[x + 1, y, z]))
            if included:
                d_sum[0] += vol[x, y, z] - vol[x + 1, y, z]
                d_sq[0] += (vol[x, y, z] - vol[x + 1, y, z]) ** 2
                d_count[0] += 1

            in_range = (y < dimensions[1] - 1)
            in_mask = in_range and (mask[x, y + 1, z] > 0)
            included = in_mask and (~np.isnan(vol[x, y + 1, z]))
            if included:
                d_sum[1] += vol[x, y, z] - vol[x, y + 1, z]
                d_sq[1] += (vol[x, y, z] - vol[x, y + 1, z]) ** 2
                d_count[1] += 1

            in_range = (z < dimensions[2] - 1)
            in_mask = in_range and (mask[x, y, z + 1] > 0)
            included = in_mask and (~np.isnan(vol[x, y, z + 1]))
            if included:
                d_sum[2] += vol[x, y, z] - vol[x, y, z + 1]
                d_sq[2] += (vol[x, y, z] - vol[x, y, z + 1]) ** 2
                d_count[2] += 1

    # Find the variance
    d_var = np.divide((d_sq - np.divide(np.power(d_sum, 2),
                                        d_count)), (np.add(d_count, -1)))

    o_var = np.divide(-1, (4 * np.log(1 - (0.5 * d_var / v_var))))
    fwhm3 = np.sqrt(o_var) * 2 * np.sqrt(2 * np.log(2))

    # Calculate the proportion of std relative to the mean
    std_proportion = np.nanstd(fwhm3) / np.nanmean(fwhm3)
    print(fwhm3)
    assert std_proportion < 0.25, 'Variance is inconsistent across dim'
예제 #3
0
def test_generate_noise():

    dimensions = np.array([10, 10, 10])  # What is the size of the brain
    feature_size = [2]
    feature_type = ['cube']
    feature_coordinates = np.array([[5, 5, 5]])
    signal_magnitude = [1]

    # Generate a volume representing the location and quality of the signal
    volume = sim.generate_signal(
        dimensions=dimensions,
        feature_coordinates=feature_coordinates,
        feature_type=feature_type,
        feature_size=feature_size,
        signal_magnitude=signal_magnitude,
    )

    # Inputs for generate_stimfunction
    onsets = [10, 30, 50, 70, 90]
    event_durations = [6]
    tr_duration = 2
    duration = 200

    # Create the time course for the signal to be generated
    stimfunction = sim.generate_stimfunction(
        onsets=onsets,
        event_durations=event_durations,
        total_time=duration,
    )

    signal_function = sim.convolve_hrf(
        stimfunction=stimfunction,
        tr_duration=tr_duration,
    )

    # Convolve the HRF with the stimulus sequence
    signal = sim.apply_signal(
        signal_function=signal_function,
        volume_signal=volume,
    )

    # Generate the mask of the signal
    mask, template = sim.mask_brain(signal, mask_self=None)

    assert min(mask[mask > 0]) > 0.1, "Mask thresholding did not work"
    assert len(np.unique(template) > 2), "Template creation did not work"

    stimfunction_tr = stimfunction[::int(tr_duration * 100)]

    # Create the noise volumes (using the default parameters)
    noise = sim.generate_noise(
        dimensions=dimensions,
        stimfunction_tr=stimfunction_tr,
        tr_duration=tr_duration,
        template=template,
        mask=mask,
        iterations=[1, 0],
    )

    assert signal.shape == noise.shape, "The dimensions of signal and noise " \
                                        "the same"

    noise_high = sim.generate_noise(
        dimensions=dimensions,
        stimfunction_tr=stimfunction_tr,
        tr_duration=tr_duration,
        template=template,
        mask=mask,
        noise_dict={
            'sfnr': 50,
            'snr': 25
        },
        iterations=[1, 0],
    )

    noise_low = sim.generate_noise(
        dimensions=dimensions,
        stimfunction_tr=stimfunction_tr,
        tr_duration=tr_duration,
        template=template,
        mask=mask,
        noise_dict={
            'sfnr': 100,
            'snr': 25
        },
        iterations=[1, 0],
    )

    system_high = np.std(noise_high[mask > 0], 1).mean()
    system_low = np.std(noise_low[mask > 0], 1).mean()

    assert system_low < system_high, "SFNR noise could not be manipulated"

    # Check that you check for the appropriate template values
    with pytest.raises(ValueError):
        sim.generate_noise(
            dimensions=dimensions,
            stimfunction_tr=stimfunction_tr,
            tr_duration=tr_duration,
            template=template * 2,
            mask=mask,
            noise_dict={},
        )

    # Check that iterations does what it should
    sim.generate_noise(
        dimensions=dimensions,
        stimfunction_tr=stimfunction_tr,
        tr_duration=tr_duration,
        template=template,
        mask=mask,
        noise_dict={},
        iterations=[0, 0],
    )

    sim.generate_noise(
        dimensions=dimensions,
        stimfunction_tr=stimfunction_tr,
        tr_duration=tr_duration,
        template=template,
        mask=mask,
        noise_dict={},
        iterations=None,
    )

    # Test drift noise
    trs = 1000
    period = 100
    drift = sim._generate_noise_temporal_drift(
        trs,
        tr_duration,
        'sine',
        period,
    )

    # Check that the max frequency is the appropriate frequency
    power = abs(np.fft.fft(drift))[1:trs // 2]
    freq = np.linspace(1, trs // 2 - 1, trs // 2 - 1) / trs
    period_freq = np.where(freq == 1 / (period // tr_duration))
    max_freq = np.argmax(power)

    assert period_freq == max_freq, 'Max frequency is not where it should be'

    # Do the same but now with cosine basis functions, answer should be close
    drift = sim._generate_noise_temporal_drift(
        trs,
        tr_duration,
        'discrete_cos',
        period,
    )

    # Check that the appropriate frequency is peaky (may not be the max)
    power = abs(np.fft.fft(drift))[1:trs // 2]
    freq = np.linspace(1, trs // 2 - 1, trs // 2 - 1) / trs
    period_freq = np.where(freq == 1 / (period // tr_duration))[0][0]

    assert power[period_freq] > power[period_freq + 1], 'Power is low'
    assert power[period_freq] > power[period_freq - 1], 'Power is low'

    # Check it runs fine
    drift = sim._generate_noise_temporal_drift(
        50,
        tr_duration,
        'discrete_cos',
        period,
    )

    # Check it runs fine
    drift = sim._generate_noise_temporal_drift(
        300,
        tr_duration,
        'cos_power_drop',
        period,
    )

    # Check that when the TR is greater than the period it errors
    with pytest.raises(ValueError):
        sim._generate_noise_temporal_drift(30, 10, 'cos_power_drop', 5)

    # Test physiological noise (using unrealistic parameters so that it's easy)
    timepoints = list(np.linspace(0, (trs - 1) * tr_duration, trs))
    resp_freq = 0.2
    heart_freq = 1.17
    phys = sim._generate_noise_temporal_phys(
        timepoints,
        resp_freq,
        heart_freq,
    )

    # Check that the max frequency is the appropriate frequency
    power = abs(np.fft.fft(phys))[1:trs // 2]
    freq = np.linspace(1, trs // 2 - 1, trs // 2 - 1) / (trs * tr_duration)
    peaks = (power > (power.mean() + power.std()))  # Where are the peaks
    peak_freqs = freq[peaks]

    assert np.any(resp_freq == peak_freqs), 'Resp frequency not found'
    assert len(peak_freqs) == 2, 'Two peaks not found'

    # Test task noise
    sim._generate_noise_temporal_task(
        stimfunction_tr,
        motion_noise='gaussian',
    )
    sim._generate_noise_temporal_task(
        stimfunction_tr,
        motion_noise='rician',
    )

    # Test ARMA noise
    with pytest.raises(ValueError):
        noise_dict = {'fwhm': 4, 'auto_reg_rho': [1], 'ma_rho': [1, 1]}
        sim._generate_noise_temporal_autoregression(
            stimfunction_tr,
            noise_dict,
            dimensions,
            mask,
        )

    # Generate spatial noise
    vol = sim._generate_noise_spatial(np.array([10, 10, 10, trs]))
    assert len(vol.shape) == 3, 'Volume was not reshaped to ignore TRs'

    # Switch some of the noise types on
    noise_dict = dict(physiological_sigma=1,
                      drift_sigma=1,
                      task_sigma=1,
                      auto_reg_sigma=0)
    sim.generate_noise(
        dimensions=dimensions,
        stimfunction_tr=stimfunction_tr,
        tr_duration=tr_duration,
        template=template,
        mask=mask,
        noise_dict=noise_dict,
        iterations=[0, 0],
    )
예제 #4
0
def test_generate_noise():

    dimensions = np.array([10, 10, 10])  # What is the size of the brain
    feature_size = [2]
    feature_type = ['cube']
    feature_coordinates = np.array(
        [[5, 5, 5]])
    signal_magnitude = [1]

    # Generate a volume representing the location and quality of the signal
    volume = sim.generate_signal(dimensions=dimensions,
                                 feature_coordinates=feature_coordinates,
                                 feature_type=feature_type,
                                 feature_size=feature_size,
                                 signal_magnitude=signal_magnitude,
                                 )

    # Inputs for generate_stimfunction
    onsets = [10, 30, 50, 70, 90]
    event_durations = [6]
    tr_duration = 2
    duration = 200

    # Create the time course for the signal to be generated
    stimfunction = sim.generate_stimfunction(onsets=onsets,
                                             event_durations=event_durations,
                                             total_time=duration,
                                             )

    signal_function = sim.convolve_hrf(stimfunction=stimfunction,
                                       tr_duration=tr_duration,
                                       )

    # Convolve the HRF with the stimulus sequence
    signal = sim.apply_signal(signal_function=signal_function,
                              volume_signal=volume,
                              )

    # Generate the mask of the signal
    mask, template = sim.mask_brain(signal,
                                    mask_self=None)

    assert min(mask[mask > 0]) > 0.1, "Mask thresholding did not work"
    assert len(np.unique(template) > 2), "Template creation did not work"

    stimfunction_tr = stimfunction[::int(tr_duration * 100)]

    # Create the noise volumes (using the default parameters)
    noise = sim.generate_noise(dimensions=dimensions,
                               stimfunction_tr=stimfunction_tr,
                               tr_duration=tr_duration,
                               template=template,
                               mask=mask,
                               iterations=[1, 0],
                               )

    assert signal.shape == noise.shape, "The dimensions of signal and noise " \
                                        "the same"

    noise_high = sim.generate_noise(dimensions=dimensions,
                                    stimfunction_tr=stimfunction_tr,
                                    tr_duration=tr_duration,
                                    template=template,
                                    mask=mask,
                                    noise_dict={'sfnr': 50, 'snr': 25},
                                    iterations=[1, 0],
                                    )

    noise_low = sim.generate_noise(dimensions=dimensions,
                                   stimfunction_tr=stimfunction_tr,
                                   tr_duration=tr_duration,
                                   template=template,
                                   mask=mask,
                                   noise_dict={'sfnr': 100, 'snr': 25},
                                   iterations=[1, 0],
                                   )

    system_high = np.std(noise_high[mask > 0], 1).mean()
    system_low = np.std(noise_low[mask > 0], 1).mean()

    assert system_low < system_high, "SFNR noise could not be manipulated"

    # Check that you check for the appropriate template values
    with pytest.raises(ValueError):
        sim.generate_noise(dimensions=dimensions,
                           stimfunction_tr=stimfunction_tr,
                           tr_duration=tr_duration,
                           template=template * 2,
                           mask=mask,
                           noise_dict={},
                           )

    # Check that iterations does what it should
    sim.generate_noise(dimensions=dimensions,
                       stimfunction_tr=stimfunction_tr,
                       tr_duration=tr_duration,
                       template=template,
                       mask=mask,
                       noise_dict={},
                       iterations=[0, 0],
                       )

    sim.generate_noise(dimensions=dimensions,
                       stimfunction_tr=stimfunction_tr,
                       tr_duration=tr_duration,
                       template=template,
                       mask=mask,
                       noise_dict={},
                       iterations=None,
                       )

    # Test drift noise
    trs = 1000
    period = 100
    drift = sim._generate_noise_temporal_drift(trs,
                                               tr_duration,
                                               'sine',
                                               period,
                                               )

    # Check that the max frequency is the appropriate frequency
    power = abs(np.fft.fft(drift))[1:trs // 2]
    freq = np.linspace(1, trs // 2 - 1, trs // 2 - 1) / trs
    period_freq = np.where(freq == 1 / (period // tr_duration))
    max_freq = np.argmax(power)

    assert period_freq == max_freq, 'Max frequency is not where it should be'

    # Do the same but now with cosine basis functions, answer should be close
    drift = sim._generate_noise_temporal_drift(trs,
                                               tr_duration,
                                               'discrete_cos',
                                               period,
                                               )

    # Check that the appropriate frequency is peaky (may not be the max)
    power = abs(np.fft.fft(drift))[1:trs // 2]
    freq = np.linspace(1, trs // 2 - 1, trs // 2 - 1) / trs
    period_freq = np.where(freq == 1 / (period // tr_duration))[0][0]

    assert power[period_freq] > power[period_freq + 1], 'Power is low'
    assert power[period_freq] > power[period_freq - 1], 'Power is low'

    # Check it gives a warning if the duration is too short
    drift = sim._generate_noise_temporal_drift(50,
                                               tr_duration,
                                               'discrete_cos',
                                               period,
                                               )

    # Test physiological noise (using unrealistic parameters so that it's easy)
    timepoints = list(np.linspace(0, (trs - 1) * tr_duration, trs))
    resp_freq = 0.2
    heart_freq = 1.17
    phys = sim._generate_noise_temporal_phys(timepoints,
                                             resp_freq,
                                             heart_freq,
                                             )

    # Check that the max frequency is the appropriate frequency
    power = abs(np.fft.fft(phys))[1:trs // 2]
    freq = np.linspace(1, trs // 2 - 1, trs // 2 - 1) / (trs * tr_duration)
    peaks = (power > (power.mean() + power.std()))  # Where are the peaks
    peak_freqs = freq[peaks]

    assert np.any(resp_freq == peak_freqs), 'Resp frequency not found'
    assert len(peak_freqs) == 2, 'Two peaks not found'

    # Test task noise
    sim._generate_noise_temporal_task(stimfunction_tr,
                                      motion_noise='gaussian',
                                      )
    sim._generate_noise_temporal_task(stimfunction_tr,
                                      motion_noise='rician',
                                      )

    # Test ARMA noise
    with pytest.raises(ValueError):
        noise_dict = {'fwhm': 4, 'auto_reg_rho': [1], 'ma_rho': [1, 1]}
        sim._generate_noise_temporal_autoregression(stimfunction_tr,
                                                    noise_dict,
                                                    dimensions,
                                                    mask,
                                                    )

    # Generate spatial noise
    vol = sim._generate_noise_spatial(np.array([10, 10, 10, trs]))
    assert len(vol.shape) == 3, 'Volume was not reshaped to ignore TRs'

    # Switch some of the noise types on
    noise_dict = dict(physiological_sigma=1, drift_sigma=1, task_sigma=1,
                      auto_reg_sigma=0)
    sim.generate_noise(dimensions=dimensions,
                       stimfunction_tr=stimfunction_tr,
                       tr_duration=tr_duration,
                       template=template,
                       mask=mask,
                       noise_dict=noise_dict,
                       iterations=[0, 0],
                       )