def test_read_nii_b1(self):
        fname_b1 = os.path.join(__dir_testing__, 'b1_maps', 'nifti',
                                'sub-01_run-10_TB1map.nii.gz')
        nii, json_info, b1 = read_nii(fname_b1)

        assert b1.shape == (64, 64, 16, 8), "Wrong rf-map shape"
        assert np.abs(b1).max() <= 180 and np.abs(
            b1).min() >= 0, "Magnitude values out of range"
        assert np.angle(b1).max(initial=0) <= np.pi and np.angle(b1).min(initial=0) >= -np.pi,\
            "Phase values out of range"

        # Check masking consistency for all coils at each slice
        for i in range(b1.shape[2]):
            for j in range(b1.shape[3] - 1):
                assert ((b1[:, :, i, j] != 0) == (b1[:, :, i, j + 1] !=
                                                  0)).any()

        test_values = [
            -4.274539911369111 + 4.599952786001116j,
            -5.8027003257021725 + 2.2042390773527423j,
            -2.1929304691258276 + 1.5241263801971388j
        ]

        assert np.isclose(
            [b1[35, 35, 0, 0], b1[35, 35, 6, 7], b1[40, 25, 15, 7]],
            test_values).all()

        assert (json.dumps(json_info, sort_keys=True) == json.dumps(self._json_b1, sort_keys=True)),\
            "JSON file is not correctly loaded for first RF JSON"
    def test_read_nii_b1_negative_mag(self):
        data_negative_mag = self._data_b1.copy()
        data_negative_mag[35, 35, 0, 0] = -1
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=data_negative_mag,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_negative_mag'))
        with open(
                os.path.join(self.data_path_b1, 'dummy_b1_negative_mag.json'),
                'w') as json_file:
            json.dump(self._json_b1, json_file)

        fname_b1 = os.path.join(self.data_path_b1, "dummy_b1_negative_mag.nii")
        with pytest.raises(ValueError,
                           match="Unexpected negative magnitude values"):
            read_nii(fname_b1)
