def test_C2_watson_gamma_equals_gamma_watson():
    scheme = wu_minn_hcp_acquisition_scheme()

    cylinder = cylinder_models.C2CylinderStejskalTannerApproximation()
    watsoncyl = distribute_models.SD1WatsonDistributed([cylinder])

    gammawatsoncyl = distribute_models.DD1GammaDistributed(
        [watsoncyl],
        target_parameter='C2CylinderStejskalTannerApproximation_1_diameter')

    param_name = 'C2CylinderStejskalTannerApproximation_1_lambda_par'
    params1 = {
        'SD1WatsonDistributed_1_' + param_name: 1.7e-9,
        'DD1Gamma_1_alpha': 2.,
        'DD1Gamma_1_beta': 4e-6,
        'SD1WatsonDistributed_1_SD1Watson_1_odi': 0.4,
        'SD1WatsonDistributed_1_SD1Watson_1_mu': [0., 0.]
    }
    gammacyl = distribute_models.DD1GammaDistributed([cylinder])
    watsongammacyl = distribute_models.SD1WatsonDistributed([gammacyl])

    params2 = {
        'DD1GammaDistributed_1_' + param_name: 1.7e-9,
        'DD1GammaDistributed_1_DD1Gamma_1_alpha': 2.,
        'DD1GammaDistributed_1_DD1Gamma_1_beta': 4e-6,
        'SD1Watson_1_odi': 0.4,
        'SD1Watson_1_mu': [0., 0.]
    }

    assert_array_almost_equal(watsongammacyl(scheme, **params2),
                              gammawatsoncyl(scheme, **params1), 5)
def test_all_fitted_model_properties():
    stick = cylinder_models.C1Stick()
    watsonstick = distribute_models.SD1WatsonDistributed([stick])
    params = {}
    for parameter, card, in watsonstick.parameter_cardinality.items():
        params[parameter] = (np.random.rand(card) *
                             watsonstick.parameter_scales[parameter])
    data = np.atleast_2d(watsonstick(scheme, **params))

    mcmod = modeling_framework.MultiCompartmentModel([watsonstick])
    mcfit = mcmod.fit(scheme, data)

    vertices = np.random.rand(10, 3)
    vertices /= np.linalg.norm(vertices, axis=1)[:, None]

    assert_(isinstance(mcfit.fitted_parameters, dict))
    assert_(isinstance(mcfit.fitted_parameters_vector, np.ndarray))
    assert_(isinstance(mcfit.fod(vertices), np.ndarray))
    assert_(isinstance(mcfit.fod_sh(), np.ndarray))
    assert_(isinstance(mcfit.peaks_spherical(), np.ndarray))
    assert_(isinstance(mcfit.peaks_cartesian(), np.ndarray))
    assert_(isinstance(mcfit.mean_squared_error(data), np.ndarray))
    assert_(isinstance(mcfit.R2_coefficient_of_determination(data),
                       np.ndarray))
    assert_(isinstance(mcfit.predict(), np.ndarray))

    mcmod_sm = modeling_framework.MultiCompartmentSphericalMeanModel([stick])
    mcfit_sm = mcmod_sm.fit(scheme, data)
    assert_(isinstance(mcfit_sm.fitted_parameters, dict))
    assert_(isinstance(mcfit_sm.fitted_parameters_vector, np.ndarray))
    assert_(isinstance(mcfit.mean_squared_error(data), np.ndarray))
    assert_(isinstance(mcfit.R2_coefficient_of_determination(data),
                       np.ndarray))
    assert_(isinstance(mcfit.predict(), np.ndarray))
Beispiel #3
0
def test_equivalence_csd_and_parametric_fod(
        odi=0.15, mu=[0., 0.], lambda_par=1.7e-9):
    stick = cylinder_models.C1Stick()
    watsonstick = distribute_models.SD1WatsonDistributed(
        [stick])

    params = {'SD1Watson_1_odi': odi,
              'SD1Watson_1_mu': mu,
              'C1Stick_1_lambda_par': lambda_par}

    data = watsonstick(scheme, **params)

    sh_mod = modeling_framework.MultiCompartmentSphericalHarmonicsModel(
        [stick])
    sh_mod.set_fixed_parameter('C1Stick_1_lambda_par', lambda_par)

    sh_fit = sh_mod.fit(scheme, data)
    fod = sh_fit.fod(sphere.vertices)

    watson = distributions.SD1Watson(mu=[0., 0.], odi=0.15)
    sf = watson(sphere.vertices)
    assert_array_almost_equal(fod[0], sf, 2)

    fitted_signal = sh_fit.predict()
    assert_array_almost_equal(data, fitted_signal[0], 4)
