Example #1
0
def f_model_example():
    """ This example illustrates the use of the f_model class"""

    # make up some structure factors
    random_structure = rs.xray_structure(sgtbx.space_group_info('P1'),
                                         elements=['C'] * 310,
                                         n_scatterers=310)

    # here f_atoms, f_mask and f_part are all the same
    # doens't make sense of course
    sfs = random_structure.structure_factors(
        False,
        3.5,
    ).f_calc()
    f_model_structure_factors = xray.f_model_core_data(
        hkl=sfs.indices(),
        f_atoms=sfs.data(),
        f_mask=sfs.data(),
        unit_cell=sfs.unit_cell(),
        k_overall=1.0,
        u_star=(0, 0, 0, 0, 0, 0),
        k_sol=1.0,
        u_sol=1.0,
        f_part=None,
        k_part=0,
        u_part=0)

    #Resetting model parameters
    #
    # over all scale parameters; scale and aniso Ustar
    f_model_structure_factors.renew_overall_scale_parameters(
        3.0, (0, 0, 0, 0, 0, 0))
    # bulk solvent scale parameters; scale and B
    f_model_structure_factors.renew_bulk_solvent_scale_parameters(0.55, 50.0)
    # partial structure scale parameters; scale and B
    f_model_structure_factors.renew_partial_structure_scale_parameters(
        0.05, 25.0)

    # is is also possible to reset the values term by term ratrher then grouped
    f_model_structure_factors.ksol(1.0)
    f_model_structure_factors.usol(3.0)
    f_model_structure_factors.kpart(1.0)
    f_model_structure_factors.upart(3.0)
    f_model_structure_factors.koverall(1.0)
    f_model_structure_factors.ustar((0, 0, 0, 0, 0, 0))
    # the cached arrays of various scale factor as updated automatically.

    # Obtaining the current parameters
    ksol = f_model_structure_factors.ksol()
    bsol = f_model_structure_factors.usol()
    kpart = f_model_structure_factors.kpart()
    bpart = f_model_structure_factors.upart()
    koverall = f_model_structure_factors.koverall()
    ustar = f_model_structure_factors.ustar()

    # Derivatives
    #
    #
    #derivates can be obtained accumalated over the full dataset
    # or on a struct term by term bases
    #what is needed in any case are one of the following arrays or floats
    # - d(target)/d(|F_model|)
    # - d(target)/d(Re[F_model]), d(target)/d(Im[F_model])
    #
    # which derivates are computed, is controlled by an array of gradient flags:
    # the order is (koverall, ustar, ksol, bsol, kpart, bpart )
    #
    gradient_flags = flex.bool([True, True, True, True, True, True])
    #
    # Use this function call is your target function returns
    # d(target)/d(|Fmodel|)
    dt_dabsfmodel = flex.double(sfs.data().size(), 1)
    dtdall = f_model_structure_factors.d_target_d_all(dt_dabsfmodel,
                                                      gradient_flags)

    # Use this function call is your target function returns
    # d(target)/d(Re[Fmodel]), d(target)/d(Im[Fmodel])
    dtda = dt_dabsfmodel
    dtdb = dt_dabsfmodel

    dtdall = f_model_structure_factors.d_target_d_all(dtda, dtdb,
                                                      gradient_flags)
    # if desired (likely in c++, not in python) you can do it term by term.
    hkl_no = 123
    dtdsingle = f_model_structure_factors.d_target_d_all(
        dtda[hkl_no], dtdb[hkl_no], hkl_no, gradient_flags)

    # the resulting gradients are delivered as a
    # 'f_model_derivative_holder'
    # it has methods both to set as well as to get items.
    #
    # getting the values
    tmp = dtdsingle.koverall()
    tmp = dtdsingle.ustar()
    tmp = dtdsingle.ksol()
    tmp = dtdsingle.usol()
    tmp = dtdsingle.kpart()
    tmp = dtdsingle.upart()
    #
    # if desired, you can set values as well
    dtdsingle.koverall(1)
    dtdsingle.ustar((1, 1, 1, 1, 1, 1))
    dtdsingle.ksol(1)
    dtdsingle.usol(1)
    dtdsingle.kpart(1)
    dtdsingle.upart(1)

    #if desired, a selection can be made on the f_model object.
    #currently, only an integer selection is supported
    new_f_model_object = f_model_structure_factors.select(flex.int([1, 2, 3]))
    assert new_f_model_object.f_model().size() == 3
