def _map_space_group_to_input_cell(intensities, space_group): best_subgroup = find_matching_symmetry(intensities.unit_cell(), space_group) cb_op_inp_best = best_subgroup["cb_op_inp_best"] best_subsym = best_subgroup["best_subsym"] cb_op_best_ref = best_subsym.change_of_basis_op_to_reference_setting( ) ref_subsym = best_subsym.change_basis(cb_op_best_ref) cb_op_ref_primitive = ( ref_subsym.change_of_basis_op_to_primitive_setting()) sg_cb_op_inp_primitive = (space_group.info( ).change_of_basis_op_to_primitive_setting()) sg_primitive = space_group.change_basis(sg_cb_op_inp_primitive) sg_best = sg_primitive.change_basis( (cb_op_ref_primitive * cb_op_best_ref).inverse()) # best_subgroup above is the bravais type, so create thin copy here with the # user-input space group instead best_subgroup = { "best_subsym": best_subsym.customized_copy( space_group_info=sg_best.info()), "cb_op_inp_best": cb_op_inp_best, } intensities = intensities.customized_copy( space_group_info=sg_best.change_basis( cb_op_inp_best.inverse()).info()) return intensities, best_subgroup
def _map_space_group_to_input_cell(intensities, space_group): from cctbx.sgtbx.bravais_types import bravais_lattice best_subgroup = find_matching_symmetry( intensities.unit_cell(), space_group, best_monoclinic_beta=str( bravais_lattice(group=space_group)) == "mI", ) cb_op_inp_best = best_subgroup["cb_op_inp_best"] best_subsym = best_subgroup["best_subsym"] cb_op_best_primitive = ( best_subsym.change_of_basis_op_to_primitive_setting()) sg_cb_op_inp_primitive = (space_group.info( ).change_of_basis_op_to_primitive_setting()) sg_primitive = space_group.change_basis(sg_cb_op_inp_primitive) sg_best = sg_primitive.change_basis( cb_op_best_primitive.inverse()) # best_subgroup above is the bravais type, so create thin copy here with the # user-input space group instead best_subsym = best_subsym.customized_copy( space_group_info=sg_best.info()) best_subgroup = { "subsym": best_subsym.change_basis(cb_op_inp_best.inverse()), "best_subsym": best_subsym, "cb_op_inp_best": cb_op_inp_best, } intensities = intensities.customized_copy( space_group_info=sg_best.change_basis( cb_op_inp_best.inverse()).info()) return intensities, best_subgroup
def test_combinations(setup_rlp): max_cell = 1.3 * max( setup_rlp["crystal_symmetry"].unit_cell().parameters()[:3]) strategy = FFT1D(max_cell) basis_vectors, used = strategy.find_basis_vectors(setup_rlp["rlp"]) target_symmetry_primitive = ( setup_rlp["crystal_symmetry"].primitive_setting().customized_copy( space_group_info=sgtbx.space_group().info())) target_symmetry_sg_only = ( setup_rlp["crystal_symmetry"].primitive_setting().customized_copy( unit_cell=None)) target_symmetry_ref = setup_rlp["crystal_symmetry"].as_reference_setting() for target_symmetry in ( setup_rlp["crystal_symmetry"], target_symmetry_primitive, target_symmetry_sg_only, target_symmetry_ref, ): crystal_models = combinations.candidate_orientation_matrices( basis_vectors, max_combinations=50) crystal_models = list(crystal_models) filtered_crystal_models = combinations.filter_known_symmetry( crystal_models, target_symmetry=target_symmetry) filtered_crystal_models = list(filtered_crystal_models) assert filtered_crystal_models for model in filtered_crystal_models: best_subgroup = find_matching_symmetry( model.get_unit_cell(), target_symmetry.space_group()) if target_symmetry.unit_cell() is not None: assert best_subgroup["best_subsym"].unit_cell().is_similar_to( setup_rlp["crystal_symmetry"].as_reference_setting(). best_cell().unit_cell(), relative_length_tolerance=0.1, absolute_angle_tolerance=5, ) or best_subgroup["best_subsym"].minimum_cell().unit_cell( ).is_similar_to( setup_rlp["crystal_symmetry"].as_reference_setting(). best_cell().minimum_cell().unit_cell(), relative_length_tolerance=0.1, absolute_angle_tolerance=5, ) else: target_sg = (target_symmetry.space_group_info(). reference_setting().group()) from cctbx.sgtbx.lattice_symmetry import metric_subgroups subgroups = metric_subgroups(model.get_crystal_symmetry(), max_delta=5, bravais_types_only=False) if not target_sg.build_derived_patterson_group() in [ g["ref_subsym"].space_group() for g in subgroups.result_groups ]: assert 0
def filter_known_symmetry( crystal_models, target_symmetry, relative_length_tolerance=0.1, absolute_angle_tolerance=5, max_delta=5, ): """Filter crystal models for known symmetry. Args: crystal_models (list): A list of :class:`dxtbx.model.Crystal` objects. target_symmetry (cctbx.crystal.symmetry): The target symmetry for filtering. relative_length_tolerance (float): Relative tolerance for unit cell lengths in unit cell comparison (default value is 0.1). absolute_angle_tolerance (float): Angular tolerance (in degrees) in unit cell comparison (default value is 5). max_delta (float): Maximum allowed Le Page delta used in searching for basis vector combinations that are consistent with the given symmetry (default value is 5). """ n_matched = 0 cb_op_ref_to_primitive = target_symmetry.change_of_basis_op_to_primitive_setting( ) if target_symmetry.unit_cell() is not None: target_symmetry_primitive = target_symmetry.change_basis( cb_op_ref_to_primitive) else: target_symmetry_primitive = target_symmetry.customized_copy( space_group_info=target_symmetry.space_group_info().change_basis( cb_op_ref_to_primitive)) for model in crystal_models: uc = model.get_unit_cell() best_subgroup = find_matching_symmetry( uc, target_symmetry_primitive.space_group(), max_delta=max_delta) if best_subgroup is not None: if target_symmetry.unit_cell() is not None and not ( best_subgroup["best_subsym"].unit_cell().is_similar_to( target_symmetry.as_reference_setting().best_cell(). unit_cell(), relative_length_tolerance=relative_length_tolerance, absolute_angle_tolerance=absolute_angle_tolerance, )): logger.debug( "Rejecting crystal model inconsistent with input symmetry:\n" f" Unit cell: {str(model.get_unit_cell())}") continue n_matched += 1 yield model if not n_matched: logger.warning( "No crystal models remaining after comparing with known symmetry")
def test_find_matching_symmetry(crystal_symmetry): cs = crystal_symmetry cs.show_summary() for op in ("x,y,z", "z,x,y", "y,z,x", "-x,z,y", "y,x,-z", "z,-y,x")[:]: cb_op = sgtbx.change_of_basis_op(op) uc_inp = cs.unit_cell().change_basis(cb_op) for ref_uc, ref_sg in [ (cs.unit_cell(), cs.space_group()), (None, cs.space_group()), ][:]: best_subgroup = symmetry.find_matching_symmetry( uc_inp, target_space_group=ref_sg) cb_op_inp_best = best_subgroup["cb_op_inp_best"] assert uc_inp.change_basis(cb_op_inp_best).is_similar_to( cs.as_reference_setting().best_cell().unit_cell())
def run_once(crystal_symmetry): cs = crystal_symmetry #print cs.show_summary() from cctbx.sgtbx import lattice_symmetry subgroups = lattice_symmetry.metric_subgroups(cs, max_delta=5) for op in ('x,y,z', 'z,x,y', 'y,z,x', '-x,z,y', 'y,x,-z', 'z,-y,x')[:]: cb_op = sgtbx.change_of_basis_op(op) uc_inp = cs.unit_cell().change_basis(cb_op) for ref_uc, ref_sg in [(cs.unit_cell(), cs.space_group()), (None, cs.space_group())][:]: best_subgroup = symmetry.find_matching_symmetry( uc_inp, target_space_group=ref_sg) cb_op_inp_best = best_subgroup['cb_op_inp_best'] assert uc_inp.change_basis(cb_op_inp_best).is_similar_to( cs.as_reference_setting().best_cell().unit_cell())
def run_once(crystal_symmetry): cs = crystal_symmetry #print cs.show_summary() from cctbx.sgtbx import lattice_symmetry subgroups = lattice_symmetry.metric_subgroups(cs, max_delta=5) for op in ('x,y,z', 'z,x,y', 'y,z,x', '-x,z,y', 'y,x,-z', 'z,-y,x')[:]: cb_op = sgtbx.change_of_basis_op(op) uc_inp = cs.unit_cell().change_basis(cb_op) for ref_uc, ref_sg in [(cs.unit_cell(), cs.space_group()), (None, cs.space_group())][:]: best_subgroup = symmetry.find_matching_symmetry( uc_inp, target_space_group=ref_sg) cb_op_inp_best = best_subgroup['cb_op_inp_best'] assert uc_inp.change_basis(cb_op_inp_best).is_similar_to( cs.as_reference_setting().best_cell().unit_cell())
def filter_known_symmetry( crystal_models, target_symmetry, relative_length_tolerance=0.1, absolute_angle_tolerance=5, max_delta=5, ): """Filter crystal models for known symmetry. Args: crystal_models (list): A list of :class:`dxtbx.model.Crystal` objects. target_symmetry (cctbx.crystal.symmetry): The target symmetry for filtering. relative_length_tolerance (float): Relative tolerance for unit cell lengths in unit cell comparision (default value is 0.1). absolute_angle_tolerance (float): Angular tolerance (in degrees) in unit cell comparison (default value is 5). max_delta (float): Maximum allowed Le Page delta used in searching for basis vector combinations that are consistent with the given symmetry (default value is 5). """ cb_op_ref_to_primitive = target_symmetry.change_of_basis_op_to_primitive_setting( ) if target_symmetry.unit_cell() is not None: target_symmetry_primitive = target_symmetry.change_basis( cb_op_ref_to_primitive) target_min_cell = target_symmetry_primitive.minimum_cell().unit_cell() else: target_symmetry_primitive = target_symmetry.customized_copy( space_group_info=target_symmetry.space_group_info().change_basis( cb_op_ref_to_primitive)) target_min_cell = None transformations = [sgtbx.change_of_basis_op()] for model in crystal_models: best_model = None for T in transformations: uc = model.get_unit_cell() det = T.c().r().determinant() if target_symmetry_primitive.unit_cell() is None: if det > 1: break else: primitive_volume = target_symmetry_primitive.unit_cell( ).volume() if det > 1 and abs(uc.volume() / primitive_volume - det) < 1e-1: uc = uc.change_basis(T) best_subgroup = find_matching_symmetry( uc, target_symmetry_primitive.space_group(), max_delta=max_delta) cb_op_extra = None if best_subgroup is None: if not cb_op_ref_to_primitive.is_identity_op(): # if we have been told we have a centred unit cell check that # indexing hasn't found the centred unit cell instead of the # primitive cell best_subgroup = find_matching_symmetry( uc, target_symmetry.space_group(). build_derived_point_group(), max_delta=max_delta, ) cb_op_extra = cb_op_ref_to_primitive if best_subgroup is None: continue else: continue cb_op_inp_best = best_subgroup["cb_op_inp_best"] best_subsym = best_subgroup["best_subsym"] cb_op_best_ref = best_subsym.change_of_basis_op_to_reference_setting( ) ref_subsym = best_subsym.change_basis(cb_op_best_ref) cb_op_ref_primitive = ref_subsym.change_of_basis_op_to_primitive_setting( ) cb_op_to_primitive = (cb_op_ref_primitive * cb_op_best_ref * cb_op_inp_best * T) if cb_op_extra is not None: cb_op_to_primitive = cb_op_extra * cb_op_to_primitive best_model = model.change_basis(cb_op_to_primitive) if target_symmetry_primitive.unit_cell( ) is not None and not (best_model.get_unit_cell().is_similar_to( target_symmetry_primitive.unit_cell(), relative_length_tolerance=relative_length_tolerance, absolute_angle_tolerance=absolute_angle_tolerance, ) or best_model.get_unit_cell().minimum_cell().is_similar_to( target_min_cell, relative_length_tolerance=relative_length_tolerance, absolute_angle_tolerance=absolute_angle_tolerance, )): best_model = None continue else: break if best_model is not None: yield best_model