Beispiel #4
0
def test_multi_compartment_fod_with_parametric_model(
        odi=0.15, mu=[0., 0.], lambda_iso=3e-9, lambda_par=1.7e-9,
        vf_intra=0.7):
    stick = cylinder_models.C1Stick()
    ball = gaussian_models.G1Ball()
    watsonstick = distribute_models.SD1WatsonDistributed(
        [stick])
    mc_mod = modeling_framework.MultiCompartmentModel([watsonstick, ball])

    sh_mod = modeling_framework.MultiCompartmentSphericalHarmonicsModel(
        [stick, ball])
    sh_mod.set_fixed_parameter('G1Ball_1_lambda_iso', lambda_iso)
    sh_mod.set_fixed_parameter('C1Stick_1_lambda_par', lambda_par)

    simulation_parameters = mc_mod.parameters_to_parameter_vector(
        G1Ball_1_lambda_iso=lambda_iso,
        SD1WatsonDistributed_1_SD1Watson_1_mu=mu,
        SD1WatsonDistributed_1_C1Stick_1_lambda_par=lambda_par,
        SD1WatsonDistributed_1_SD1Watson_1_odi=odi,
        partial_volume_0=vf_intra,
        partial_volume_1=1 - vf_intra)
    data = mc_mod.simulate_signal(scheme, simulation_parameters)

    sh_fit = sh_mod.fit(scheme, data)

    vf_intra_estimated = sh_fit.fitted_parameters['partial_volume_0']
    assert_almost_equal(vf_intra, vf_intra_estimated)

    predicted_signal = sh_fit.predict()

    assert_array_almost_equal(data, predicted_signal[0], 4)
Beispiel #5
0
def test_laplacian_and_AI_with_regularization(odi=0.15,
                                              mu=[0., 0.],
                                              lambda_par=1.7e-9):
    stick = cylinder_models.C1Stick()
    watsonstick = distribute_models.SD1WatsonDistributed([stick])
    params = {
        'SD1Watson_1_odi': odi,
        'SD1Watson_1_mu': mu,
        'C1Stick_1_lambda_par': lambda_par
    }
    data = watsonstick(scheme, **params)

    sh_mod = modeling_framework.MultiCompartmentSphericalHarmonicsModel(
        [stick])
    sh_mod.set_fixed_parameter('C1Stick_1_lambda_par', lambda_par)

    for solver in ['csd_tournier07', 'csd_cvxpy']:
        sh_fit = sh_mod.fit(scheme, data, solver=solver, lambda_lb=0.)
        sh_fit_reg = sh_mod.fit(scheme, data, solver=solver, lambda_lb=1e-3)
        ai = sh_fit.anisotropy_index()
        lb = sh_fit.norm_of_laplacian_fod()
        ai_reg = sh_fit_reg.anisotropy_index()
        lb_reg = sh_fit_reg.norm_of_laplacian_fod()
        assert_(ai > ai_reg)
        assert_(lb > lb_reg)
Beispiel #6
0
def test_spherical_harmonics_model_raises(odi=0.15,
                                          mu=[0., 0.],
                                          lambda_par=1.7e-9):
    stick = cylinder_models.C1Stick()
    ball = gaussian_models.G1Ball()
    watsonstick = distribute_models.SD1WatsonDistributed([stick])

    params = {
        'SD1Watson_1_odi': odi,
        'SD1Watson_1_mu': mu,
        'C1Stick_1_lambda_par': lambda_par
    }
    data = watsonstick(scheme, **params)

    assert_raises(ValueError,
                  modeling_framework.MultiCompartmentSphericalHarmonicsModel,
                  [ball])

    sh_mod = modeling_framework.MultiCompartmentSphericalHarmonicsModel(
        [stick])
    assert_raises(ValueError, sh_mod.fit, scheme, data, solver='csd_cvxpy')

    sh_mod = modeling_framework.MultiCompartmentSphericalHarmonicsModel(
        [stick, ball])
    sh_mod.set_fixed_parameter('C1Stick_1_lambda_par', lambda_par)
    sh_mod.set_fixed_parameter('G1Ball_1_lambda_iso', 3e-9)
    assert_raises(ValueError,
                  sh_mod.fit,
                  scheme,
                  data,
                  solver='csd_tournier07')