Example #2
0
def tst_f_model(this_hkl=123):
    tmp = rs.xray_structure(sgtbx.space_group_info('P1'),
                            elements=['C'] * 310,
                            n_scatterers=310)

    sfs = tmp.structure_factors(
        False,
        3.5,
    ).f_calc()
    f_mod = xray.f_model_core_data(hkl=sfs.indices(),
                                   f_atoms=sfs.data(),
                                   f_mask=sfs.data(),
                                   unit_cell=sfs.unit_cell(),
                                   k_overall=1.0,
                                   u_star=(0, 0, 0, 0, 0, 0),
                                   k_sol=1.0,
                                   u_sol=1.0,
                                   f_part=sfs.data(),
                                   k_part=1.0,
                                   u_part=1.0)

    data1 = sfs.data()[this_hkl]
    hkl1 = sfs.indices()[this_hkl]

    fbulk = f_mod.f_bulk()[this_hkl]
    fatoms = f_mod.f_atoms()[this_hkl]
    fpart = f_mod.f_part()[this_hkl]
    fmod = f_mod.f_model()[this_hkl]
    # we have unit scale now
    assert approx_equal(fmod, fbulk + fatoms + fpart)
    # get derivatives please
    #
    # make a mock target function: T=A^2 + B^2
    # dT/dF=2F
    # dT/dA=2A
    # dT/dB=2B
    f_model_data_complex = f_mod.f_model()
    fm = flex.double()
    a = flex.double()
    b = flex.double()

    for cmplx in f_model_data_complex:
        tmp_a = cmplx.real
        tmp_b = cmplx.imag
        fm.append(math.sqrt(tmp_a * tmp_a + tmp_b * tmp_b))
        a.append(tmp_a)
        b.append(tmp_b)

    dtdf = 2.0 * fm
    dtda = 2.0 * a
    dtdb = 2.0 * b

    gradient_flags = flex.bool([True, True, True, True, True, True])

    grads_f = f_mod.d_target_d_all(dtdf, gradient_flags)
    grads_ab = f_mod.d_target_d_all(dtda, dtdb, gradient_flags)
    compare_all(grads_ab, grads_f)

    f_mod = xray.f_model_core_data(hkl=sfs.indices(),
                                   f_atoms=sfs.data(),
                                   f_mask=sfs.data() * 0.0,
                                   unit_cell=sfs.unit_cell(),
                                   k_overall=1.0,
                                   u_star=(0, 0, 0, 0, 0, 0),
                                   k_sol=0.0,
                                   u_sol=0.0,
                                   f_part=sfs.data() * 0.0,
                                   k_part=0.0,
                                   u_part=0.0)
    f_mod.refresh()
    grad_123 = f_mod.d_target_d_all(0, 1, this_hkl, gradient_flags)
    assert approx_equal(grad_123.koverall(),
                        f_mod.f_model()[this_hkl].imag / f_mod.koverall())
    tps = 19.7392088  # 2 pi^2
    h = hkl1[0]
    k = hkl1[1]
    l = hkl1[2]
    assert approx_equal(-2 * tps * h * h * f_mod.f_model()[this_hkl].imag,
                        grad_123.ustar()[0])
    assert approx_equal(-2 * tps * k * k * f_mod.f_model()[this_hkl].imag,
                        grad_123.ustar()[1])
    assert approx_equal(-2 * tps * l * l * f_mod.f_model()[this_hkl].imag,
                        grad_123.ustar()[2])
    assert approx_equal(-4 * tps * h * k * f_mod.f_model()[this_hkl].imag,
                        grad_123.ustar()[3])
    assert approx_equal(-4 * tps * h * l * f_mod.f_model()[this_hkl].imag,
                        grad_123.ustar()[4])
    assert approx_equal(-4 * tps * k * l * f_mod.f_model()[this_hkl].imag,
                        grad_123.ustar()[5])

    grad_123 = f_mod.d_target_d_all(1, 0, this_hkl, gradient_flags)
    assert approx_equal(grad_123.koverall(),
                        f_mod.f_model()[this_hkl].real / f_mod.koverall())
    tps = 19.7392088
    h = hkl1[0]
    k = hkl1[1]
    l = hkl1[2]
    assert approx_equal(-2 * tps * h * h * f_mod.f_model()[this_hkl].real,
                        grad_123.ustar()[0])
    assert approx_equal(-2 * tps * k * k * f_mod.f_model()[this_hkl].real,
                        grad_123.ustar()[1])
    assert approx_equal(-2 * tps * l * l * f_mod.f_model()[this_hkl].real,
                        grad_123.ustar()[2])
    assert approx_equal(-4 * tps * h * k * f_mod.f_model()[this_hkl].real,
                        grad_123.ustar()[3])
    assert approx_equal(-4 * tps * h * l * f_mod.f_model()[this_hkl].real,
                        grad_123.ustar()[4])
    assert approx_equal(-4 * tps * k * l * f_mod.f_model()[this_hkl].real,
                        grad_123.ustar()[5])

    oldfm = xray.f_model_core_data(hkl=sfs.indices(),
                                   f_atoms=sfs.data(),
                                   f_mask=sfs.data() * 1.0,
                                   unit_cell=sfs.unit_cell(),
                                   k_overall=1.0,
                                   u_star=(0, 0, 0, 0, 0, 0),
                                   k_sol=1.0,
                                   u_sol=1.0,
                                   f_part=sfs.data() * 1.0,
                                   k_part=1.0,
                                   u_part=1.0)
    h = 0.0001

    newfm = xray.f_model_core_data(hkl=sfs.indices(),
                                   f_atoms=sfs.data(),
                                   f_mask=sfs.data() * 1.0,
                                   unit_cell=sfs.unit_cell(),
                                   k_overall=1.0,
                                   u_star=(0, 0, 0, 0, 0, 0),
                                   k_sol=1.0,
                                   u_sol=1.0,
                                   f_part=sfs.data() * 1.0,
                                   k_part=1.0,
                                   u_part=1.0)

    newfm.renew_overall_scale_parameters(1.0 + h, (0, 0, 0, 0, 0, 0))
    newfm.refresh()

    tmp = oldfm.d_target_d_all(1, 0, this_hkl, gradient_flags).koverall()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).real
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_overall_scale_parameters(1, (0, 0, 0, 0, 0, 0))

    newfm.renew_bulk_solvent_scale_parameters(1 + h, 1.0)
    tmp = oldfm.d_target_d_all(1, 0, this_hkl, gradient_flags).ksol()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).real
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1, 1.0)

    newfm.renew_bulk_solvent_scale_parameters(1.0, 1.0 + h)
    tmp = oldfm.d_target_d_all(1, 0, this_hkl, gradient_flags).usol()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).real
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1.0, 1.0)

    newfm.renew_bulk_solvent_scale_parameters(1 + h, 1.0)
    tmp = oldfm.d_target_d_all(0, 1, this_hkl, gradient_flags).ksol()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).imag
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1, 1.0)

    newfm.renew_bulk_solvent_scale_parameters(1.0, 1.0 + h)
    tmp = oldfm.d_target_d_all(0, 1, this_hkl, gradient_flags).usol()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).imag
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1.0, 1.0)

    newfm.renew_partial_structure_scale_parameters(1 + h, 1.0)
    tmp = oldfm.d_target_d_all(1, 0, this_hkl, gradient_flags).kpart()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).real
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1, 1.0)

    newfm.renew_partial_structure_scale_parameters(1.0, 1.0 + h)
    tmp = oldfm.d_target_d_all(1, 0, this_hkl, gradient_flags).upart()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).real
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1.0, 1.0)

    newfm.renew_partial_structure_scale_parameters(1 + h, 1.0)
    tmp = oldfm.d_target_d_all(0, 1, this_hkl, gradient_flags).kpart()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).imag
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1, 1.0)

    newfm.renew_partial_structure_scale_parameters(1.0, 1.0 + h)
    tmp = oldfm.d_target_d_all(0, 1, this_hkl, gradient_flags).upart()
    tmp_d = ((oldfm.f_model()[this_hkl] - newfm.f_model()[this_hkl]) /
             (-h)).imag
    assert approx_equal(tmp, tmp_d, eps=1e-2)
    newfm.renew_bulk_solvent_scale_parameters(1.0, 1.0)
