Skip to content

crystallography

crystallography

apply_atom_site_symmetry_constraints(atom_site, name_hm, coord_code, wyckoff_letter)

Apply symmetry constraints to atomic coordinates based on site symmetry.

Parameters:

Name Type Description Default
atom_site Dict[str, Any]

Dictionary containing atom position data.

required
name_hm str

Hermann-Mauguin symbol of the space group.

required
coord_code int

Coordinate system code.

required
wyckoff_letter str

Wyckoff position letter.

required

Returns:

Type Description
Dict[str, Any]

The atom_site dictionary with applied symmetry constraints.

Source code in src/easydiffraction/crystallography/crystallography.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
def apply_atom_site_symmetry_constraints(
    atom_site: Dict[str, Any],
    name_hm: str,
    coord_code: int,
    wyckoff_letter: str,
) -> Dict[str, Any]:
    """
    Apply symmetry constraints to atomic coordinates based on site symmetry.

    Args:
        atom_site: Dictionary containing atom position data.
        name_hm: Hermann-Mauguin symbol of the space group.
        coord_code: Coordinate system code.
        wyckoff_letter: Wyckoff position letter.

    Returns:
        The atom_site dictionary with applied symmetry constraints.
    """
    it_number = get_it_number_by_name_hm_short(name_hm)
    if it_number is None:
        error_msg = f"Failed to get IT_number for name_H-M '{name_hm}'"
        print(error_msg)
        return atom_site

    it_coordinate_system_code = coord_code
    if it_coordinate_system_code is None:
        error_msg = 'IT_coordinate_system_code is not set'
        print(error_msg)
        return atom_site

    space_group_entry = SPACE_GROUP_LOOKUP_DICT[(it_number, it_coordinate_system_code)]
    wyckoff_positions = space_group_entry['Wyckoff_positions'][wyckoff_letter]
    coords_xyz = wyckoff_positions['coords_xyz']

    first_position = coords_xyz[0]
    components = first_position.strip('()').split(',')
    parsed_exprs: List[Expr] = [sympify(comp.strip()) for comp in components]

    x_val: Expr = sympify(atom_site['fract_x'])
    y_val: Expr = sympify(atom_site['fract_y'])
    z_val: Expr = sympify(atom_site['fract_z'])

    substitutions: Dict[str, Expr] = {'x': x_val, 'y': y_val, 'z': z_val}

    axes: tuple[str, ...] = ('x', 'y', 'z')
    x, y, z = symbols('x y z')
    symbols_xyz: tuple[Symbol, ...] = (x, y, z)

    for i, axis in enumerate(axes):
        symbol = symbols_xyz[i]
        is_free = any(symbol in expr.free_symbols for expr in parsed_exprs)

        if not is_free:
            evaluated = parsed_exprs[i].subs(substitutions)
            simplified = simplify(evaluated)
            atom_site[f'fract_{axis}'] = float(simplified)

    return atom_site

apply_cell_symmetry_constraints(cell, name_hm)

Apply symmetry constraints to unit cell parameters based on space group.

Parameters:

Name Type Description Default
cell Dict[str, float]

Dictionary containing lattice parameters.

required
name_hm str

Hermann-Mauguin symbol of the space group.

required

Returns:

Type Description
Dict[str, float]

The cell dictionary with applied symmetry constraints.

Source code in src/easydiffraction/crystallography/crystallography.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def apply_cell_symmetry_constraints(
    cell: Dict[str, float],
    name_hm: str,
) -> Dict[str, float]:
    """
    Apply symmetry constraints to unit cell parameters based on space group.

    Args:
        cell: Dictionary containing lattice parameters.
        name_hm: Hermann-Mauguin symbol of the space group.

    Returns:
        The cell dictionary with applied symmetry constraints.
    """
    it_number = get_it_number_by_name_hm_short(name_hm)
    if it_number is None:
        error_msg = f"Failed to get IT_number for name_H-M '{name_hm}'"
        print(error_msg)
        return cell

    crystal_system = get_crystal_system_by_it_number(it_number)
    if crystal_system is None:
        error_msg = f"Failed to get crystal system for IT_number '{it_number}'"
        print(error_msg)
        return cell

    if crystal_system == 'cubic':
        a = cell['lattice_a']
        cell['lattice_b'] = a
        cell['lattice_c'] = a
        cell['angle_alpha'] = 90
        cell['angle_beta'] = 90
        cell['angle_gamma'] = 90

    elif crystal_system == 'tetragonal':
        a = cell['lattice_a']
        cell['lattice_b'] = a
        cell['angle_alpha'] = 90
        cell['angle_beta'] = 90
        cell['angle_gamma'] = 90

    elif crystal_system == 'orthorhombic':
        cell['angle_alpha'] = 90
        cell['angle_beta'] = 90
        cell['angle_gamma'] = 90

    elif crystal_system in {'hexagonal', 'trigonal'}:
        a = cell['lattice_a']
        cell['lattice_b'] = a
        cell['angle_alpha'] = 90
        cell['angle_beta'] = 90
        cell['angle_gamma'] = 120

    elif crystal_system == 'monoclinic':
        cell['angle_alpha'] = 90
        cell['angle_gamma'] = 90

    elif crystal_system == 'triclinic':
        pass  # No constraints to apply

    else:
        error_msg = f'Unknown or unsupported crystal system: {crystal_system}'
        print(error_msg)

    return cell