def test_set_fixed_parameter_raises():
    cyl = cylinder_models.C1Stick()
    distcyl = distribute_models.SD1WatsonDistributed([cyl])
    assert_raises(ValueError, distcyl.set_fixed_parameter, 'SD1Watson_1_odi',
                  [1])
    assert_raises(ValueError, distcyl.set_fixed_parameter, 'SD1Watson_1_mu',
                  [1])
    assert_raises(ValueError, distcyl.set_fixed_parameter, 'blabla', [1])
Beispiel #8
0
def test_set_equal_param():
    cylinder = cylinder_models.C2CylinderStejskalTannerApproximation()
    watsoncyl = distribute_models.SD1WatsonDistributed([cylinder])
    p1 = 'C2CylinderStejskalTannerApproximation_1_lambda_par'
    p2 = 'C2CylinderStejskalTannerApproximation_1_diameter'
    watsoncyl.set_equal_parameter(p1, p2)

    isnone = False
    reset = watsoncyl.set_equal_parameter(p1, p2)
    if reset is None:
        isnone = True

    assert_equal(isnone, True)
Beispiel #9
0
def test_C4_watson_gamma_equals_gamma_watson():
    scheme = wu_minn_hcp_acquisition_scheme()

    cylinder = cylinder_models.C4CylinderGaussianPhaseApproximation()
    watsoncyl = distribute_models.SD1WatsonDistributed([cylinder])

    gammawatsoncyl = distribute_models.DD1GammaDistributed(
        [watsoncyl],
        target_parameter='C4CylinderGaussianPhaseApproximation_1_diameter')

    param = 'SD1WatsonDistributed_1_C4CylinderGaussianPhaseApproximation'
    param += '_1_lambda_par'

    params1 = {
        param: 1.7e-9,
        'DD1Gamma_1_alpha': 2.,
        'DD1Gamma_1_beta': 4e-6,
        'SD1WatsonDistributed_1_SD1Watson_1_odi': 0.4,
        'SD1WatsonDistributed_1_SD1Watson_1_mu': [0., 0.]
    }
    gammacyl = distribute_models.DD1GammaDistributed([cylinder])
    watsongammacyl = distribute_models.SD1WatsonDistributed(
        [gammacyl],
        target_parameter='C4CylinderGaussianPhaseApproximation_1_mu')

    param = 'DD1GammaDistributed_1_C4CylinderGaussianPhaseApproximation'
    param += '_1_lambda_par'

    params2 = {
        param: 1.7e-9,
        'DD1GammaDistributed_1_DD1Gamma_1_alpha': 2.,
        'DD1GammaDistributed_1_DD1Gamma_1_beta': 4e-6,
        'SD1Watson_1_odi': 0.4,
        'SD1Watson_1_mu': [0., 0.]
    }

    assert_array_almost_equal(watsongammacyl(scheme, **params2),
                              gammawatsoncyl(scheme, **params1), 5)