Example #3
0
def tst_ls_on_i():
    tmp = rs.xray_structure(sgtbx.space_group_info('P4'),
                            elements=['C'] * 310,
                            n_scatterers=310)

    sfs = tmp.structure_factors(False, 3.5).f_calc()
    f_mod = xray.f_model_core_data(hkl=sfs.indices(),
                                   f_atoms=sfs.data(),
                                   f_mask=sfs.data(),
                                   unit_cell=sfs.unit_cell(),
                                   k_overall=1.0,
                                   u_star=(0, 0, 0, 0, 0, 0),
                                   k_sol=0.0,
                                   u_sol=0.0,
                                   f_part=sfs.data(),
                                   k_part=0.0,
                                   u_part=0.0)

    target_evaluator = xray.least_squares_hemihedral_twinning_on_i(
        hkl_obs=sfs.indices(),
        i_obs=(flex.abs(sfs.data()) * flex.abs(sfs.data())) * 1.0,
        w_obs=None,
        hkl_calc=sfs.indices(),
        space_group=sfs.space_group(),
        anomalous_flag=False,
        alpha=0.0,
        twin_law=[-1, 0, 0, 0, 1, 0, 0, 0, -1])

    target = target_evaluator.target(sfs.data())
    # The target vaslue should be zero
    assert approx_equal(target, 0, eps=1e-6)

    # the derivatives as well
    derivs_complex = target_evaluator.d_target_d_fmodel(sfs.data())
    derivs_ab = target_evaluator.d_target_d_ab(sfs.data())
    for cmplx, da, db in zip(derivs_complex, derivs_ab[0], derivs_ab[1]):
        assert approx_equal(cmplx.real, da, eps=1e-5)
        assert approx_equal(cmplx.imag, db, eps=1e-5)

    for alpha in flex.double(range(50)) / 100.0:
        #----------------------------------------------------------------
        # use fin diffs to check the derivatives to a and b
        old_target_evaluator = xray.least_squares_hemihedral_twinning_on_i(
            hkl_obs=sfs.indices(),
            i_obs=(flex.abs(sfs.data()) * flex.abs(sfs.data())) * 1.1,
            w_obs=None,
            hkl_calc=sfs.indices(),
            space_group=sfs.space_group(),
            anomalous_flag=False,
            alpha=alpha,
            twin_law=[-1, 0, 0, 0, 1, 0, 0, 0, -1])
        old_target_value = old_target_evaluator.target(sfs.data())
        old_derivs = old_target_evaluator.d_target_d_ab(sfs.data())

        new_data = sfs.data()
        h = 0.0001

        for N_test in range(sfs.data().size()):
            ori = complex(sfs.data()[N_test])
            #print "----------------"
            #print alpha
            #print sfs.indices()[N_test]
            #print sfs.data()[N_test]
            new_data[N_test] = ori + complex(h, 0)
            new_target_value = old_target_evaluator.target(new_data)
            fdif_real = float((new_target_value - old_target_value) / h)
            new_data[N_test] = ori + complex(0, h)
            new_target_value = old_target_evaluator.target(new_data)
            fdif_imag = float((new_target_value - old_target_value) / h)
            # only use 'large' first derivatives.
            if old_derivs[0][N_test] > 0:
                #print "real", N_test, fdif_real,old_derivs[0][N_test], (fdif_real-old_derivs[0][N_test])/old_derivs[0][N_test]
                if old_derivs[0][N_test] > 2500:
                    assert approx_equal(
                        (fdif_real - old_derivs[0][N_test]) / fdif_real,
                        0,
                        eps=1e-2)
            if old_derivs[1][N_test] > 0:
                #print  "Imag", N_test, fdif_imag,old_derivs[1][N_test], (fdif_imag-old_derivs[1][N_test])/old_derivs[1][N_test]
                if old_derivs[1][N_test] > 2500:
                    assert approx_equal(
                        (fdif_imag - old_derivs[1][N_test]) / fdif_imag,
                        0,
                        eps=1e-2)
            new_data[N_test] = ori

    #-------------------------------------
    # use fin diffs to test derivatives wrst alpha, the twin fraction
    h = 0.0000000001

    target_evaluator = xray.least_squares_hemihedral_twinning_on_i(
        hkl_obs=sfs.indices(),
        i_obs=(flex.abs(sfs.data()) * flex.abs(sfs.data())) * 1.0,
        w_obs=None,
        hkl_calc=sfs.indices(),
        space_group=sfs.space_group(),
        anomalous_flag=False,
        alpha=0,
        twin_law=[-1, 0, 0, 0, 1, 0, 0, 0, -1])

    tst_alpha = [0.1, 0.2, 0.3, 0.4, 0.5]

    for ii in tst_alpha:
        target_evaluator.alpha(ii)
        old_target = target_evaluator.target(sfs.data() * 1.0)
        target_evaluator.alpha(ii + h)
        new_target = target_evaluator.target(sfs.data() * 1.0)
        fd = (new_target - old_target) / h
        target_evaluator.alpha(ii)
        an = target_evaluator.d_target_d_alpha(sfs.data() * 1.0)
        assert approx_equal(fd / an, 1.0, eps=1e-2)
