def test_kbdm_m_none_should_use_default_value(data_brain_sim, dwell): l = 30 line_lists, info = kbdm(data=data_brain_sim, dwell=dwell, l=l) assert np.shape(line_lists) == (l, 4) assert info.m == l assert info.l == l
def test_kbdm_svd(data_brain_sim, dwell, df_params_brain_sim, columns): m = 300 params_est, info = kbdm( data_brain_sim, dwell, m=m, ) assert params_est.shape == (m, 4) assert info.m == m assert info.l == m assert info.q == pytest.approx(0) assert info.p == 1 df_est = pd.DataFrame(data=params_est, columns=columns) df_est = df_est[df_est['amplitude'] > 1e-4] df_est = df_est.sort_values(['frequency']) assert len(df_est) == 16 for i in range(16): assert pytest.approx(df_est['amplitude'].iloc[i]) == df_params_brain_sim['amplitude'].iloc[i], \ f'Amplitude does not match at peak #{i}' assert pytest.approx(df_est['t2'].iloc[i], rel=1e-3) == df_params_brain_sim['t2'].iloc[i], \ f'T2 does not match at peak #{i}' assert pytest.approx(df_est['frequency'].iloc[i], abs=0.3) == df_params_brain_sim['frequency'].iloc[i], \ f'Frequency does not match at peak #{i}' assert pytest.approx(df_est['phase'].iloc[i], abs=1e-10) == df_params_brain_sim['phase'].iloc[i], \ f'Phase does not match at peak #{i}'
def test_sample_kbdm(data_brain_sim, dwell): m_range = range(100, 103, 1) line_lists, infos = sample_kbdm(data=data_brain_sim, dwell=dwell, m_range=m_range, p=1, l=None, q=0, filter_invalid_features=False) assert len(line_lists) == len(m_range) assert len(infos) == len(m_range) line_list_0_expected, info_expected = kbdm(data=data_brain_sim, dwell=dwell, m=m_range[0], p=1, l=None) assert line_lists[0] == pytest.approx(line_list_0_expected) assert infos[0].m == info_expected.m assert infos[0].l == info_expected.l assert infos[0].p == info_expected.p assert infos[0].q == info_expected.q assert infos[0].singular_values == pytest.approx( info_expected.singular_values)
def m_150_kbdm_line_list(data_brain_sim, dwell): line_list, _ = kbdm( data=data_brain_sim, dwell=dwell, m=150, ) return line_list
def test_kbdm_svd_with_q_greater_than_zero_should_use_tikhonov_regularization( data_brain_sim, dwell, caplog): caplog.set_level('DEBUG') m = 10 params_est, info = kbdm( data_brain_sim, dwell, m=m, q=1e-3, ) assert 'Using Tikhonov Regularization' in caplog.text assert params_est.shape == (m, 4) assert info.q == pytest.approx(1e-3) assert info.m == m
def test_kbdm_should_check_for_m_and_l_values(data_brain_sim, dwell): with pytest.raises(ValueError) as e_info: kbdm(data=data_brain_sim, dwell=dwell) assert "l or m must be specified" in str(e_info.value) with pytest.raises(ValueError) as e_info: kbdm(data=data_brain_sim, dwell=dwell, l=30, m=20) assert "l can't be greater than m" in str(e_info.value) _, info = kbdm(data=data_brain_sim, dwell=dwell, l=30) assert info.l == 30 assert info.m == 30 _, info = kbdm(data=data_brain_sim, dwell=dwell, m=30) assert info.l == 30 assert info.m == 30
def test_kbdm_invalid_m_n_p_constraint_should_raise_value_error( data_brain_sim, dwell): with pytest.raises(ValueError) as e_info: kbdm(data=data_brain_sim, dwell=dwell, m=int(len(data_brain_sim) / 2) + 1) assert "m or l can't be greater than (n + 1 - p)/2." in str(e_info.value) with pytest.raises(ValueError) as e_info: kbdm(data=data_brain_sim, dwell=dwell, l=int(len(data_brain_sim) / 2) + 1, m=int(len(data_brain_sim) / 2) + 1) with pytest.raises(ValueError) as e_info: kbdm(data=data_brain_sim, dwell=dwell, l=10, m=int(len(data_brain_sim) / 2) + 1) assert "m or l can't be greater than (n + 1 - p)/2." in str(e_info.value)
def sample_kbdm(data, dwell, m_range, p, l, q=0, filter_invalid_features=True): """ Compute samples of multiple computations of KBDM in a given range of m values. :param numpy.ndarray data: Complex input data. :param float dwell: Dwell time in seconds. :param list|range m_range: Range or list with number of columns/rows of U matrices for iteration of KBDM sampling. Its size must be greater than 2. :param str gep_solver: Method used to solve Generalized Eigenvalue Problem. Can be 'svd', for self-implemented solution; or scipy to use eig function from scipy.linalg.eig. Default is 'svd'. :param int p: Eigenvalue exponent of the generalized eigenvalue equation. It will represent a 'shift' during the construction of U^p and U^{p-1} matrices. :param int|TypeNone l: This is used only with if gep_solver is set to 'svd'. ..see:: llckbdm.kbdm._solve_gep_svd Default is None. :param float q: This is used only with if gep_solver is set to 'svd'. ..see:: llckbdm.kbdm._solve_gep_svd Default is 0. :param bool filter_invalid_features: Apply filter_samples on each sample. Default is True. :return: Tuple containing a list with obtained features for each value of m and respective dictionary containing KBDM computations meta-information. :rtype: tuple(list(numpy.array), dict) """ line_lists = [] infos = [] for m in m_range: logger.info(f'Computing KBDM with m = {m}') line_list, info = kbdm( data=data, dwell=dwell, m=m, p=p, l=l, q=q, ) if filter_invalid_features: line_list = filter_samples(line_list) if len(line_list) > 0: logger.debug(f'Empty line list') line_lists.append(line_list) infos.append(info) return line_lists, infos