def dRq_de(theta, e, q): '''Calculate derivative of rotated vector r = R*q with respect to the elements of the rotation axis e, where the angle of rotation is theta. Implementation of Equation (8) from Gallego & Yezzi. NB a C++ version exists in gallego_yezzi.h.''' from scitbx import matrix # ensure e is unit vector e = e.normalize() # rotation matrix R = e.axis_and_angle_as_r3_rotation_matrix(theta, deg=False) # rotation vector v v = theta * e qx = skew_symm(q) vx = skew_symm(v) vvt = v*v.transpose() Rt = R.transpose() I3 = matrix.identity(3) return (-1./theta) * R * qx * (vvt + (Rt - I3) * vx)
def align_reference_frame(primary_axis, primary_target, secondary_axis, secondary_target): """Compute a rotation matrix R: R x primary_axis = primary_target and R x secondary_axis places the secondary_axis in the plane perpendicular to the primary_target, as close as possible to the secondary_target. Require: primary_target orthogonal to secondary_target, primary axis not colinear with secondary axis.""" from scitbx import matrix import math if type(primary_axis) == type(()) or type(primary_axis) == type([]): primary_axis = matrix.col(primary_axis).normalize() else: primary_axis = primary_axis.normalize() if type(primary_target) == type(()) or type(primary_target) == type([]): primary_target = matrix.col(primary_target).normalize() else: primary_target = primary_target.normalize() if type(secondary_axis) == type(()) or type(secondary_axis) == type([]): secondary_axis = matrix.col(secondary_axis).normalize() else: secondary_axis = secondary_axis.normalize() if type(secondary_target) == type(()) or \ type(secondary_target) == type([]): secondary_target = matrix.col(secondary_target).normalize() else: secondary_target = secondary_target.normalize() # check properties of input axes assert(math.fabs(primary_axis.angle(secondary_axis) % math.pi) > 0.001) assert(primary_target.dot(secondary_target) < 0.001) if primary_target.angle(primary_axis) % math.pi: axis_p = primary_target.cross(primary_axis) angle_p = - primary_target.angle(primary_axis) Rprimary = axis_p.axis_and_angle_as_r3_rotation_matrix(angle_p) elif primary_target.angle(primary_axis) < 0: axis_p = primary_axis.ortho().normalize() angle_p = math.pi Rprimary = axis_p.axis_and_angle_as_r3_rotation_matrix(angle_p) else: Rprimary = matrix.identity(3) axis_r = secondary_target.cross(Rprimary * secondary_axis) axis_s = primary_target if (axis_r.angle(primary_target) > 0.5 * math.pi): angle_s = orthogonal_component(axis_s, secondary_target).angle( orthogonal_component(axis_s, Rprimary * secondary_axis)) else: angle_s = - orthogonal_component(axis_s, secondary_target).angle( orthogonal_component(axis_s, Rprimary * secondary_axis)) Rsecondary = axis_s.axis_and_angle_as_r3_rotation_matrix(angle_s) return Rsecondary * Rprimary
def exercise_ls_cycles(self): xs = self.xray_structure.deep_copy_scatterers() connectivity_table = smtbx.utils.connectivity_table(xs) emma_ref = xs.as_emma_model() # shaking must happen before the reparametrisation is constructed, # otherwise the original values will prevail xs.shake_sites_in_place(rms_difference=0.1) reparametrisation = constraints.reparametrisation( structure=xs, constraints=[], connectivity_table=connectivity_table) ls = least_squares.crystallographic_ls( self.fo_sq.as_xray_observations(), reparametrisation, weighting_scheme=least_squares.unit_weighting(), origin_fixing_restraints_type= origin_fixing_restraints.atomic_number_weighting) cycles = normal_eqns_solving.naive_iterations( ls, n_max_iterations=5, track_all=True) assert approx_equal(ls.scale_factor(), 1, eps=1e-5) assert approx_equal(ls.objective(), 0) # skip next-to-last one to allow for no progress and rounding error assert ( cycles.objective_history[0] >= cycles.objective_history[1] >= cycles.objective_history[3]), numstr(cycles.objective_history) assert approx_equal(cycles.gradient_norm_history[-1], 0, eps=5e-8) match = emma.model_matches(emma_ref, xs.as_emma_model()).refined_matches[0] assert match.rt.r == matrix.identity(3) for pair in match.pairs: assert approx_equal(match.calculate_shortest_dist(pair), 0, eps=1e-4)
def exercise_ls_cycles(self): xs = self.xray_structure.deep_copy_scatterers() connectivity_table = smtbx.utils.connectivity_table(xs) emma_ref = xs.as_emma_model() # shaking must happen before the reparametrisation is constructed, # otherwise the original values will prevail xs.shake_sites_in_place(rms_difference=0.1) reparametrisation = constraints.reparametrisation( structure=xs, constraints=[], connectivity_table=connectivity_table) ls = least_squares.crystallographic_ls( self.fo_sq.as_xray_observations(), reparametrisation, weighting_scheme=least_squares.mainstream_shelx_weighting(a=0), origin_fixing_restraints_type= origin_fixing_restraints.atomic_number_weighting) cycles = normal_eqns_solving.naive_iterations( ls, gradient_threshold=1e-12, step_threshold=1e-7, track_all=True) assert approx_equal(ls.scale_factor(), 1, eps=1e-5), ls.scale_factor() assert approx_equal(ls.objective(), 0), ls.objective() match = emma.model_matches(emma_ref, xs.as_emma_model()).refined_matches[0] assert match.rt.r == matrix.identity(3) for pair in match.pairs: assert approx_equal(match.calculate_shortest_dist(pair), 0, eps=1e-4)
def dRq_de(theta, e, q): '''Calculate derivative of rotated vector r = R*q with respect to the elements of the rotation axis e, where the angle of rotation is theta. Implementation of Equation (8) from Gallego & Yezzi. NB a C++ version exists in gallego_yezzi.h.''' from scitbx import matrix # ensure e is unit vector e = e.normalize() # rotation matrix R = e.axis_and_angle_as_r3_rotation_matrix(theta, deg=False) # rotation vector v v = theta * e qx = skew_symm(q) vx = skew_symm(v) vvt = v * v.transpose() Rt = R.transpose() I3 = matrix.identity(3) return (-1. / theta) * R * qx * (vvt + (Rt - I3) * vx)
def __init__(self, r, d, symmetry_agreement, status): assert r.den() == 1 self.r = r order = r.order() self.r_info = sgtbx.rot_mx_info(r) type = self.r_info.type() axis = self.r_info.ev() self.symmetry_agreement = symmetry_agreement self.status = status # compute intrinsic and location part of d, using p, which is # the order times the projector onto r's invariant space p = mat.sqr(r.accumulate().as_double()) t_i_num = (p*d).as_int() t_l = d - t_i_num/order t_i = sgtbx.tr_vec(sg_t_den//order*t_i_num, tr_den=sg_t_den) # compute the origin corresponding to t_l by solving # (1 - r) o = t_l one_minus_r = -mat.sqr(self.r.minus_unit_mx().num()) one_minus_r_row_echelon = one_minus_r.as_flex_int_matrix() q = mat.identity(3).as_flex_int_matrix() rank = scitbx.math.row_echelon_form_t(one_minus_r_row_echelon, q) qd = flex.double(mat.sqr(q)*t_l)[:rank] o = flex.double((0,0,0)) scitbx.math.row_echelon_back_substitution_float( one_minus_r_row_echelon, qd, o) # construct object state self.t_i, self.raw_origin = t_i, mat.col(o) self.origin = None self.one_minus_r = one_minus_r
def __init__(self, r, d, symmetry_agreement, status): assert r.den() == 1 self.r = r order = r.order() self.r_info = sgtbx.rot_mx_info(r) type = self.r_info.type() axis = self.r_info.ev() self.symmetry_agreement = symmetry_agreement self.status = status # compute intrinsic and location part of d, using p, which is # the order times the projector onto r's invariant space p = mat.sqr(r.accumulate().as_double()) t_i_num = (p * d).as_int() t_l = d - t_i_num / order t_i = sgtbx.tr_vec(sg_t_den // order * t_i_num, tr_den=sg_t_den) # compute the origin corresponding to t_l by solving # (1 - r) o = t_l one_minus_r = -mat.sqr(self.r.minus_unit_mx().num()) one_minus_r_row_echelon = one_minus_r.as_flex_int_matrix() q = mat.identity(3).as_flex_int_matrix() rank = scitbx.math.row_echelon_form_t(one_minus_r_row_echelon, q) qd = flex.double(mat.sqr(q) * t_l)[:rank] o = flex.double((0, 0, 0)) scitbx.math.row_echelon_back_substitution_float( one_minus_r_row_echelon, qd, o) # construct object state self.t_i, self.raw_origin = t_i, mat.col(o) self.origin = None self.one_minus_r = one_minus_r
def test_align_reference_frame(): _i = (1, 0, 0) _j = (0, 1, 0) _k = (0, 0, 1) primary_axis = _i primary_target = _i secondary_axis = _k secondary_target = _k m = align_reference_frame(primary_axis, primary_target, secondary_axis, secondary_target) i = matrix.identity(3) for j in range(9): assert(math.fabs(m.elems[j] - i.elems[j]) < 0.001) primary_axis = _j primary_target = _i secondary_axis = _k secondary_target = _k m = align_reference_frame(primary_axis, primary_target, secondary_axis, secondary_target) for j in range(3): assert(math.fabs((m * primary_axis).elems[j] - matrix.col(primary_target).elems[j]) < 0.001)
def align_reference_frame( primary_axis, primary_target, secondary_axis, secondary_target ): """Compute a rotation matrix R: R x primary_axis = primary_target and R x secondary_axis places the secondary_axis in the plane perpendicular to the primary_target, as close as possible to the secondary_target. Require: primary_target orthogonal to secondary_target, primary axis not colinear with secondary axis.""" from scitbx import matrix if type(primary_axis) == type(()) or type(primary_axis) == type([]): primary_axis = matrix.col(primary_axis).normalize() else: primary_axis = primary_axis.normalize() if type(primary_target) == type(()) or type(primary_target) == type([]): primary_target = matrix.col(primary_target).normalize() else: primary_target = primary_target.normalize() if type(secondary_axis) == type(()) or type(secondary_axis) == type([]): secondary_axis = matrix.col(secondary_axis).normalize() else: secondary_axis = secondary_axis.normalize() if type(secondary_target) == type(()) or type(secondary_target) == type([]): secondary_target = matrix.col(secondary_target).normalize() else: secondary_target = secondary_target.normalize() # check properties of input axes assert fabs(primary_axis.angle(secondary_axis) % pi) > 0.001 assert primary_target.dot(secondary_target) < 0.001 if primary_target.angle(primary_axis) % pi: axis_p = primary_target.cross(primary_axis) angle_p = -primary_target.angle(primary_axis) Rprimary = axis_p.axis_and_angle_as_r3_rotation_matrix(angle_p) elif primary_target.angle(primary_axis) < 0: axis_p = primary_axis.ortho().normalize() angle_p = pi Rprimary = axis_p.axis_and_angle_as_r3_rotation_matrix(angle_p) else: Rprimary = matrix.identity(3) Rpsa = Rprimary * secondary_axis axis_r = secondary_target.cross(Rpsa) axis_s = primary_target oc = AnglePredictor_rstbx.orthogonal_component angle_s = oc(axis_s, secondary_target).angle(oc(axis_s, Rpsa)) if axis_r.angle(primary_target) <= 0.5 * pi: angle_s *= -1.0 Rsecondary = axis_s.axis_and_angle_as_r3_rotation_matrix(angle_s) return Rsecondary * Rprimary
def exercise(self, fixed_twin_fraction): # Create a shaken structure xs ready for refinement xs0 = self.structure emma_ref = xs0.as_emma_model() xs = xs0.deep_copy_scatterers() xs.shake_sites_in_place(rms_difference=0.15) xs.shake_adp() for sc in xs.scatterers(): sc.flags.set_use_u_iso(False).set_use_u_aniso(True) sc.flags.set_grad_site(True).set_grad_u_aniso(True) # Setup L.S. problem connectivity_table = smtbx.utils.connectivity_table(xs) shaken_twin_fraction = (self.twin_fraction if fixed_twin_fraction else self.twin_fraction + 0.1 * flex.random_double()) # 2nd domain in __init__ twin_components = (xray.twin_component(twin_law=self.twin_law.r(), value=shaken_twin_fraction, grad=not fixed_twin_fraction), ) reparametrisation = constraints.reparametrisation( structure=xs, constraints=[], connectivity_table=connectivity_table, twin_fractions=twin_components) obs = self.fo_sq.as_xray_observations(twin_components=twin_components) ls = least_squares.crystallographic_ls( obs, reparametrisation, weighting_scheme=least_squares.unit_weighting(), origin_fixing_restraints_type=origin_fixing_restraints. atomic_number_weighting) # Refine till we get back the original structure (so we hope) cycles = normal_eqns_solving.levenberg_marquardt_iterations( ls, gradient_threshold=1e-12, step_threshold=1e-6, track_all=True) # Now let's start to check it all worked assert ls.n_parameters == 63 if fixed_twin_fraction else 64 match = emma.model_matches(emma_ref, xs.as_emma_model()).refined_matches[0] assert match.rt.r == matrix.identity(3) for pair in match.pairs: assert approx_equal(match.calculate_shortest_dist(pair), 0, eps=1e-4), pair if fixed_twin_fraction: assert ls.twin_fractions[0].value == self.twin_fraction else: assert approx_equal(ls.twin_fractions[0].value, self.twin_fraction, eps=1e-2) assert approx_equal(ls.scale_factor(), 1, eps=1e-5) assert approx_equal(ls.objective(), 0)
def test_matrix(s,eps=1e-3): # s is a list of 9 float numbers R = matrix.sqr(s) t1 = R*R.transpose() t2 = matrix.identity(3) det_is = R.determinant() det_tet = abs(det_is - 1) < eps inv_test = abs(t1 - t2) < eps return det_is, det_tet, inv_test
def exercise(self, fixed_twin_fraction): # Create a shaken structure xs ready for refinement xs0 = self.structure emma_ref = xs0.as_emma_model() xs = xs0.deep_copy_scatterers() xs.shake_sites_in_place(rms_difference=0.15) xs.shake_adp() for sc in xs.scatterers(): sc.flags.set_use_u_iso(False).set_use_u_aniso(True) sc.flags.set_grad_site(True).set_grad_u_aniso(True) # Setup L.S. problem connectivity_table = smtbx.utils.connectivity_table(xs) shaken_twin_fraction = ( self.twin_fraction if fixed_twin_fraction else self.twin_fraction + 0.1*flex.random_double()) # 2nd domain in __init__ twin_components = (xray.twin_component( twin_law=self.twin_law.r(), value=shaken_twin_fraction, grad=not fixed_twin_fraction),) reparametrisation = constraints.reparametrisation( structure=xs, constraints=[], connectivity_table=connectivity_table, twin_fractions=twin_components) obs = self.fo_sq.as_xray_observations(twin_components=twin_components) ls = least_squares.crystallographic_ls( obs, reparametrisation, weighting_scheme=least_squares.unit_weighting(), origin_fixing_restraints_type= origin_fixing_restraints.atomic_number_weighting) # Refine till we get back the original structure (so we hope) cycles = normal_eqns_solving.levenberg_marquardt_iterations( ls, gradient_threshold=1e-12, step_threshold=1e-6, track_all=True) # Now let's start to check it all worked assert ls.n_parameters == 63 if fixed_twin_fraction else 64 match = emma.model_matches(emma_ref, xs.as_emma_model()).refined_matches[0] assert match.rt.r == matrix.identity(3) for pair in match.pairs: assert approx_equal(match.calculate_shortest_dist(pair), 0, eps=1e-4), pair if fixed_twin_fraction: assert ls.twin_fractions[0].value == self.twin_fraction else: assert approx_equal(ls.twin_fractions[0].value, self.twin_fraction, eps=1e-2) assert approx_equal(ls.scale_factor(), 1, eps=1e-5) assert approx_equal(ls.objective(), 0)
def mcI(m, c, I): """ % mcI spatial rigid-body inertia from mass, CoM and rotational inertia. % mcI(m,c,I) calculates the spatial inertia matrix of a rigid body from its % mass, centre of mass (3D vector) and rotational inertia (3x3 matrix) % about its centre of mass. """ c1, c2, c3 = c C = matrix.sqr((0, -c3, c2, c3, 0, -c1, -c2, c1, 0)) return matrix.sqr((I + m * C * C.transpose(), m * C, m * C.transpose(), m * matrix.identity(3))).resolve_partitions()
def DrawGL(self): wx_viewer.show_points_and_lines_mixin.DrawGL(self) gonio = self.parent.imageset.get_goniometer() beam = self.parent.imageset.get_beam() from scitbx import matrix R = matrix.identity(3) names = reversed(gonio.get_names()) axes = reversed(gonio.get_axes()) angles = reversed(gonio.get_angles()) for name, axis, angle in zip(names, axes, angles): axis = R * matrix.col(axis) self.draw_axis(axis.elems, name) R = axis.axis_and_angle_as_r3_rotation_matrix(angle, deg=True) * R self.draw_axis(beam.get_s0(), "beam")
def find_closest_matrix(moving, target): '''Work through lattice permutations to try to align moving with target, with the metric of trace(inverse(moving) * target).''' trace = 0.0 reindex = matrix.identity(3) for op in sgtbx.space_group_info('P422').type().group().all_ops(): moved = matrix.sqr(op.r().as_double()) * moving if (moved.inverse() * target).trace() > trace: trace = (moved.inverse() * target).trace() reindex = matrix.sqr(op.r().as_double()) return reindex
def mcI(m, c, I): """ % mcI spatial rigid-body inertia from mass, CoM and rotational inertia. % mcI(m,c,I) calculates the spatial inertia matrix of a rigid body from its % mass, centre of mass (3D vector) and rotational inertia (3x3 matrix) % about its centre of mass. """ c1,c2,c3 = c C = matrix.sqr(( 0, -c3, c2, c3, 0, -c1, -c2, c1, 0)) return matrix.sqr(( I + m*C*C.transpose(), m*C, m*C.transpose(), m*matrix.identity(3))).resolve_partitions()
def gallego_yezzi_eqn9(t, k): """This is equation (9) from Gallego & Yezzi""" from scitbx import matrix from math import sin, cos v = t * k R = k.axis_and_angle_as_r3_rotation_matrix(t, deg=False) I3 = matrix.identity(3) V = skew_symm(v) e = (matrix.col((1, 0, 0)), matrix.col((0, 1, 0)), matrix.col((0, 0, 1))) term1 = [skew_symm(v.cross((I3 - R) * e[i])) for i in range(3)] return [(1.0 / t) * (v[i] * V + term1[i]) * R for i in range(3)]
def p_matrix_from(a_sites, b_sites, weights): # Diamond, Acta Cryst A44, 211-216 (1988) assert len(a_sites) == len(b_sites) and len(a_sites) == len(weights) (xa, ya, za) = component_arrays(a_sites) (xb, yb, zb) = component_arrays(b_sites) m = matrix.sqr([ flex.sum(weights * xa * xb), flex.sum(weights * xa * yb), flex.sum(weights * xa * zb), flex.sum(weights * ya * xb), flex.sum(weights * ya * yb), flex.sum(weights * ya * zb), flex.sum(weights * za * xb), flex.sum(weights * za * yb), flex.sum(weights * za * zb), ]) q = m + m.transpose() - 2 * matrix.identity(3) * m.trace() # Application of Sum(j, k)[ epsilon( i, j, k ) * m( j, k ) ] # where i,j,k = [ 0, 1, 2 ] and epsilon is the Levi-Civitta symbol v = (m[5] - m[7], m[6] - m[2], m[1] - m[3]) return matrix.sqr([ q[0], q[1], q[2], v[0], q[3], q[4], q[5], v[1], q[6], q[7], q[8], v[2], v[0], v[1], v[2], 0, ])
def test_UnitCellAnalysisObserver(): # generate some random unit cells sgi = sgtbx.space_group_info("P1") unit_cells = [ sgi.any_compatible_unit_cell(volume=random.uniform(990, 1010)) for i in range(10) ] # generate experiment list experiments = ExperimentList() U = matrix.identity(3) for uc in unit_cells: B = matrix.sqr(uc.fractionalization_matrix()).transpose() direct_matrix = (U * B).inverse() experiments.append( Experiment(crystal=Crystal( direct_matrix[:3], direct_matrix[3:6], direct_matrix[6:9], space_group=sgi.group(), ))) # generate dendrogram crystal_symmetries = [ expt.crystal.get_crystal_symmetry() for expt in experiments ] lattice_ids = experiments.identifiers() ucs = UnitCellCluster.from_crystal_symmetries(crystal_symmetries, lattice_ids=lattice_ids) _, dendrogram, _ = ucs.ab_cluster(write_file_lists=False, doplot=False) # setup script script = mock.Mock() script._experiments = experiments script.unit_cell_dendrogram = dendrogram # test the observer observer = observers.UnitCellAnalysisObserver() observer.update(script) assert set(observer.data) == {"experiments", "dendrogram"} d = observer.make_plots() assert "unit_cell_graphs" in d
def run(args): import libtbx.load_env from dials.util.options import OptionParser from dials.util.options import flatten_experiments # The script usage usage = "usage: %s [options] [param.phil] experiments.json" %libtbx.env.dispatcher_name parser = OptionParser( usage=usage, phil=phil_scope, read_experiments=True, check_format=False, epilog=help_message) params, options = parser.parse_args(show_diff_phil=True) experiments = flatten_experiments(params.input.experiments) if len(experiments) == 0: parser.print_help() return if len(params.hkl) == 0 and params.hkl_limit is None: from libtbx.utils import Sorry raise Sorry("Please provide hkl or hkl_limit parameters.") if params.hkl is not None and len(params.hkl): miller_indices = flex.miller_index(params.hkl) elif params.hkl_limit is not None: limit = params.hkl_limit miller_indices = flex.miller_index() for h in range(-limit, limit+1): for k in range(-limit, limit+1): for l in range(-limit, limit+1): if (h,k,l) == (0,0,0): continue miller_indices.append((h,k,l)) crystals = experiments.crystals() symmetry = crystal.symmetry( unit_cell=crystals[0].get_unit_cell(), space_group=crystals[0].get_space_group()) miller_set = miller.set(symmetry, miller_indices) d_spacings = miller_set.d_spacings() if params.eliminate_sys_absent: d_spacings = d_spacings.eliminate_sys_absent() if params.expand_to_p1: d_spacings = d_spacings.as_non_anomalous_array().expand_to_p1() d_spacings = d_spacings.generate_bijvoet_mates() miller_indices = d_spacings.indices() # find the greatest common factor (divisor) between miller indices miller_indices_unique = flex.miller_index() for hkl in miller_indices: gcd = gcd_list(hkl) if gcd > 1: miller_indices_unique.append(tuple(int(h/gcd) for h in hkl)) elif gcd < 1: pass else: miller_indices_unique.append(hkl) miller_indices = miller_indices_unique miller_indices = flex.miller_index(list(set(miller_indices))) ref_crystal = crystals[0] A = ref_crystal.get_A() U = ref_crystal.get_U() B = ref_crystal.get_B() R = matrix.identity(3) if params.frame == 'laboratory': reference_poles = reference_poles_perpendicular_to_beam( experiments[0].beam, experiments[0].goniometer) if params.use_starting_angle: rotation_axis = matrix.col( experiments[0].goniometer.get_rotation_axis()) R = rotation_axis.axis_and_angle_as_r3_rotation_matrix( experiments[0].scan.get_oscillation()[0], deg=True) elif params.phi_angle != 0: rotation_axis = matrix.col( experiments[0].goniometer.get_rotation_axis()) R = rotation_axis.axis_and_angle_as_r3_rotation_matrix( params.phi_angle, deg=True) else: if params.plane_normal is not None: plane_normal = params.plane_normal else: plane_normal = (0,0,1) reference_poles = reference_poles_crystal( ref_crystal, plane_normal=plane_normal) if params.frame == 'crystal': U = matrix.identity(3) reciprocal_space_points = list(R * U * B) * miller_indices.as_vec3_double() projections_ref = stereographic_projection( reciprocal_space_points, reference_poles) projections_all = [projections_ref] if len(experiments) > 0: from dials.algorithms.indexing.compare_orientation_matrices import \ difference_rotation_matrix_and_euler_angles for expt in experiments[1:]: cryst = expt.crystal if params.frame == 'crystal': R_ij, euler_angles, cb_op = difference_rotation_matrix_and_euler_angles( ref_crystal, cryst) U = R_ij elif params.use_starting_angle: if params.use_starting_angle: rotation_axis = matrix.col( expt.goniometer.get_rotation_axis()) R = rotation_axis.axis_and_angle_as_r3_rotation_matrix( expt.scan.get_oscillation()[0], deg=True) else: U = cryst.get_U() reciprocal_space_points = list(R * U * cryst.get_B()) * miller_indices.as_vec3_double() projections = stereographic_projection( reciprocal_space_points, reference_poles) projections_all.append(projections) if params.save_coordinates: with open('projections.txt', 'wb') as f: print >> f, "crystal h k l x y" for i_cryst, projections in enumerate(projections_all): for hkl, proj in zip(miller_indices, projections): print >> f, "%i" %(i_cryst+1), print >> f, "%i %i %i" %hkl, print >> f, "%f %f" %proj if params.plot.show or params.plot.filename: plot_projections( projections_all, filename=params.plot.filename, show=params.plot.show, colours=params.plot.colours, marker_size=params.plot.marker_size, font_size=params.plot.font_size, label_indices=params.plot.label_indices)
def DrawGL(self): wx_viewer.show_points_and_lines_mixin.DrawGL(self) gonio = self.parent.imageset.get_goniometer() beam = self.parent.imageset.get_beam() detector = self.parent.imageset.get_detector() if self.settings.show_panel_axes and detector is not None: for p in detector: image_size = p.get_image_size_mm() from scitbx import matrix o = matrix.col(p.get_lab_coord((0,0))) f = matrix.col(p.get_lab_coord((image_size[0],0))) _f = (f - o).normalize() s = matrix.col(p.get_lab_coord((0,image_size[1]))) _s = (s - o).normalize() _n = _f.cross(_s) n = _n * (0.25 * (f.length() + s.length())) + o self.draw_lab_axis(o.elems, f.elems, 'FAST') self.draw_lab_axis(o.elems, s.elems, 'SLOW') self.draw_lab_axis(o.elems, n.elems, 'NORM') from scitbx import matrix if isinstance(gonio, MultiAxisGoniometer): R = matrix.identity(3) names = reversed(gonio.get_names()) axes = reversed(gonio.get_axes()) angles = reversed(gonio.get_angles()) for name, axis, angle in zip(names, axes, angles): axis = R * matrix.col(axis) self.draw_axis(axis.elems, name) R = axis.axis_and_angle_as_r3_rotation_matrix(angle, deg=True) * R elif gonio is not None: axis = matrix.col(gonio.get_rotation_axis()) self.draw_axis(axis.elems, "phi") self.draw_axis(beam.get_s0(), "beam") crystal = self.parent.crystal if crystal is not None: crystal = copy.deepcopy(crystal) scan = self.parent.imageset.get_scan() fixed_rotation = matrix.sqr(gonio.get_fixed_rotation()) setting_rotation = matrix.sqr(gonio.get_setting_rotation()) rotation_axis = matrix.col(gonio.get_rotation_axis_datum()) if isinstance(gonio, MultiAxisGoniometer): angle = gonio.get_angles()[gonio.get_scan_axis()] else: angle = scan.get_oscillation()[0] rotation_matrix = rotation_axis.axis_and_angle_as_r3_rotation_matrix( angle, deg=True) U0 = matrix.sqr(crystal.get_U()) # Goniometer datum setting [D] at which the orientation was determined D = (setting_rotation * rotation_matrix * fixed_rotation).inverse() U = D.inverse() * U0 B = matrix.sqr(crystal.get_B()) a_star = U * B * matrix.col((1,0,0)) b_star = U * B * matrix.col((0,1,0)) c_star = U * B * matrix.col((0,0,1)) color = (1.0, 0.0, 0.0) # red self.draw_axis(a_star.normalize() * 0.5, "a*", color=color) self.draw_axis(b_star.normalize() * 0.5, "b*", color=color) self.draw_axis(c_star.normalize() * 0.5, "c*", color=color)
def __init__(model, m, I, J): model.NB = 1 model.pitch = [J] model.parent = [-1] model.Xtree = [matrix.identity(n=6)] model.I = [featherstone.mcI(m, (0, 0, 0), I)]
def exercise_one_structure( target_structure, flipping_type, anomalous_flag, d_min, grid_resolution_factor=1.0 / 2, verbose=False, amplitude_type="F", ): assert amplitude_type in ("F", "E", "quasi-E") # Generate its structure factors f_target = ( miller.build_set( crystal_symmetry=target_structure, anomalous_flag=target_structure.scatterers().count_anomalous() != 0, d_min=d_min, ) .structure_factors_from_scatterers(xray_structure=target_structure, algorithm="direct") .f_calc() ) f_target_in_p1 = f_target.expand_to_p1().as_non_anomalous_array().merge_equivalents().array() f_obs = f_target.as_amplitude_array() # Unleash charge flipping on the amplitudes flipping = flipping_type(delta=None) extra = group_args() if amplitude_type == "E": extra.normalisations_for = lambda f: f.amplitude_normalisations( target_structure.unit_cell_content(omit=("H", "D")) ) elif amplitude_type == "quasi-E": extra.normalisations_for = charge_flipping.amplitude_quasi_normalisations solving = charge_flipping.solving_iterator( flipping, f_obs, yield_during_delta_guessing=True, yield_solving_interval=1, **extra.__dict__ ) s = StringIO() charge_flipping.loop(solving, verbose="highly", out=s) if verbose: print s.getvalue() # check whether a phase transition has occured assert solving.had_phase_transition flipping = solving.flipping_iterator f_result_in_p1 = solving.flipping_iterator.f_calc # Euclidean matching of the peaks from the obtained map # against those of the correct structure (in P1) target_structure = target_structure.select(target_structure.scattering_types() == "H", negate=True) target_structure_in_p1 = target_structure.expand_to_p1() search_parameters = maptbx.peak_search_parameters( interpolate=True, min_distance_sym_equiv=1.0, max_clusters=int(target_structure_in_p1.scatterers().size() * 1.2) ) peak_search_outcome = flipping.rho_map.peak_search(search_parameters) peak_structure = emma.model( target_structure_in_p1.crystal_symmetry().special_position_settings(), positions=[emma.position("Q%i" % i, x) for i, x in enumerate(peak_search_outcome.all().sites())], ) refined_matches = emma.model_matches( target_structure_in_p1.as_emma_model(), peak_structure, tolerance=0.5, break_if_match_with_no_singles=False ).refined_matches m = refined_matches[0] assert m.rms < 0.2, m.rms # no farther than that assert m.rt.r in (mat.identity(3), mat.inversion(3)) reference_shift = -refined_matches[0].rt.t # Find the translation to bring back the structure to the same space-group # setting as the starting f_obs from correlation map analysis is_allowed = lambda x: f_target.space_group_info().is_allowed_origin_shift(x, tolerance=0.1) first_correct_correlation_peak = None for i, (f_calc, shift, cc_peak_height) in enumerate(solving.f_calc_solutions): if is_allowed(shift - reference_shift) or is_allowed(shift + reference_shift): first_correct_correlation_peak = i break else: if verbose == "more": print "++ Incorrect peak: shift=(%.3f, %.3f, %.3f), height=%.2f" % (tuple(shift) + (cc_peak_height,)) print " Reference shift=(%.3f, %.3f, %.3f)" % tuple(reference_shift) assert first_correct_correlation_peak is not None if verbose and first_correct_correlation_peak != 0: print "** First correct correlation peak: #%i (%.3f) **" % (first_correct_correlation_peak, cc_peak_height) # check Euclidean matching in the original space-group search_parameters = maptbx.peak_search_parameters( interpolate=True, min_distance_sym_equiv=1.0, max_clusters=int(1.5 * target_structure.scatterers().size()) ) solution_fft_map = f_calc.fft_map(symmetry_flags=maptbx.use_space_group_symmetry) solution_peaks = solution_fft_map.peak_search(search_parameters, verify_symmetry=False) solution_peak_structure = emma.model( target_structure.crystal_symmetry().special_position_settings(), positions=[emma.position("Q%i" % i, x) for i, x in enumerate(solution_peaks.all().sites())], ) refined_matches = emma.model_matches( target_structure.as_emma_model(), solution_peak_structure, break_if_match_with_no_singles=False ).refined_matches assert refined_matches m = refined_matches[0] assert not m.singles1, m.show() # all sites match a peak assert m.rms < 0.15, m.rms # no farther than that assert m.rt.r in (mat.identity(3), mat.inversion(3)) # success! if verbose: print "@@ Success @@"
def run(args): from dials.util.options import OptionParser from dials.util.options import flatten_experiments # The script usage usage = "dials.stereographic_projection [options] [param.phil] experiments.json" parser = OptionParser( usage=usage, phil=phil_scope, read_experiments=True, check_format=False, epilog=help_message, ) params, options = parser.parse_args(show_diff_phil=True) experiments = flatten_experiments(params.input.experiments) if not experiments: parser.print_help() return if not params.hkl and params.hkl_limit is None: sys.exit("Please provide hkl or hkl_limit parameters.") if params.hkl is not None and len(params.hkl): miller_indices = flex.miller_index(params.hkl) elif params.hkl_limit is not None: limit = params.hkl_limit miller_indices = flex.miller_index() for h in range(-limit, limit + 1): for k in range(-limit, limit + 1): for l in range(-limit, limit + 1): if (h, k, l) == (0, 0, 0): continue miller_indices.append((h, k, l)) crystals = experiments.crystals() symmetry = crystal.symmetry( unit_cell=crystals[0].get_unit_cell(), space_group=crystals[0].get_space_group() ) miller_set = miller.set(symmetry, miller_indices) d_spacings = miller_set.d_spacings() if params.eliminate_sys_absent: d_spacings = d_spacings.eliminate_sys_absent() if params.expand_to_p1: d_spacings = d_spacings.as_non_anomalous_array().expand_to_p1() d_spacings = d_spacings.generate_bijvoet_mates() miller_indices = d_spacings.indices() # find the greatest common factor (divisor) between miller indices miller_indices_unique = flex.miller_index() for hkl in miller_indices: gcd = gcd_list(hkl) if gcd > 1: miller_indices_unique.append(tuple(int(h / gcd) for h in hkl)) elif gcd < 1: pass else: miller_indices_unique.append(hkl) miller_indices = miller_indices_unique miller_indices = flex.miller_index(list(set(miller_indices))) ref_crystal = crystals[0] U = matrix.sqr(ref_crystal.get_U()) B = matrix.sqr(ref_crystal.get_B()) R = matrix.identity(3) if params.frame == "laboratory": reference_poles = reference_poles_perpendicular_to_beam( experiments[0].beam, experiments[0].goniometer ) if params.use_starting_angle: rotation_axis = matrix.col(experiments[0].goniometer.get_rotation_axis()) R = rotation_axis.axis_and_angle_as_r3_rotation_matrix( experiments[0].scan.get_oscillation()[0], deg=True ) elif params.phi_angle != 0: rotation_axis = matrix.col(experiments[0].goniometer.get_rotation_axis()) R = rotation_axis.axis_and_angle_as_r3_rotation_matrix( params.phi_angle, deg=True ) else: if params.plane_normal is not None: plane_normal = params.plane_normal else: plane_normal = (0, 0, 1) reference_poles = reference_poles_crystal( ref_crystal, plane_normal=plane_normal ) if params.frame == "crystal": U = matrix.identity(3) reciprocal_space_points = list(R * U * B) * miller_indices.as_vec3_double() projections_ref = stereographic_projection(reciprocal_space_points, reference_poles) projections_all = [projections_ref] if experiments: from dials.algorithms.indexing.compare_orientation_matrices import ( difference_rotation_matrix_axis_angle, ) for expt in experiments[1:]: cryst = expt.crystal if params.frame == "crystal": R_ij, axis, angle, cb_op = difference_rotation_matrix_axis_angle( ref_crystal, cryst ) U = R_ij elif params.use_starting_angle: if params.use_starting_angle: rotation_axis = matrix.col(expt.goniometer.get_rotation_axis()) R = rotation_axis.axis_and_angle_as_r3_rotation_matrix( expt.scan.get_oscillation()[0], deg=True ) else: U = matrix.sqr(cryst.get_U()) reciprocal_space_points = ( list(R * U * matrix.sqr(cryst.get_B())) * miller_indices.as_vec3_double() ) projections = stereographic_projection( reciprocal_space_points, reference_poles ) projections_all.append(projections) if params.save_coordinates: with open("projections.txt", "w") as f: f.write("crystal h k l x y" + os.linesep) for i_cryst, projections in enumerate(projections_all): for hkl, proj in zip(miller_indices, projections): f.write("%i " % (i_cryst + 1)) f.write("%i %i %i " % hkl) f.write(("%f %f" + os.linesep) % proj) if params.plot.show or params.plot.filename: epochs = None if params.plot.colour_map is not None: if experiments[0].scan is not None: epochs = [expt.scan.get_epochs()[0] for expt in experiments] else: epochs = [i for i, expt in enumerate(experiments)] plot_projections( projections_all, filename=params.plot.filename, show=params.plot.show, colours=params.plot.colours, marker_size=params.plot.marker_size, font_size=params.plot.font_size, gridsize=params.plot.gridsize, label_indices=params.plot.label_indices, epochs=epochs, colour_map=params.plot.colour_map, ) if params.json.filename: projections_as_json(projections_all, filename=params.json.filename)
def exercise(self): xs0 = self.structure xs = xs0.deep_copy_scatterers() k1, s1, li1, o1, o2 = xs.scatterers() self.shake_point_group_3(k1) self.shake_point_group_3(s1) self.shake_point_group_3(li1) self.shake_point_group_3(o1) o2.site = tuple( [ x*(1 + random.uniform(-self.delta_site, self.delta_site)) for x in o2.site]) o2.u_star = tuple( [ u*(1 + random.uniform(-self.delta_u_star, self.delta_u_star)) for u in o2.u_star]) for sc in xs.scatterers(): sc.flags.set_use_u_iso(False).set_use_u_aniso(True) sc.flags.set_grad_site(True).set_grad_u_aniso(True) connectivity_table = smtbx.utils.connectivity_table(xs) reparametrisation = constraints.reparametrisation( structure=xs, constraints=[], connectivity_table=connectivity_table) ls = least_squares.crystallographic_ls( self.fo_sq.as_xray_observations(), reparametrisation, weighting_scheme=least_squares.unit_weighting(), origin_fixing_restraints_type= origin_fixing_restraints.atomic_number_weighting) cycles = normal_eqns_solving.naive_iterations( ls, gradient_threshold=1e-6, step_threshold=1e-6, track_all=True) ## Test whether refinement brought back the shaked structure to its ## original state match = emma.model_matches(xs0.as_emma_model(), xs.as_emma_model()).refined_matches[0] assert match.rt.r == matrix.identity(3) assert not match.singles1 and not match.singles2 assert match.rms < 1e-6 delta_u_carts= ( xs.scatterers().extract_u_cart(xs.unit_cell()) - xs0.scatterers().extract_u_cart(xs.unit_cell())).norms() assert flex.abs(delta_u_carts) < 1e-6 assert approx_equal(ls.scale_factor(), 1, eps=1e-4) ## Test covariance matrix jac_tr = reparametrisation.jacobian_transpose_matching_grad_fc() cov = ls.covariance_matrix( jacobian_transpose=jac_tr, normalised_by_goof=False)\ .matrix_packed_u_as_symmetric() m, n = cov.accessor().focus() # x,y for point group 3 sites are fixed: no variance or correlation for i in (0, 9, 18, 27,): assert cov.matrix_copy_block(i, 0, 2, n) == 0 # u_star coefficients u13 and u23 for point group 3 sites are fixed # to 0: again no variance or correlation with any other param for i in (7, 16, 25, 34,): assert cov.matrix_copy_block(i, 0, 2, n).as_1d()\ .all_approx_equal(0., 1e-20) # u_star coefficients u11, u22 and u12 for point group 3 sites # are totally correlated, with variances in ratios 1:1:1/2 for i in (3, 12, 21, 30,): assert cov[i, i] != 0 assert approx_equal(cov[i, i], cov[i+1, i+1], eps=1e-15) assert approx_equal(cov[i, i+1]/cov[i, i], 1, eps=1e-12) assert approx_equal(cov[i, i+3]/cov[i, i], 0.5, eps=1e-12)
def exercise_basics(): # construct a simple structure whose sites and u_iso's are to be refined xs = xray.structure(crystal_symmetry=crystal.symmetry( unit_cell=(10, 10, 10, 90, 90, 90), space_group_symbol='hall: P 1'), scatterers=flex.xray_scatterer(( xray.scatterer('C0', site=(0, -1 / 2, 0), u=0.1), xray.scatterer('C1', site=(0, 1 / 2, 0), u=0.2), xray.scatterer('C0a', site=(1 / 2, 0, 0), u=0.1), xray.scatterer('C1a', site=(-1 / 2, 0, 0), u=0.2), ))) for sc in xs.scatterers(): sc.flags.set_grad_site(True) sc.flags.set_grad_u_iso(True) # copy the original structure as a reference to test against later xs_ref = xs.deep_copy_scatterers() # mess up the symmetries that the forthcoming constraints shall impose c0, c1, c0a, c1a = xs.scatterers() c0a.site = (0, 0, 0) c1a.site = (1 / 2, 1 / 2, 1 / 2) c0a.u_iso = 0.5 c1a.u_iso = 0.6 # construct a reparametrisation for the following constraints: # (C0a, C1a) is the image of (C0, C1) through a rotation of 90 degrees # about the z-axis r = constraints.ext.reparametrisation(xs.unit_cell()) sc_params = constraints.shared_scatterer_parameters(xs.scatterers()) c0_site_param = r.add(constraints.independent_site_parameter, c0) sc_params[0].site = c0_site_param c1_site_param = r.add(constraints.independent_site_parameter, c1) sc_params[1].site = c1_site_param move_param = r.add(constraints.independent_small_6_vector_parameter, (0, 0, 0, 0, 0, math.pi / 2)) c0a_c1a_site_param = r.add(constraints.same_group_xyz, scatterers=(c0a, c1a), sites=(c0_site_param, c1_site_param), alignment_matrix=matrix.identity(3), shifts_and_angles=move_param) sc_params[2].site = sc_params[3].site = c0a_c1a_site_param c0_u_iso_param = r.add(constraints.independent_u_iso_parameter, c0) sc_params[0].u = c0_u_iso_param c1_u_iso_param = r.add(constraints.independent_u_iso_parameter, c1) sc_params[1].u = c1_u_iso_param c0a_c1a_u_iso_param = r.add(constraints.same_group_u_iso, scatterers=(c0a, c1a), u_isos=(c0_u_iso_param, c1_u_iso_param)) sc_params[2].u = sc_params[3].u = c0a_c1a_u_iso_param r.finalise() # put the reparametrisation to work r.linearise() r.store() c0_ref, c1_ref, c0a_ref, c1a_ref = xs_ref.scatterers() assert approx_equal(c0a.site, c0a_ref.site, eps=1e-12) assert approx_equal(c1a.site, c1a_ref.site, eps=1e-12) assert approx_equal(c0a.u_iso, c0a_ref.u_iso, eps=1e-12) assert approx_equal(c1a.u_iso, c1a_ref.u_iso, eps=1e-12) # check that origin fixing restraints work in the presence of # that reparametrisation # this is a regression test as they used not to (bug reported by Oleg) from smtbx.refinement.restraints import origin_fixing_restraints from scitbx import lstbx orig_fixing = origin_fixing_restraints.homogeneous_weighting( xs.space_group()) normal_eqn = lstbx.normal_eqns.ext.linear_ls(n_parameters=(3 + 1) * 2 + 6) jacobian_transpose_matching_grad_fc = r.jacobian_transpose_matching( sc_params.mapping_to_grad_fc()) orig_fixing.add_to(normal_eqn, jacobian_transpose_matching_grad_fc, sc_params)
def align_reference_frame(primary_axis, primary_target, secondary_axis, secondary_target): '''Compute a rotation matrix R: R x primary_axis = primary_target and R x secondary_axis places the secondary_axis in the plane perpendicular to the primary_target, as close as possible to the secondary_target. Require: primary_target orthogonal to secondary_target, primary axis not colinear with secondary axis.''' if type(primary_axis) == type(()) or type(primary_axis) == type([]): primary_axis = matrix.col(primary_axis).normalize() else: primary_axis = primary_axis.normalize() if type(primary_target) == type(()) or type(primary_target) == type([]): primary_target = matrix.col(primary_target).normalize() else: primary_target = primary_target.normalize() if type(secondary_axis) == type(()) or type(secondary_axis) == type([]): secondary_axis = matrix.col(secondary_axis).normalize() else: secondary_axis = secondary_axis.normalize() if type(secondary_target) == type(()) or \ type(secondary_target) == type([]): secondary_target = matrix.col(secondary_target).normalize() else: secondary_target = secondary_target.normalize() # check properties of input axes assert(math.fabs(primary_axis.angle(secondary_axis) % math.pi) > 0.001) assert(primary_target.dot(secondary_target) < 0.001) if primary_target.angle(primary_axis) % math.pi: axis_p = primary_target.cross(primary_axis) angle_p = - primary_target.angle(primary_axis) Rprimary = axis_p.axis_and_angle_as_r3_rotation_matrix(angle_p) elif primary_target.dot(primary_axis) < 0: axis_p = primary_axis.ortho().normalize() angle_p = math.pi Rprimary = axis_p.axis_and_angle_as_r3_rotation_matrix(angle_p) else: Rprimary = matrix.identity(3) if math.fabs(secondary_target.angle(Rprimary * secondary_axis)) < 1.0e-6: Rsecondary = matrix.identity(3) else: axis_r = secondary_target.cross(Rprimary * secondary_axis) axis_s = primary_target if (axis_r.angle(primary_target) > 0.5 * math.pi): angle_s = orthogonal_component(axis_s, secondary_target).angle( orthogonal_component(axis_s, Rprimary * secondary_axis)) else: angle_s = - orthogonal_component(axis_s, secondary_target).angle( orthogonal_component(axis_s, Rprimary * secondary_axis)) Rsecondary = axis_s.axis_and_angle_as_r3_rotation_matrix(angle_s) return Rsecondary * Rprimary
def exercise(self): xs0 = self.structure xs = xs0.deep_copy_scatterers() k1, s1, li1, o1, o2 = xs.scatterers() self.shake_point_group_3(k1) self.shake_point_group_3(s1) self.shake_point_group_3(li1) self.shake_point_group_3(o1) o2.site = tuple( [ x*(1 + random.uniform(-self.delta_site, self.delta_site)) for x in o2.site]) o2.u_star = tuple( [ u*(1 + random.uniform(-self.delta_u_star, self.delta_u_star)) for u in o2.u_star]) for sc in xs.scatterers(): sc.flags.set_use_u_iso(False).set_use_u_aniso(True) sc.flags.set_grad_site(True).set_grad_u_aniso(True) connectivity_table = smtbx.utils.connectivity_table(xs) reparametrisation = constraints.reparametrisation( structure=xs, constraints=[], connectivity_table=connectivity_table) ls = least_squares.crystallographic_ls( self.fo_sq.as_xray_observations(), reparametrisation, weighting_scheme=least_squares.unit_weighting(), origin_fixing_restraints_type= origin_fixing_restraints.atomic_number_weighting) cycles = normal_eqns_solving.levenberg_marquardt_iterations( ls, gradient_threshold=1e-12, step_threshold=1e-7, track_all=True) ## Test whether refinement brought back the shaked structure to its ## original state match = emma.model_matches(xs0.as_emma_model(), xs.as_emma_model()).refined_matches[0] assert match.rt.r == matrix.identity(3) assert not match.singles1 and not match.singles2 assert match.rms < 1e-6 delta_u_carts= ( xs.scatterers().extract_u_cart(xs.unit_cell()) - xs0.scatterers().extract_u_cart(xs.unit_cell())).norms() assert flex.abs(delta_u_carts) < 1e-6 assert approx_equal(ls.scale_factor(), 1, eps=1e-4) ## Test covariance matrix jac_tr = reparametrisation.jacobian_transpose_matching_grad_fc() cov = ls.covariance_matrix( jacobian_transpose=jac_tr, normalised_by_goof=False)\ .matrix_packed_u_as_symmetric() m, n = cov.accessor().focus() # x,y for point group 3 sites are fixed: no variance or correlation for i in (0, 9, 18, 27,): assert cov.matrix_copy_block(i, 0, 2, n) == 0 # u_star coefficients u13 and u23 for point group 3 sites are fixed # to 0: again no variance or correlation with any other param for i in (7, 16, 25, 34,): assert cov.matrix_copy_block(i, 0, 2, n).as_1d()\ .all_approx_equal(0., 1e-20) # u_star coefficients u11, u22 and u12 for point group 3 sites # are totally correlated, with variances in ratios 1:1:1/2 for i in (3, 12, 21, 30,): assert cov[i, i] != 0 assert approx_equal(cov[i, i], cov[i+1, i+1], eps=1e-15) assert approx_equal(cov[i, i+1]/cov[i, i], 1, eps=1e-12) assert approx_equal(cov[i, i+3]/cov[i, i], 0.5, eps=1e-12)
def exercise_one_structure( target_structure, flipping_type, anomalous_flag, d_min, grid_resolution_factor=1. / 2, verbose=False, amplitude_type="F", ): assert amplitude_type in ('F', 'E', 'quasi-E') # Generate its structure factors f_target = miller.build_set( crystal_symmetry=target_structure, anomalous_flag=target_structure.scatterers().count_anomalous() != 0, d_min=d_min).structure_factors_from_scatterers( xray_structure=target_structure, algorithm="direct").f_calc() f_target_in_p1 = f_target.expand_to_p1()\ .as_non_anomalous_array()\ .merge_equivalents().array() f_obs = f_target.as_amplitude_array() # Unleash charge flipping on the amplitudes flipping = flipping_type(delta=None) extra = group_args() if amplitude_type == 'E': extra.normalisations_for = lambda f: f.amplitude_normalisations( target_structure.unit_cell_content(omit=('H', 'D'))) elif amplitude_type == 'quasi-E': extra.normalisations_for = charge_flipping.amplitude_quasi_normalisations solving = charge_flipping.solving_iterator( flipping, f_obs, yield_during_delta_guessing=True, yield_solving_interval=1, **extra.__dict__) s = StringIO() charge_flipping.loop(solving, verbose="highly", out=s) if verbose: print s.getvalue() # check whether a phase transition has occured assert solving.had_phase_transition flipping = solving.flipping_iterator f_result_in_p1 = solving.flipping_iterator.f_calc # Euclidean matching of the peaks from the obtained map # against those of the correct structure (in P1) target_structure = target_structure.select( target_structure.scattering_types() == "H", negate=True) target_structure_in_p1 = target_structure.expand_to_p1() search_parameters = maptbx.peak_search_parameters( interpolate=True, min_distance_sym_equiv=1., max_clusters=int(target_structure_in_p1.scatterers().size() * 1.2)) peak_search_outcome = flipping.rho_map.peak_search(search_parameters) peak_structure = emma.model( target_structure_in_p1.crystal_symmetry().special_position_settings(), positions=[ emma.position('Q%i' % i, x) for i, x in enumerate(peak_search_outcome.all().sites()) ]) refined_matches = emma.model_matches( target_structure_in_p1.as_emma_model(), peak_structure, tolerance=0.5, break_if_match_with_no_singles=False).refined_matches m = refined_matches[0] assert m.rms < 0.2, m.rms # no farther than that assert m.rt.r in (mat.identity(3), mat.inversion(3)) reference_shift = -refined_matches[0].rt.t # Find the translation to bring back the structure to the same space-group # setting as the starting f_obs from correlation map analysis is_allowed = lambda x: f_target.space_group_info().is_allowed_origin_shift( x, tolerance=0.1) first_correct_correlation_peak = None for i, (f_calc, shift, cc_peak_height) in enumerate(solving.f_calc_solutions): if (is_allowed(shift - reference_shift) or is_allowed(shift + reference_shift)): first_correct_correlation_peak = i break else: if verbose == "more": print "++ Incorrect peak: shift=(%.3f, %.3f, %.3f), height=%.2f"\ % (tuple(shift)+(cc_peak_height,)) print " Reference shift=(%.3f, %.3f, %.3f)" % tuple( reference_shift) assert first_correct_correlation_peak is not None if verbose and first_correct_correlation_peak != 0: print "** First correct correlation peak: #%i (%.3f) **"\ % (first_correct_correlation_peak, cc_peak_height) # check Euclidean matching in the original space-group search_parameters = maptbx.peak_search_parameters( interpolate=True, min_distance_sym_equiv=1., max_clusters=int(1.5 * target_structure.scatterers().size())) solution_fft_map = f_calc.fft_map( symmetry_flags=maptbx.use_space_group_symmetry) solution_peaks = solution_fft_map.peak_search(search_parameters, verify_symmetry=False) solution_peak_structure = emma.model( target_structure.crystal_symmetry().special_position_settings(), positions=[ emma.position('Q%i' % i, x) for i, x in enumerate(solution_peaks.all().sites()) ]) refined_matches = emma.model_matches( target_structure.as_emma_model(), solution_peak_structure, break_if_match_with_no_singles=False).refined_matches assert refined_matches m = refined_matches[0] assert not m.singles1, m.show() # all sites match a peak assert m.rms < 0.15, m.rms # no farther than that assert m.rt.r in (mat.identity(3), mat.inversion(3)) # success! if verbose: print "@@ Success @@"
def exercise_basics(): # construct a simple structure whose sites and u_iso's are to be refined xs = xray.structure( crystal_symmetry=crystal.symmetry( unit_cell=(10, 10, 10, 90, 90, 90), space_group_symbol='hall: P 1'), scatterers=flex.xray_scatterer(( xray.scatterer('C0', site=(0, -1/2, 0), u=0.1), xray.scatterer('C1', site=(0, 1/2, 0), u=0.2), xray.scatterer('C0a', site=( 1/2, 0, 0), u=0.1), xray.scatterer('C1a', site=(-1/2, 0, 0), u=0.2), ))) for sc in xs.scatterers(): sc.flags.set_grad_site(True) sc.flags.set_grad_u_iso(True) # copy the original structure as a reference to test against later xs_ref = xs.deep_copy_scatterers() # mess up the symmetries that the forthcoming constraints shall impose c0, c1, c0a, c1a = xs.scatterers() c0a.site = (0, 0, 0) c1a.site = (1/2, 1/2, 1/2) c0a.u_iso = 0.5 c1a.u_iso = 0.6 # construct a reparametrisation for the following constraints: # (C0a, C1a) is the image of (C0, C1) through a rotation of 90 degrees # about the z-axis r = constraints.ext.reparametrisation(xs.unit_cell()) sc_params = constraints.shared_scatterer_parameters(xs.scatterers()) c0_site_param = r.add(constraints.independent_site_parameter, c0) sc_params[0].site = c0_site_param c1_site_param = r.add(constraints.independent_site_parameter, c1) sc_params[1].site = c1_site_param move_param = r.add( constraints.independent_small_6_vector_parameter, (0,0,0, 0, 0, math.pi/2)) c0a_c1a_site_param = r.add( constraints.same_group_xyz, scatterers=(c0a, c1a), sites=(c0_site_param, c1_site_param), alignment_matrix=matrix.identity(3), shifts_and_angles=move_param) sc_params[2].site = sc_params[3].site = c0a_c1a_site_param c0_u_iso_param = r.add(constraints.independent_u_iso_parameter, c0) sc_params[0].u = c0_u_iso_param c1_u_iso_param = r.add(constraints.independent_u_iso_parameter, c1) sc_params[1].u = c1_u_iso_param c0a_c1a_u_iso_param = r.add( constraints.same_group_u_iso, scatterers=(c0a, c1a), u_isos=(c0_u_iso_param, c1_u_iso_param)) sc_params[2].u = sc_params[3].u = c0a_c1a_u_iso_param r.finalise() # put the reparametrisation to work r.linearise() r.store() c0_ref, c1_ref, c0a_ref, c1a_ref = xs_ref.scatterers() assert approx_equal(c0a.site, c0a_ref.site, eps=1e-12) assert approx_equal(c1a.site, c1a_ref.site, eps=1e-12) assert approx_equal(c0a.u_iso, c0a_ref.u_iso, eps=1e-12) assert approx_equal(c1a.u_iso, c1a_ref.u_iso, eps=1e-12) # check that origin fixing restraints work in the presence of # that reparametrisation # this is a regression test as they used not to (bug reported by Oleg) from smtbx.refinement.restraints import origin_fixing_restraints from scitbx import lstbx orig_fixing = origin_fixing_restraints.homogeneous_weighting(xs.space_group()) normal_eqn = lstbx.normal_eqns.ext.linear_ls(n_parameters=(3 + 1)*2 + 6) jacobian_transpose_matching_grad_fc = r.jacobian_transpose_matching( sc_params.mapping_to_grad_fc()) orig_fixing.add_to(normal_eqn, jacobian_transpose_matching_grad_fc, sc_params)