Example #4
0
def tst_f_model(this_hkl=123):
  tmp = rs.xray_structure(sgtbx.space_group_info( 'P1' ),
                          elements=['C']*310,
                          n_scatterers=310)

  sfs = tmp.structure_factors( False, 3.5,  ).f_calc()
  f_mod = xray.f_model_core_data( hkl = sfs.indices(),
                        f_atoms= sfs.data(),
                        f_mask = sfs.data(),
                        unit_cell = sfs.unit_cell(),
                        k_overall=1.0,
                        u_star=(0,0,0,0,0,0),
                        k_sol=1.0,
                        u_sol=1.0,
                        f_part=sfs.data(),
                        k_part=1.0,
                        u_part=1.0 )

  data1 = sfs.data()[this_hkl]
  hkl1 =  sfs.indices()[this_hkl]

  fbulk = f_mod.f_bulk()[this_hkl]
  fatoms = f_mod.f_atoms()[this_hkl]
  fpart = f_mod.f_part()[this_hkl]
  fmod = f_mod.f_model()[this_hkl]
  # we have unit scale now
  assert approx_equal( fmod, fbulk+fatoms+fpart )
  # get derivatives please
  #
  # make a mock target function: T=A^2 + B^2
  # dT/dF=2F
  # dT/dA=2A
  # dT/dB=2B
  f_model_data_complex = f_mod.f_model()
  fm = flex.double()
  a = flex.double()
  b = flex.double()

  for cmplx in f_model_data_complex:
    tmp_a=cmplx.real
    tmp_b=cmplx.imag
    fm.append( math.sqrt(tmp_a*tmp_a + tmp_b*tmp_b) )
    a.append( tmp_a )
    b.append( tmp_b )

  dtdf = 2.0*fm
  dtda = 2.0*a
  dtdb = 2.0*b

  gradient_flags=flex.bool([True,True,
                            True,True,
                            True,True])

  grads_f = f_mod.d_target_d_all(dtdf,gradient_flags)
  grads_ab = f_mod.d_target_d_all(dtda, dtdb,gradient_flags)
  compare_all(grads_ab,grads_f)

  f_mod = xray.f_model_core_data( hkl = sfs.indices(),
                        f_atoms= sfs.data(),
                        f_mask = sfs.data()*0.0,
                        unit_cell = sfs.unit_cell(),
                        k_overall=1.0,
                        u_star=(0,0,0,0,0,0),
                        k_sol=0.0,
                        u_sol=0.0,
                        f_part=sfs.data()*0.0,
                        k_part=0.0,
                        u_part=0.0 )
  f_mod.refresh()
  grad_123 = f_mod.d_target_d_all(0,1,this_hkl, gradient_flags)
  assert approx_equal( grad_123.koverall(),
                       f_mod.f_model()[this_hkl].imag/f_mod.koverall() )
  tps=19.7392088 # 2 pi^2
  h=hkl1[0]
  k=hkl1[1]
  l=hkl1[2]
  assert approx_equal( -2*tps*h*h*f_mod.f_model()[this_hkl].imag,
                       grad_123.ustar()[0] )
  assert approx_equal( -2*tps*k*k*f_mod.f_model()[this_hkl].imag,
                       grad_123.ustar()[1] )
  assert approx_equal( -2*tps*l*l*f_mod.f_model()[this_hkl].imag,
                       grad_123.ustar()[2] )
  assert approx_equal( -4*tps*h*k*f_mod.f_model()[this_hkl].imag,
                       grad_123.ustar()[3] )
  assert approx_equal( -4*tps*h*l*f_mod.f_model()[this_hkl].imag,
                       grad_123.ustar()[4] )
  assert approx_equal( -4*tps*k*l*f_mod.f_model()[this_hkl].imag,
                       grad_123.ustar()[5] )





  grad_123 = f_mod.d_target_d_all(1,0,this_hkl, gradient_flags)
  assert approx_equal( grad_123.koverall(),
                       f_mod.f_model()[this_hkl].real/f_mod.koverall() )
  tps=19.7392088
  h=hkl1[0]
  k=hkl1[1]
  l=hkl1[2]
  assert approx_equal( -2*tps*h*h*f_mod.f_model()[this_hkl].real,
                       grad_123.ustar()[0] )
  assert approx_equal( -2*tps*k*k*f_mod.f_model()[this_hkl].real,
                       grad_123.ustar()[1] )
  assert approx_equal( -2*tps*l*l*f_mod.f_model()[this_hkl].real,
                       grad_123.ustar()[2] )
  assert approx_equal( -4*tps*h*k*f_mod.f_model()[this_hkl].real,
                       grad_123.ustar()[3] )
  assert approx_equal( -4*tps*h*l*f_mod.f_model()[this_hkl].real,
                       grad_123.ustar()[4] )
  assert approx_equal( -4*tps*k*l*f_mod.f_model()[this_hkl].real,
                       grad_123.ustar()[5] )


  oldfm = xray.f_model_core_data( hkl = sfs.indices(),
                        f_atoms= sfs.data(),
                        f_mask = sfs.data()*1.0,
                        unit_cell = sfs.unit_cell(),
                        k_overall=1.0,
                        u_star=(0,0,0,0,0,0),
                        k_sol=1.0,
                        u_sol=1.0,
                        f_part=sfs.data()*1.0,
                        k_part=1.0,
                        u_part=1.0 )
  h=0.0001


  newfm = xray.f_model_core_data( hkl = sfs.indices(),
                        f_atoms= sfs.data(),
                        f_mask = sfs.data()*1.0,
                        unit_cell = sfs.unit_cell(),
                        k_overall=1.0,
                        u_star=(0,0,0,0,0,0),
                        k_sol=1.0,
                        u_sol=1.0,
                        f_part=sfs.data()*1.0,
                        k_part=1.0,
                        u_part=1.0 )


  newfm.renew_overall_scale_parameters(1.0+h, (0,0,0,0,0,0))
  newfm.refresh()

  tmp = oldfm.d_target_d_all(1,0,this_hkl,gradient_flags).koverall()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).real
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_overall_scale_parameters(1, (0,0,0,0,0,0))

  newfm.renew_bulk_solvent_scale_parameters(1+h,1.0)
  tmp = oldfm.d_target_d_all(1,0,this_hkl,gradient_flags).ksol()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).real
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1,1.0)

  newfm.renew_bulk_solvent_scale_parameters(1.0,1.0+h)
  tmp = oldfm.d_target_d_all(1,0,this_hkl,gradient_flags).usol()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).real
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1.0,1.0)

  newfm.renew_bulk_solvent_scale_parameters(1+h,1.0)
  tmp = oldfm.d_target_d_all(0,1,this_hkl,gradient_flags).ksol()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).imag
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1,1.0)

  newfm.renew_bulk_solvent_scale_parameters(1.0,1.0+h)
  tmp = oldfm.d_target_d_all(0,1,this_hkl,gradient_flags).usol()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).imag
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1.0,1.0)


  newfm.renew_partial_structure_scale_parameters(1+h,1.0)
  tmp = oldfm.d_target_d_all(1,0,this_hkl,gradient_flags).kpart()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).real
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1,1.0)

  newfm.renew_partial_structure_scale_parameters(1.0,1.0+h)
  tmp = oldfm.d_target_d_all(1,0,this_hkl,gradient_flags).upart()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).real
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1.0,1.0)

  newfm.renew_partial_structure_scale_parameters(1+h,1.0)
  tmp = oldfm.d_target_d_all(0,1,this_hkl,gradient_flags).kpart()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).imag
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1,1.0)

  newfm.renew_partial_structure_scale_parameters(1.0,1.0+h)
  tmp = oldfm.d_target_d_all(0,1,this_hkl,gradient_flags).upart()
  tmp_d = ((oldfm.f_model()[this_hkl]-newfm.f_model()[this_hkl])/(-h)).imag
  assert approx_equal( tmp,tmp_d,eps=1e-2 )
  newfm.renew_bulk_solvent_scale_parameters(1.0,1.0)