Beispiel #3
0
def prepare_fieldmap_cli(phase, fname_mag, unwrapper, fname_output, fname_mask, threshold, gaussian_filter, sigma):
    """Creates fieldmap (in Hz) from phase images. This function accommodates multiple echoes (2 or more) and phase
    difference. This function also accommodates 4D phase inputs, where the 4th dimension represents the time, in case
    multiple field maps are acquired across time for the purpose of real-time shimming experiments.

    phase: Input path of phase nifti file(s), in ascending order: echo1, echo2, etc.
    """

    # Import phase
    list_phase = []
    echo_times = []
    for i_echo in range(len(phase)):
        nii_phase, json_phase, phase_img = read_nii(phase[i_echo], auto_scale=True)
        # Add pi since read_nii returns phase between 0 and 2pi whereas prepare_fieldmap accepts between -pi to pi
        phase_img -= math.pi

        list_phase.append(phase_img)
        # Special case for echo_times if input is a phasediff
        if len(phase) == 1:
            # Check that the input phase is indeed a phasediff, by checking the existence of two echo times in the
            # metadata
            if not ('EchoTime1' in json_phase) or not ('EchoTime2' in json_phase):
                raise RuntimeError(
                    "The JSON file of the input phase should include the fields EchoTime1 and EchoTime2 if"
                    "it is a phase difference.")
            echo_times = [json_phase['EchoTime1'], json_phase['EchoTime2']]  # [s]
        else:
            echo_times.append(json_phase['EchoTime'])

    # Get affine from nii
    affine = nii_phase.affine

    # If fname_mag is not an input define mag as None
    if fname_mag is not None:
        mag = nib.load(fname_mag).get_fdata()
    else:
        mag = None

    # Import mask
    if fname_mask is not None:
        mask = nib.load(fname_mask).get_fdata()
    else:
        mask = None

    fieldmap_hz = prepare_fieldmap(list_phase, echo_times, affine, mag=mag, unwrapper=unwrapper, mask=mask,
                                   threshold=threshold, gaussian_filter=gaussian_filter, sigma=sigma)

    # Save NIFTI
    nii_fieldmap = nib.Nifti1Image(fieldmap_hz, affine)
    nib.save(nii_fieldmap, fname_output)

    # Save json
    json_fieldmap = json_phase
    if len(phase) > 1:
        for i_echo in range(len(echo_times)):
            json_fieldmap[f'EchoTime{i_echo + 1}'] = echo_times[i_echo]
    fname_json = fname_output.rsplit('.nii', 1)[0] + '.json'
    with open(fname_json, 'w') as outfile:
        json.dump(json_fieldmap, outfile, indent=2)
    def test_read_nii_b1_no_shimsetting(self):
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=self._data_b1,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_no_shimsetting'))
        with open(
                os.path.join(self.data_path_b1,
                             'dummy_b1_no_shimsetting.json'),
                'w') as json_file:
            self._json_b1_no_shimsetting = self._json_b1.copy()
            del self._json_b1_no_shimsetting['ShimSetting']
            json.dump(self._json_b1_no_shimsetting, json_file)

        fname_b1 = os.path.join(self.data_path_b1,
                                'dummy_b1_no_shimsetting.nii')
        with pytest.raises(KeyError, match="Missing json tag: 'ShimSetting'"):
            read_nii(fname_b1)
 def test_read_nii_b1_no_scaling(self):
     fname_b1 = os.path.join(__dir_testing__, 'b1_maps', 'nifti',
                             'sub-01_run-10_TB1map.nii.gz')
     _, _, b1 = read_nii(fname_b1, auto_scale=False)
     assert b1.shape == (64, 64, 16, 16), "Wrong rf-map shape"
     test_values = [87.0, 1890.0, 37.0]
     assert [b1[35, 35, 0, 0], b1[35, 35, 6, 13], b1[40, 25, 15,
                                                     7]] == test_values
    def test_read_nii_b1_negative_mag(self):
        data_negative_mag = self._data_b1.copy()
        data_negative_mag[35, 35, 0, 0] = -1
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=data_negative_mag,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_negative_mag'))
        with open(
                os.path.join(self.data_path_b1, 'dummy_b1_negative_mag.json'),
                'w') as json_file:
            json.dump(self._json_b1, json_file)

        fname_b1 = os.path.join(self.data_path_b1, "dummy_b1_negative_mag.nii")
        try:
            read_nii(fname_b1)
        except ValueError:
            return 0
    def test_read_nii_real_data(self):
        fname_phasediff = os.path.join(__dir_testing__,
                                       'realtime_zshimming_data', 'nifti',
                                       'sub-example', 'fmap',
                                       'sub-example_phasediff.nii.gz')
        nii, json_info, phasediff = read_nii(fname_phasediff)

        assert nii.shape == (64, 96, 1, 10)
        assert ('P' in json_info['ImageType'])
        assert (phasediff.max() <= 2 * math.pi) and (phasediff.min() >= 0)
    def test_read_nii_b1_no_slicetiming(self):
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=self._data_b1,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_no_slicetiming'))
        with open(
                os.path.join(self.data_path_b1,
                             'dummy_b1_no_slicetiming.json'),
                'w') as json_file:
            self._json_b1_no_slicetiming = self._json_b1.copy()
            del self._json_b1_no_slicetiming['SliceTiming']
            json.dump(self._json_b1_no_slicetiming, json_file)

        fname_b1 = os.path.join(self.data_path_b1,
                                'dummy_b1_no_slicetiming.nii')
        try:
            read_nii(fname_b1)
        except ValueError:
            return 0
    def test_read_nii_b1_wrong_slicetiming(self):
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=self._data_b1,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_wrong_slicetiming'))
        with open(
                os.path.join(self.data_path_b1,
                             'dummy_b1_wrong_slicetiming.json'),
                'w') as json_file:
            self._json_b1_wrong_slicetiming = self._json_b1.copy()
            self._json_b1_wrong_slicetiming['SliceTiming'] = str(np.zeros([15
                                                                           ]))
            json.dump(self._json_b1_wrong_slicetiming, json_file)

        fname_b1 = os.path.join(self.data_path_b1,
                                "dummy_b1_wrong_slicetiming.nii")
        with pytest.raises(
                ValueError,
                match="Wrong array dimension: number of slices not matching"):
            read_nii(fname_b1)
    def test_read_nii_b1_wrong_shimsetting(self):
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=self._data_b1,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_wrong_shimsetting'))
        with open(
                os.path.join(self.data_path_b1,
                             'dummy_b1_wrong_shimsetting.json'),
                'w') as json_file:
            self._json_b1_wrong_shimsetting = self._json_b1.copy()
            self._json_b1_wrong_shimsetting['ShimSetting'] = str(np.zeros([15
                                                                           ]))
            json.dump(self._json_b1_wrong_shimsetting, json_file)

        fname_b1 = os.path.join(self.data_path_b1,
                                "dummy_b1_wrong_shimsetting.nii")
        try:
            read_nii(fname_b1)
        except ValueError:
            return 0
    def test_read_nii_b1_no_slicetiming(self):
        dummy_data_b1 = nib.nifti1.Nifti1Image(dataobj=self._data_b1,
                                               affine=self._aff)
        nib.save(dummy_data_b1,
                 os.path.join(self.data_path_b1, 'dummy_b1_no_slicetiming'))
        with open(
                os.path.join(self.data_path_b1,
                             'dummy_b1_no_slicetiming.json'),
                'w') as json_file:
            self._json_b1_no_slicetiming = self._json_b1.copy()
            del self._json_b1_no_slicetiming['SliceTiming']
            json.dump(self._json_b1_no_slicetiming, json_file)

        fname_b1 = os.path.join(self.data_path_b1,
                                "dummy_b1_no_slicetiming.nii")
        with pytest.warns(
                UserWarning,
                match=
                "Missing json tag: 'SliceTiming', slices number cannot be checked."
        ):
            read_nii(fname_b1)