Beispiel #10
0
def test_equivalence_sh_distributed_mc_with_mcsh():
    """
    We test if we can input a Watson-distributed zeppelin and stick into an
    SD3SphericalHarmonicsDistributedModel in an MC-model, and compare it with
    an MCSH model with the same watson distribution as a kernel.
    """
    stick = cylinder_models.C1Stick()
    zep = gaussian_models.G2Zeppelin()

    mck_dist = distribute_models.SD1WatsonDistributed([stick, zep])
    mck_dist.set_equal_parameter('G2Zeppelin_1_lambda_par',
                                 'C1Stick_1_lambda_par')
    mck_dist.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
                                    'G2Zeppelin_1_lambda_par',
                                    'partial_volume_0')

    mcsh = modeling_framework.MultiCompartmentSphericalHarmonicsModel(
        models=[mck_dist], sh_order=8)
    mc = modeling_framework.MultiCompartmentModel([
        distribute_models.SD3SphericalHarmonicsDistributed([mck_dist],
                                                           sh_order=8)
    ])

    lambda_par = 0.
    odi = .02
    sh_coeff = np.ones(45)
    sh_coeff[0] = 1 / (2 * np.sqrt(np.pi))
    pv0 = .3

    params_mcsh = {
        'SD1WatsonDistributed_1_partial_volume_0': pv0,
        'SD1WatsonDistributed_1_G2Zeppelin_1_lambda_par': lambda_par,
        'SD1WatsonDistributed_1_SD1Watson_1_odi': odi,
        'sh_coeff': sh_coeff
    }

    basemod = 'SD3SphericalHarmonicsDistributed_1_'
    params_mc = {
        basemod + 'SD1WatsonDistributed_1_partial_volume_0': pv0,
        basemod + 'SD1WatsonDistributed_1_G2Zeppelin_1_lambda_par': lambda_par,
        basemod + 'SD1WatsonDistributed_1_SD1Watson_1_odi': odi,
        basemod + 'SD3SphericalHarmonics_1_sh_coeff': sh_coeff
    }

    E_mcsh = mcsh.simulate_signal(scheme, params_mcsh)
    E_mc = mc.simulate_signal(scheme, params_mc)

    np.testing.assert_array_almost_equal(E_mcsh, E_mc)
Beispiel #11
0
def test_construction_observation_matrix(
        odi=0.15, mu=[0., 0.], lambda_par=1.7e-9, lmax=8):
    stick = cylinder_models.C1Stick(lambda_par=lambda_par)
    watsonstick = distribute_models.SD1WatsonDistributed(
        [stick])

    params = {'SD1Watson_1_odi': odi,
              'SD1Watson_1_mu': mu,
              'C1Stick_1_lambda_par': lambda_par}

    data = watsonstick(scheme, **params)
    watson = distributions.SD1Watson(mu=mu, odi=odi)
    sh_watson = watson.spherical_harmonics_representation(lmax)

    stick_rh = stick.rotational_harmonics_representation(scheme)
    A = construct_model_based_A_matrix(scheme, stick_rh, lmax)

    data_approximated = A.dot(sh_watson)
    np.testing.assert_array_almost_equal(data_approximated, data, 4)
Beispiel #12
0
def _make_single_and_crossing():
    zeppelin = G2Zeppelin(lambda_par=1.7e-9, lambda_perp=1e-9, mu=[0., 0.])
    data_aniso = zeppelin(scheme)
    S0_aniso, aniso_model = estimate_TR2_anisotropic_tissue_response_model(
        scheme, np.atleast_2d(data_aniso))

    watson_mod = distribute_models.SD1WatsonDistributed([aniso_model])
    watson_params_par = {
        'SD1Watson_1_mu': np.array([0., 0.]),
        'SD1Watson_1_odi': .2
    }
    watson_params_perp = {
        'SD1Watson_1_mu': np.array([np.pi / 2., np.pi / 2.]),
        'SD1Watson_1_odi': .2
    }
    data_watson_par = watson_mod(scheme, **watson_params_par)
    data_watson_perp = watson_mod(scheme, **watson_params_perp)

    data_cross = np.array(
        [data_watson_par, data_watson_par + data_watson_perp])
    return data_cross
Beispiel #13
0
def test_watson_dispersed_stick_tortuous_zeppelin():
    stick = cylinder_models.C1Stick()
    zeppelin = gaussian_models.G2Zeppelin()

    watson_bundle = distribute_models.SD1WatsonDistributed(
        models=[stick, zeppelin])

    watson_bundle.set_tortuous_parameter(
        'G2Zeppelin_1_lambda_perp',
        'G2Zeppelin_1_lambda_par',
        'partial_volume_0'
    )

    watson_bundle.set_equal_parameter(
        'G2Zeppelin_1_lambda_par',
        'C1Stick_1_lambda_par')

    watson_bundle.set_fixed_parameter(
        'G2Zeppelin_1_lambda_par', 1.7e-9)

    mc_watson = (
        modeling_framework.MultiCompartmentModel(
            models=[watson_bundle])
    )

    beta0 = camino_dispersed.beta == 0.
    diff17 = camino_dispersed.diffusivities == 1.7e-9
    mask = np.all([beta0, diff17], axis=0)
    E_watson = camino_dispersed.signal_attenuation[mask]
    fractions_watson = camino_dispersed.fractions[mask]

    fitted_params = (
        mc_watson.fit(scheme, E_watson[::20]).fitted_parameters
    )

    mean_abs_error = np.mean(
        abs(fitted_params['SD1WatsonDistributed_1_partial_volume_0'].squeeze(
        ) - fractions_watson[::20]))
    assert_equal(mean_abs_error < 0.03, True)
