コード例 #1
0
    def generate_t2_star_map(self,
                             tissue: Tissue,
                             mask_path: str = None,
                             num_workers: int = 0):
        """
        Generate 3D :math:`T_2^* map and r-squared fit map using mono-exponential fit
        across subvolumes acquired at different echo times.

        :math:`T_2^* map is also added to the tissue.

        Args:
            tissue (Tissue): Tissue to generate quantitative value for.
            mask_path (:obj:`str`, optional): File path to mask of ROI to analyze.
                If specified, only voxels specified by mask will be fit.
                This can considerably speed up computation.
            num_workers (int, optional): Number of subprocesses to use for fitting.
                If `0`, will execute on the main thread.

        Returns:
            qv.T2Star: :math:`T_2^* fit for tissue.

        Raises:
            ValueError: If ``mask_path`` corresponds to non-binary volume.
        """
        # only calculate for focused region if a mask is available, this speeds up computation
        mask = tissue.get_mask()
        if mask_path is not None:
            mask = (fio_utils.generic_load(mask_path, expected_num_volumes=1)
                    if isinstance(mask_path,
                                  (str, os.PathLike)) else mask_path)

        spin_lock_times = self.echo_times
        subvolumes_list = self.volumes

        mef = MonoExponentialFit(
            bounds=(__T2_STAR_LOWER_BOUND__, __T2_STAR_UPPER_BOUND__),
            tc0="polyfit",
            decimal_precision=__T2_STAR_DECIMAL_PRECISION__,
            num_workers=num_workers,
            verbose=True,
        )

        t2star_map, r2 = mef.fit(spin_lock_times, subvolumes_list, mask=mask)

        quant_val_map = qv.T2Star(t2star_map)
        quant_val_map.add_additional_volume("r2", r2)

        tissue.add_quantitative_value(quant_val_map)

        return quant_val_map
コード例 #2
0
    def test_headers(self):
        x, y, b = _generate_monoexp_data((10, 10, 20))
        t = 1 / np.abs(b)
        for idx, _y in enumerate(y):
            _y._headers = util.build_dummy_headers(
                (1, 1) + _y.shape[2:],
                fields={"StudyDescription": "Sample study", "EchoNumbers": idx},
            )

        fitter = MonoExponentialFit(decimal_precision=8)
        t_hat = fitter.fit(x, y)[0]

        assert np.allclose(t_hat.volume, t)
        assert t_hat.headers() is not None
        assert t_hat.headers().shape == (1, 1, 20)
        for h in t_hat.headers().flatten():
            assert h.get("StudyDescription") == "Sample study"
コード例 #3
0
    def test_matches_monoexponential_fit(self):
        """Match functionality of ``MonoexponentialFit`` using ``CurveFitter``."""
        x, y, _ = _generate_monoexp_data((10, 10, 20))

        fitter = MonoExponentialFit(tc0=30.0, bounds=(0, 100), decimal_precision=8)
        t_hat_mef = fitter.fit(x, y)[0]

        fitter = CurveFitter(
            monoexponential,
            p0=(1.0, -1 / 30),
            out_ufuncs=[None, lambda x: 1 / np.abs(x)],
            out_bounds=(0, 100),
            nan_to_num=0,
        )
        t_hat_cf = fitter.fit(x, y)[0][..., 1]
        t_hat_cf = np.round(t_hat_cf, decimals=8)

        assert np.allclose(t_hat_mef.volume, t_hat_cf.volume)
コード例 #4
0
    def __fitting_helper(
        self,
        qv_type: QuantitativeValueType,
        echo_inds: Sequence[int],
        tissue: Tissue,
        bounds,
        tc0,
        decimal_precision,
        mask_path,
        num_workers,
    ):
        echo_info = [(self.echo_times[i], self.volumes[i]) for i in echo_inds]

        # sort by echo time
        echo_info = sorted(echo_info, key=lambda x: x[0])

        xs = [et for et, _ in echo_info]
        ys = [vol for _, vol in echo_info]

        # only calculate for focused region if a mask is available, this speeds up computation
        mask = tissue.get_mask()
        if mask_path is not None:
            mask = (fio_utils.generic_load(mask_path, expected_num_volumes=1)
                    if isinstance(mask_path,
                                  (str, os.PathLike)) else mask_path)

        mef = MonoExponentialFit(
            bounds=bounds,
            tc0=tc0,
            decimal_precision=decimal_precision,
            num_workers=num_workers,
            verbose=True,
        )
        qv_map, r2 = mef.fit(xs, ys, mask=mask)

        quant_val_map = qv_type(qv_map)
        quant_val_map.add_additional_volume("r2", r2)

        tissue.add_quantitative_value(quant_val_map)

        return quant_val_map
コード例 #5
0
    def test_mask(self):
        x, y, b = _generate_monoexp_data((10, 10, 20))
        mask_arr = np.random.rand(*y[0].shape) > 0.5
        t = 1 / np.abs(b)

        mask = MedicalVolume(mask_arr, np.eye(4))
        fitter = MonoExponentialFit(decimal_precision=8)
        t_hat = fitter.fit(x, y, mask)[0]

        mask = mask.volume
        assert np.allclose(t_hat.volume[mask != 0], t[mask != 0])

        fitter2 = MonoExponentialFit(decimal_precision=8)
        t_hat2 = fitter2.fit(x, y, mask_arr)[0]
        assert np.allclose(t_hat2.volume, t_hat.volume)

        with self.assertWarns(UserWarning):
            fitter3 = MonoExponentialFit(mask=mask, decimal_precision=8)
        t_hat3 = fitter3.fit(x, y)[0]
        assert np.allclose(t_hat3.volume, t_hat.volume)
コード例 #6
0
    def test_polyfit_initialization(self):
        x, y, b = _generate_monoexp_data((10, 10, 20))
        t = 1 / np.abs(b)

        fitter = MonoExponentialFit(tc0="polyfit", decimal_precision=8)
        t_hat = fitter.fit(x, y)[0]
        assert np.allclose(t_hat.volume, t)

        # Test fitting still works even if some values are 0.
        # The values will not be accurate, but other pixel values should be.
        x, y, b = _generate_monoexp_data((10, 10, 20))
        t = 1 / np.abs(b)
        mask_arr = np.zeros(y[0].shape, dtype=np.bool)
        mask_arr[:5, :5] = 1
        y[0][mask_arr] = 0

        fitter = MonoExponentialFit(tc0="polyfit", decimal_precision=8)
        t_hat = fitter.fit(x, y)[0]
        assert np.allclose(t_hat.volume[mask_arr == 0], t[mask_arr == 0])
コード例 #7
0
    def test_basic(self):
        x, y, b = _generate_monoexp_data((10, 10, 20))
        t = 1 / np.abs(b)

        fitter = MonoExponentialFit(decimal_precision=8)
        t_hat = fitter.fit(x, y)[0]
        assert np.allclose(t_hat.volume, t)

        with self.assertWarns(UserWarning):
            fitter = MonoExponentialFit(x, y, decimal_precision=8)
        t_hat = fitter.fit(x, y)[0]
        assert np.allclose(t_hat.volume, t)

        with self.assertRaises(ValueError):
            fitter = MonoExponentialFit(list(x) + [5], y)
        with self.assertRaises(TypeError):
            fitter = MonoExponentialFit(x, [_y.A for _y in y])
        with self.assertRaises(ValueError):
            fitter = MonoExponentialFit(x, y, tc0="a value")