def f_model_example():
  """ This example illustrates the use of the f_model class"""

  # make up some structure factors
  random_structure = rs.xray_structure(
    sgtbx.space_group_info( 'P1' ),
    elements=['C']*310,
    n_scatterers=310)

  # here f_atoms, f_mask and f_part are all the same
  # doens't make sense of course
  sfs = random_structure.structure_factors( False, 3.5,  ).f_calc()
  f_model_structure_factors =  xray.f_model_core_data( hkl = sfs.indices(),
                                             f_atoms= sfs.data(),
                                             f_mask = sfs.data(),
                                             unit_cell = sfs.unit_cell(),
                                             k_overall=1.0,
                                             u_star=(0,0,0,0,0,0),
                                             k_sol=1.0,
                                             u_sol=1.0,
                                             f_part=None,
                                             k_part=0,
                                             u_part=0 )

  #Resetting model parameters
  #
  # over all scale parameters; scale and aniso Ustar
  f_model_structure_factors.renew_overall_scale_parameters(
    3.0,(0,0,0,0,0,0) )
  # bulk solvent scale parameters; scale and B
  f_model_structure_factors.renew_bulk_solvent_scale_parameters(0.55,50.0)
  # partial structure scale parameters; scale and B
  f_model_structure_factors.renew_partial_structure_scale_parameters(0.05,25.0)

  # is is also possible to reset the values term by term ratrher then grouped
  f_model_structure_factors.ksol( 1.0 )
  f_model_structure_factors.usol( 3.0 )
  f_model_structure_factors.kpart( 1.0 )
  f_model_structure_factors.upart( 3.0 )
  f_model_structure_factors.koverall( 1.0 )
  f_model_structure_factors.ustar( (0,0,0,0,0,0) )
  # the cached arrays of various scale factor as updated automatically.

  # Obtaining the current parameters
  ksol = f_model_structure_factors.ksol()
  bsol = f_model_structure_factors.usol()
  kpart = f_model_structure_factors.kpart()
  bpart = f_model_structure_factors.upart()
  koverall = f_model_structure_factors.koverall()
  ustar = f_model_structure_factors.ustar()

  # Derivatives
  #
  #
  #derivates can be obtained accumalated over the full dataset
  # or on a struct term by term bases
  #what is needed in any case are one of the following arrays or floats
  # - d(target)/d(|F_model|)
  # - d(target)/d(Re[F_model]), d(target)/d(Im[F_model])
  #
  # which derivates are computed, is controlled by an array of gradient flags:
  # the order is (koverall, ustar, ksol, bsol, kpart, bpart )
  #
  gradient_flags = flex.bool([True,True,
                              True,True,
                              True,True])
  #
  # Use this function call is your target function returns
  # d(target)/d(|Fmodel|)
  dt_dabsfmodel = flex.double( sfs.data().size(), 1 )
  dtdall = f_model_structure_factors.d_target_d_all(
    dt_dabsfmodel,gradient_flags )

  # Use this function call is your target function returns
  # d(target)/d(Re[Fmodel]), d(target)/d(Im[Fmodel])
  dtda = dt_dabsfmodel
  dtdb = dt_dabsfmodel

  dtdall = f_model_structure_factors.d_target_d_all(
    dtda, dtdb, gradient_flags)
  # if desired (likely in c++, not in python) you can do it term by term.
  hkl_no=123
  dtdsingle = f_model_structure_factors.d_target_d_all(
    dtda[hkl_no], dtdb[hkl_no], hkl_no, gradient_flags)

  # the resulting gradients are delivered as a
  # 'f_model_derivative_holder'
  # it has methods both to set as well as to get items.
  #
  # getting the values
  tmp = dtdsingle.koverall()
  tmp = dtdsingle.ustar()
  tmp = dtdsingle.ksol()
  tmp = dtdsingle.usol()
  tmp = dtdsingle.kpart()
  tmp = dtdsingle.upart()
  #
  # if desired, you can set values as well
  dtdsingle.koverall(1)
  dtdsingle.ustar(  (1,1,1,1,1,1)  )
  dtdsingle.ksol(1)
  dtdsingle.usol(1)
  dtdsingle.kpart(1)
  dtdsingle.upart(1)



  #if desired, a selection can be made on the f_model object.
  #currently, only an integer selection is supported
  new_f_model_object = f_model_structure_factors.select( flex.int([1,2,3]) )
  assert  new_f_model_object.f_model().size()==3
