def get_UBlattsymm_from_sweep_info(self, sweep_info): """Calculate U, B and lattice symmetry from experiment.""" expt = load.experiment_list(sweep_info.get_experiments())[0] uc = expt.crystal.get_unit_cell() umatrix = expt.crystal.get_U() lattice_symm = lattice_symmetry_group(uc, max_delta=0.0) return tuple(umatrix), mosflm_B_matrix(uc), lattice_symm
def lattice_group_info(self): # Get highest symmetry compatible with lattice lattice_group = sgtbx.lattice_symmetry_group( self.minimum_symmetry.unit_cell(), max_delta=self.max_delta, enforce_max_delta_for_generated_two_folds=self. enforce_max_delta_for_generated_two_folds) return sgtbx.space_group_info(group=lattice_group)
def lattice_group_info(self): # Get highest symmetry compatible with lattice lattice_group = sgtbx.lattice_symmetry_group( self.minimum_symmetry.unit_cell(), max_delta=self.max_delta, enforce_max_delta_for_generated_two_folds =self.enforce_max_delta_for_generated_two_folds) return sgtbx.space_group_info(group=lattice_group)
def lattice_symmetry_group(self, max_delta=3, enforce_max_delta_for_generated_two_folds=True): from cctbx import sgtbx return sgtbx.lattice_symmetry_group( reduced_cell=self, max_delta=max_delta, enforce_max_delta_for_generated_two_folds =enforce_max_delta_for_generated_two_folds)
def get_umat_bmat_lattice_symmetry_from_mtz(mtz_file): """Get the U matrix and lattice symmetry derived from the unit cell constants from an MTZ file.""" m = mtz.object(mtz_file) # assert first U matrix from batches is OK uc = m.crystals()[0].unit_cell() lattice_symm = lattice_symmetry_group(uc, max_delta=0.0) return tuple(m.batches()[0].umat()), mosflm_B_matrix(uc), lattice_symm
def get_umat_bmat_lattice_symmetry_from_mtz(mtz_file): '''Get the U matrix and lattice symmetry derived from the unit cell constants from an MTZ file.''' from iotbx import mtz m = mtz.object(mtz_file) # assert first U matrix from batches is OK uc = m.crystals()[0].unit_cell() from cctbx.sgtbx import lattice_symmetry_group lattice_symm = lattice_symmetry_group(uc, max_delta=0.0) return tuple(m.batches()[0].umat()), mosflm_B_matrix(uc), lattice_symm
def run(args): import libtbx.load_env from scitbx import matrix from cctbx.sgtbx import lattice_symmetry_group from scitbx.math import r3_rotation_axis_and_angle_from_matrix usage = "%s [options] experiment_0.expt ..." % 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 = params.input.experiments # check input space_group = None for experiment in experiments: assert len(experiment.data.goniometers()) == 1 assert len(experiment.data.crystals()) == 1 crystal = experiment.data.crystals()[0] if space_group is None: space_group = crystal.get_space_group() else: assert crystal.get_space_group() == space_group reference_U = None reference_space_group = None for j, experiment in enumerate(experiments): goniometer = experiment.data.goniometers()[0] F = matrix.sqr(goniometer.get_fixed_rotation()) crystal = experiment.data.crystals()[0] U = matrix.sqr(crystal.get_U()) B = matrix.sqr(crystal.get_B()) UB = F * U * B UBt = UB.transpose().elems a, b, c = matrix.col(UBt[0:3]), matrix.col(UBt[3:6]), matrix.col( UBt[6:9]) axis = matrix.col(goniometer.get_rotation_axis()) from math import pi r2d = 180 / pi abc = [a, b, c] abc_names = "abc" distances = [(r2d * (min(axis.angle(_a), pi - axis.angle(_a))), k) for k, _a in enumerate(abc)] close = sorted(distances)[0] if reference_U is None: reference_U = U reference_space_group = lattice_symmetry_group( crystal.get_unit_cell(), max_delta=0.0) print("%s possible lattice ops" % len(reference_space_group.all_ops())) print("Experiment %d" % j) print("Closest (original) axis: %s* %.2f" % (abc_names[close[1]], close[0])) results = [] for op in reference_space_group.all_ops(): R = B * matrix.sqr(op.r().as_double()).transpose() * B.inverse() relative = (U * R).inverse() * reference_U rot = r3_rotation_axis_and_angle_from_matrix(relative) results.append((abs(rot.angle()), op.r().as_hkl(), rot)) results.sort() print("Best reindex op for experiment %d: %12s (%.3f)" % (j, results[0][1], 180.0 * results[0][2].angle() / pi)) if results[0][0] > (5 * pi / 180.0): print("Rotation: axis: %.4f %.4f %.4f" % results[0][2].axis) print(" angle: %.4f degrees" % (180.0 * results[0][2].angle() / pi))
def find_matching_symmetry(unit_cell, target_space_group, max_delta=5): cs = crystal.symmetry(unit_cell=unit_cell, space_group=sgtbx.space_group()) target_bravais_t = bravais_types.bravais_lattice( group=target_space_group.info().reference_setting().group()) best_subgroup = None best_angular_difference = 1e8 # code based on cctbx/sgtbx/lattice_symmetry.py but optimised to only # look at subgroups with the correct bravais type input_symmetry = cs # Get cell reduction operator cb_op_inp_minimum = input_symmetry.change_of_basis_op_to_minimum_cell() # New symmetry object with changed basis minimum_symmetry = input_symmetry.change_basis(cb_op_inp_minimum) # Get highest symmetry compatible with lattice lattice_group = sgtbx.lattice_symmetry_group( minimum_symmetry.unit_cell(), max_delta=max_delta, enforce_max_delta_for_generated_two_folds=True) # Get list of sub-spacegroups subgrs = subgroups.subgroups(lattice_group.info()).groups_parent_setting() # Order sub-groups sort_values = flex.double() for group in subgrs: order_z = group.order_z() space_group_number = sgtbx.space_group_type(group, False).number() assert 1 <= space_group_number <= 230 sort_values.append(order_z * 1000 + space_group_number) perm = flex.sort_permutation(sort_values, True) for i_subgr in perm: acentric_subgroup = subgrs[i_subgr] acentric_supergroup = metric_supergroup(acentric_subgroup) ## Add centre of inversion to acentric lattice symmetry #centric_group = sgtbx.space_group(acentric_subgroup) #centric_group.expand_inv(sgtbx.tr_vec((0,0,0))) # Make symmetry object: unit-cell + space-group # The unit cell is potentially modified to be exactly compatible # with the space group symmetry. subsym = crystal.symmetry(unit_cell=minimum_symmetry.unit_cell(), space_group=acentric_subgroup, assert_is_compatible_unit_cell=False) #supersym = crystal.symmetry( #unit_cell=minimum_symmetry.unit_cell(), #space_group=acentric_supergroup, #assert_is_compatible_unit_cell=False) # Convert subgroup to reference setting cb_op_minimum_ref = subsym.space_group_info().type().cb_op() ref_subsym = subsym.change_basis(cb_op_minimum_ref) # Ignore unwanted groups bravais_t = bravais_types.bravais_lattice( group=ref_subsym.space_group()) if bravais_t != target_bravais_t: continue # Choose best setting for monoclinic and orthorhombic systems cb_op_best_cell = ref_subsym.change_of_basis_op_to_best_cell( best_monoclinic_beta=True) best_subsym = ref_subsym.change_basis(cb_op_best_cell) # Total basis transformation cb_op_best_cell = change_of_basis_op(str(cb_op_best_cell), stop_chars='', r_den=144, t_den=144) cb_op_minimum_ref = change_of_basis_op(str(cb_op_minimum_ref), stop_chars='', r_den=144, t_den=144) cb_op_inp_minimum = change_of_basis_op(str(cb_op_inp_minimum), stop_chars='', r_den=144, t_den=144) cb_op_inp_best = cb_op_best_cell * cb_op_minimum_ref * cb_op_inp_minimum # Use identity change-of-basis operator if possible if best_subsym.unit_cell().is_similar_to(input_symmetry.unit_cell()): cb_op_corr = cb_op_inp_best.inverse() try: best_subsym_corr = best_subsym.change_basis(cb_op_corr) except RuntimeError as e: if str(e).find( "Unsuitable value for rational rotation matrix.") < 0: raise else: if best_subsym_corr.space_group() == best_subsym.space_group(): cb_op_inp_best = cb_op_corr * cb_op_inp_best max_angular_difference = find_max_delta( reduced_cell=minimum_symmetry.unit_cell(), space_group=acentric_supergroup) if max_angular_difference < best_angular_difference: #best_subgroup = subgroup best_angular_difference = max_angular_difference best_subgroup = { 'subsym': subsym, #'supersym':supersym, 'ref_subsym': ref_subsym, 'best_subsym': best_subsym, 'cb_op_inp_best': cb_op_inp_best, 'max_angular_difference': max_angular_difference } if best_subgroup is not None: return best_subgroup
def find_matching_symmetry(unit_cell, target_space_group, max_delta=5): cs = crystal.symmetry(unit_cell=unit_cell, space_group=sgtbx.space_group()) target_bravais_t = bravais_types.bravais_lattice( group=target_space_group.info().reference_setting().group()) best_subgroup = None best_angular_difference = 1e8 # code based on cctbx/sgtbx/lattice_symmetry.py but optimised to only # look at subgroups with the correct bravais type input_symmetry = cs # Get cell reduction operator cb_op_inp_minimum = input_symmetry.change_of_basis_op_to_minimum_cell() # New symmetry object with changed basis minimum_symmetry = input_symmetry.change_basis(cb_op_inp_minimum) # Get highest symmetry compatible with lattice lattice_group = sgtbx.lattice_symmetry_group( minimum_symmetry.unit_cell(), max_delta=max_delta, enforce_max_delta_for_generated_two_folds=True) # Get list of sub-spacegroups subgrs = subgroups.subgroups(lattice_group.info()).groups_parent_setting() # Order sub-groups sort_values = flex.double() for group in subgrs: order_z = group.order_z() space_group_number = sgtbx.space_group_type(group, False).number() assert 1 <= space_group_number <= 230 sort_values.append(order_z*1000+space_group_number) perm = flex.sort_permutation(sort_values, True) for i_subgr in perm: acentric_subgroup = subgrs[i_subgr] acentric_supergroup = metric_supergroup(acentric_subgroup) ## Add centre of inversion to acentric lattice symmetry #centric_group = sgtbx.space_group(acentric_subgroup) #centric_group.expand_inv(sgtbx.tr_vec((0,0,0))) # Make symmetry object: unit-cell + space-group # The unit cell is potentially modified to be exactly compatible # with the space group symmetry. subsym = crystal.symmetry( unit_cell=minimum_symmetry.unit_cell(), space_group=acentric_subgroup, assert_is_compatible_unit_cell=False) #supersym = crystal.symmetry( #unit_cell=minimum_symmetry.unit_cell(), #space_group=acentric_supergroup, #assert_is_compatible_unit_cell=False) # Convert subgroup to reference setting cb_op_minimum_ref = subsym.space_group_info().type().cb_op() ref_subsym = subsym.change_basis(cb_op_minimum_ref) # Ignore unwanted groups bravais_t = bravais_types.bravais_lattice( group=ref_subsym.space_group()) if bravais_t != target_bravais_t: continue # Choose best setting for monoclinic and orthorhombic systems cb_op_best_cell = ref_subsym.change_of_basis_op_to_best_cell( best_monoclinic_beta=True) best_subsym = ref_subsym.change_basis(cb_op_best_cell) # Total basis transformation cb_op_best_cell = change_of_basis_op(str(cb_op_best_cell),stop_chars='',r_den=144,t_den=144) cb_op_minimum_ref=change_of_basis_op(str(cb_op_minimum_ref),stop_chars='',r_den=144,t_den=144) cb_op_inp_minimum=change_of_basis_op(str(cb_op_inp_minimum),stop_chars='',r_den=144,t_den=144) cb_op_inp_best = cb_op_best_cell * cb_op_minimum_ref * cb_op_inp_minimum # Use identity change-of-basis operator if possible if (best_subsym.unit_cell().is_similar_to(input_symmetry.unit_cell())): cb_op_corr = cb_op_inp_best.inverse() try: best_subsym_corr = best_subsym.change_basis(cb_op_corr) except RuntimeError, e: if (str(e).find("Unsuitable value for rational rotation matrix.") < 0): raise else: if (best_subsym_corr.space_group() == best_subsym.space_group()): cb_op_inp_best = cb_op_corr * cb_op_inp_best max_angular_difference = find_max_delta( reduced_cell=minimum_symmetry.unit_cell(), space_group=acentric_supergroup) if max_angular_difference < best_angular_difference: #best_subgroup = subgroup best_angular_difference = max_angular_difference best_subgroup = {'subsym':subsym, #'supersym':supersym, 'ref_subsym':ref_subsym, 'best_subsym':best_subsym, 'cb_op_inp_best':cb_op_inp_best, 'max_angular_difference':max_angular_difference }
def run(args): import libtbx.load_env from scitbx import matrix from cctbx.sgtbx import lattice_symmetry_group from scitbx.math import r3_rotation_axis_and_angle_from_matrix usage = "%s [options] experiment_0.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 = params.input.experiments # check input space_group = None for experiment in experiments: assert(len(experiment.data.goniometers()) == 1) assert(len(experiment.data.crystals()) == 1) crystal = experiment.data.crystals()[0] if space_group is None: space_group = crystal.get_space_group() else: assert(crystal.get_space_group() == space_group) reference_U = None reference_space_group = None for j, experiment in enumerate(experiments): goniometer = experiment.data.goniometers()[0] F = matrix.sqr(goniometer.get_fixed_rotation()) crystal = experiment.data.crystals()[0] U = matrix.sqr(crystal.get_U()) B = matrix.sqr(crystal.get_B()) UB = F * U * B UBt = UB.transpose().elems a, b, c = matrix.col(UBt[0:3]), matrix.col(UBt[3:6]), matrix.col(UBt[6:9]) axis = matrix.col(goniometer.get_rotation_axis()) from math import pi r2d = 180 / pi abc = [a, b, c] abc_names = 'abc' distances = [(r2d * (min(axis.angle(_a), pi - axis.angle(_a))), k) for k, _a in enumerate(abc)] close = sorted(distances)[0] if reference_U is None: reference_U = U reference_space_group = lattice_symmetry_group(crystal.get_unit_cell(), max_delta=0.0) print '%s possible lattice ops' % len(reference_space_group.all_ops()) print 'Experiment %d' % j print 'Closest (original) axis: %s* %.2f' % \ (abc_names[close[1]], close[0]) results = [] for op in reference_space_group.all_ops(): R = B * matrix.sqr(op.r().as_double()).transpose() * B.inverse() relative = (U * R).inverse() * reference_U rot = r3_rotation_axis_and_angle_from_matrix(relative) results.append((abs(rot.angle()), op.r().as_hkl(), rot)) results.sort() print 'Best reindex op for experiment %d: %12s (%.3f)' % \ (j, results[0][1], 180.0 * results[0][2].angle() / pi) if results[0][0] > (5 * pi / 180.0): print 'Rotation: axis: %.4f %.4f %.4f' % results[0][2].axis print ' angle: %.4f degrees' % \ (180.0 * results[0][2].angle() / pi)