def test_parametric_fod_spherical_mean_model():
    stick = cylinder_models.C1Stick()
    watsonstick = distribute_models.SD1WatsonDistributed([stick])
    params = {}
    for parameter, card, in watsonstick.parameter_cardinality.items():
        params[parameter] = (np.random.rand(card) *
                             watsonstick.parameter_scales[parameter])
    data = np.atleast_2d(watsonstick(scheme, **params))

    stick = cylinder_models.C1Stick()
    zeppelin = gaussian_models.G2Zeppelin()
    smt = modeling_framework.MultiCompartmentSphericalMeanModel(
        [stick, zeppelin])
    smt.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
                               'C1Stick_1_lambda_par', 'partial_volume_0',
                               'partial_volume_1')
    smt.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par')

    smt_fit = smt.fit(scheme, data)

    assert_raises(ValueError,
                  smt_fit.return_parametric_fod_model,
                  Ncompartments=1.5)

    assert_raises(ValueError,
                  smt_fit.return_parametric_fod_model,
                  Ncompartments=0)

    assert_raises(ValueError,
                  smt_fit.return_parametric_fod_model,
                  distribution='bla')

    for distribution_name in ['watson', 'bingham']:
        fod_model = smt_fit.return_parametric_fod_model(
            distribution=distribution_name, Ncompartments=1)
        fitted_fod_model = fod_model.fit(scheme, data)
        assert_(isinstance(fitted_fod_model.fitted_parameters, dict))
def test_tissue_response_model_multi_compartment_models():
    ball = G1Ball(lambda_iso=2.5e-9)
    data_iso = ball(scheme)
    data_iso_sm = ball.spherical_mean(scheme)
    S0_iso, iso_model = estimate_TR1_isotropic_tissue_response_model(
        scheme, np.atleast_2d(data_iso))

    zeppelin = G2Zeppelin(lambda_par=1.7e-9,
                          lambda_perp=1e-9,
                          mu=[np.pi / 2, np.pi / 2])
    data_aniso = zeppelin(scheme)
    data_aniso_sm = zeppelin.spherical_mean(scheme)
    S0_aniso, aniso_model = estimate_TR2_anisotropic_tissue_response_model(
        scheme, np.atleast_2d(data_aniso))
    models = [iso_model, aniso_model]

    mc = MultiCompartmentModel(models)
    mc_smt = MultiCompartmentSphericalMeanModel(models)

    test_mc_data = 0.5 * data_iso + 0.5 * data_aniso
    test_mc_data_sm = 0.5 * data_iso_sm + 0.5 * data_aniso_sm
    test_data = [test_mc_data, test_mc_data_sm]

    params = {
        'partial_volume_0': [0.5],
        'partial_volume_1': [0.5],
        'TR2AnisotropicTissueResponseModel_1_mu':
        np.array([np.pi / 2, np.pi / 2])
    }

    mc_models = [mc, mc_smt]
    for model, data in zip(mc_models, test_data):
        data_mc = model(scheme, **params)
        assert_array_almost_equal(data, data_mc, 3)

    # csd model with single models
    mc_csd = MultiCompartmentSphericalHarmonicsModel([aniso_model])
    watson_mod = distribute_models.SD1WatsonDistributed([aniso_model])
    watson_params = {
        'SD1Watson_1_mu': np.array([np.pi / 2, np.pi / 2]),
        'SD1Watson_1_odi': .3
    }
    data_watson = watson_mod(scheme, **watson_params)
    mc_csd_fit = mc_csd.fit(scheme, data_watson)
    assert_array_almost_equal(mc_csd_fit.predict()[0], data_watson, 2)

    # csd model with multiple models
    mc_csd = MultiCompartmentSphericalHarmonicsModel(models)
    watson_mod = distribute_models.SD1WatsonDistributed(
        [iso_model, aniso_model])
    watson_params = {
        'SD1Watson_1_mu': np.array([np.pi / 2, np.pi / 2]),
        'SD1Watson_1_odi': .3,
        'partial_volume_0': 0.5
    }
    data_watson = watson_mod(scheme, **watson_params)
    mc_csd_fit = mc_csd.fit(scheme, data_watson)
    assert_array_almost_equal(mc_csd_fit.predict()[0], data_watson, 2)

    scheme_panagiotaki = panagiotaki_verdict_acquisition_scheme()
    assert_raises(ValueError,
                  mc_csd.fit,
                  acquisition_scheme=scheme_panagiotaki,
                  data=data_watson)