def tst_ls_on_i():
  tmp = rs.xray_structure(sgtbx.space_group_info( 'P4' ),
                          elements=['C']*310,
                          n_scatterers=310)

  sfs = tmp.structure_factors( False, 3.5  ).f_calc()
  f_mod = xray.f_model_core_data( hkl = sfs.indices(),
                        f_atoms= sfs.data(),
                        f_mask = sfs.data(),
                        unit_cell = sfs.unit_cell(),
                        k_overall=1.0,
                        u_star=(0,0,0,0,0,0),
                        k_sol=0.0,
                        u_sol=0.0,
                        f_part=sfs.data(),
                        k_part=0.0,
                        u_part=0.0 )

  target_evaluator = xray.least_squares_hemihedral_twinning_on_i(
    hkl_obs=sfs.indices(),
    i_obs=( flex.abs(sfs.data())*flex.abs(sfs.data()))*1.0,
    w_obs=None,
    hkl_calc=sfs.indices(),
    space_group=sfs.space_group(),
    anomalous_flag=False,
    alpha=0.0,
    twin_law=[-1,0,0, 0,1,0, 0,0,-1]
    )

  target = target_evaluator.target( sfs.data() )
  # The target vaslue should be zero
  assert approx_equal( target, 0, eps=1e-6)

  # the derivatives as well
  derivs_complex = target_evaluator.d_target_d_fmodel( sfs.data()  )
  derivs_ab = target_evaluator.d_target_d_ab( sfs.data()  )
  for cmplx,da,db in zip(derivs_complex,
                         derivs_ab[0],
                         derivs_ab[1]):
    assert approx_equal( cmplx.real, da, eps=1e-5)
    assert approx_equal( cmplx.imag, db, eps=1e-5)

  for alpha in flex.double(range(50))/100.0:
    #----------------------------------------------------------------
    # use fin diffs to check the derivatives to a and b
    old_target_evaluator = xray.least_squares_hemihedral_twinning_on_i(
      hkl_obs=sfs.indices(),
      i_obs=( flex.abs(sfs.data())*flex.abs(sfs.data()))*1.1,
      w_obs=None,
      hkl_calc=sfs.indices(),
      space_group=sfs.space_group(),
      anomalous_flag=False,
      alpha=alpha,
      twin_law=[-1,0,0, 0,1,0, 0,0,-1]
      )
    old_target_value = old_target_evaluator.target( sfs.data() )
    old_derivs = old_target_evaluator.d_target_d_ab( sfs.data() )

    new_data =  sfs.data()
    h=0.0001

    for N_test in xrange(sfs.data().size() ):
      ori = complex( sfs.data()[N_test] )
      #print "----------------"
      #print alpha
      #print sfs.indices()[N_test]
      #print sfs.data()[N_test]
      new_data[N_test] = ori+complex(h,0)
      new_target_value = old_target_evaluator.target( new_data )
      fdif_real = float((new_target_value-old_target_value)/h)
      new_data[N_test] = ori+complex(0,h)
      new_target_value = old_target_evaluator.target( new_data )
      fdif_imag = float( (new_target_value-old_target_value)/h )
      # only use 'large' first derivatives.
      if old_derivs[0][N_test]>0:
        #print "real", N_test, fdif_real,old_derivs[0][N_test], (fdif_real-old_derivs[0][N_test])/old_derivs[0][N_test]
        if old_derivs[0][N_test]>2500:
          assert approx_equal( (fdif_real-old_derivs[0][N_test])/fdif_real,0, eps=1e-2)
      if old_derivs[1][N_test]>0:
        #print  "Imag", N_test, fdif_imag,old_derivs[1][N_test], (fdif_imag-old_derivs[1][N_test])/old_derivs[1][N_test]
        if old_derivs[1][N_test]>2500:
          assert approx_equal( (fdif_imag-old_derivs[1][N_test])/fdif_imag,0, eps=1e-2)
      new_data[N_test] = ori

  #-------------------------------------
  # use fin diffs to test derivatives wrst alpha, the twin fraction
  h=0.0000000001

  target_evaluator = xray.least_squares_hemihedral_twinning_on_i(
    hkl_obs=sfs.indices(),
    i_obs=( flex.abs(sfs.data())*flex.abs(sfs.data()))*1.0,
    w_obs=None,
    hkl_calc=sfs.indices(),
    space_group=sfs.space_group(),
    anomalous_flag=False,
    alpha=0,
    twin_law=[-1,0,0, 0,1,0, 0,0,-1]
    )

  tst_alpha = [0.1, 0.2, 0.3, 0.4, 0.5]

  for ii in tst_alpha:
    target_evaluator.alpha(ii)
    old_target = target_evaluator.target( sfs.data()*1.0 )
    target_evaluator.alpha( ii + h )
    new_target = target_evaluator.target( sfs.data()*1.0 )
    fd = (new_target-old_target)/h
    target_evaluator.alpha(ii)
    an = target_evaluator.d_target_d_alpha(sfs.data()*1.0)
    assert approx_equal( fd/an , 1.0, eps=1e-2 )