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_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 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)
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 )