Beispiel #16
0
def test_raise_spherical_distribution_in_spherical_mean():
    zeppelin = gaussian_models.G2Zeppelin()
    watson = distribute_models.SD1WatsonDistributed([zeppelin])
    assert_raises(ValueError,
                  modeling_framework.MultiCompartmentSphericalMeanModel,
                  [watson])
Beispiel #17
0
def test_multi_voxel_parametric_to_sm_to_sh_fod_watson():
    stick = cylinder_models.C1Stick()
    zeppelin = gaussian_models.G2Zeppelin()
    watsonstick = distribute_models.SD1WatsonDistributed([stick, zeppelin])

    watsonstick.set_equal_parameter('G2Zeppelin_1_lambda_par',
                                    'C1Stick_1_lambda_par')
    watsonstick.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
                                       'G2Zeppelin_1_lambda_par',
                                       'partial_volume_0')
    mc_mod = modeling_framework.MultiCompartmentModel([watsonstick])

    parameter_dict = {
        'SD1WatsonDistributed_1_SD1Watson_1_mu':
        np.random.rand(10, 2),
        'SD1WatsonDistributed_1_partial_volume_0':
        np.linspace(0.1, 0.9, 10),
        'SD1WatsonDistributed_1_G2Zeppelin_1_lambda_par':
        np.linspace(1.5, 2.5, 10) * 1e-9,
        'SD1WatsonDistributed_1_SD1Watson_1_odi':
        np.linspace(0.3, 0.7, 10)
    }

    data = mc_mod.simulate_signal(scheme, parameter_dict)

    sm_mod = modeling_framework.MultiCompartmentSphericalMeanModel(
        [stick, zeppelin])
    sm_mod.set_equal_parameter('G2Zeppelin_1_lambda_par',
                               'C1Stick_1_lambda_par')
    sm_mod.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
                                  'G2Zeppelin_1_lambda_par',
                                  'partial_volume_0', 'partial_volume_1')

    sf_watson = []
    for mu, odi in zip(
            parameter_dict['SD1WatsonDistributed_1_SD1Watson_1_mu'],
            parameter_dict['SD1WatsonDistributed_1_SD1Watson_1_odi']):
        watson = distributions.SD1Watson(mu=mu, odi=odi)
        sf_watson.append(watson(sphere.vertices))
    sf_watson = np.array(sf_watson)

    sm_fit = sm_mod.fit(scheme, data)
    sh_mod = sm_fit.return_spherical_harmonics_fod_model()

    sh_fit_auto = sh_mod.fit(scheme, data)  # will pick tournier
    fod_tournier = sh_fit_auto.fod(sphere.vertices)
    assert_array_almost_equal(fod_tournier, sf_watson, 1)

    sh_fit_tournier = sh_mod.fit(scheme,
                                 data,
                                 solver='csd_tournier07',
                                 unity_constraint=False)
    fod_tournier = sh_fit_tournier.fod(sphere.vertices)
    assert_array_almost_equal(fod_tournier, sf_watson, 1)

    sh_fit_cvxpy = sh_mod.fit(scheme,
                              data,
                              solver='csd_cvxpy',
                              unity_constraint=True,
                              lambda_lb=0.)
    fod_cvxpy = sh_fit_cvxpy.fod(sphere.vertices)
    assert_array_almost_equal(fod_cvxpy, sf_watson, 2)

    sh_fit_cvxpy = sh_mod.fit(scheme,
                              data,
                              solver='csd_cvxpy',
                              unity_constraint=False,
                              lambda_lb=0.)
    fod_cvxpy = sh_fit_cvxpy.fod(sphere.vertices)
    assert_array_almost_equal(fod_cvxpy, sf_watson, 2)