File: python-interface.md

package info (click to toggle)
spglib 2.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 14,180 kB
  • sloc: ansic: 125,066; python: 7,717; cpp: 2,197; f90: 2,143; ruby: 792; makefile: 22; sh: 18
file content (307 lines) | stat: -rw-r--r-- 8,995 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
84
85
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# Spglib for Python

## Usage note

The python binding will first try to use your system installed version of spglib. This can
be controlled by setting an appropriate `LD_LIBRARY_PATH` (linux) or `DYLD_LIBRAY_PATH`
(macos) to the appropriate location of the `libsymspg.so` library file. If no suitable
version is found, it will default to using the bundled version.

## Installation

The main installation method we support are using [pip](#using-pip) and [conda](#using-conda).
Additionally, you can build and install [from source](#building-from-source).

The following pip and conda packages are made and maintained by
[Paweł T. Jochym](https://github.com/jochym), which is of great help
to keeping spglib handy and useful.

### Using pip

You can find all the spglib release versions on our [PyPI project page](https://pypi.org/project/spglib/).
To install it use the standard pip install commands:

```console
$ pip install spglib
```

### Using conda

We also maintain a [conda package](https://anaconda.org/conda-forge/spglib) which you
can install:

```console
$ conda install -c conda-forge spglib
```

### Building from source

For this section we are assuming you have cloned or downloaded the spglib source
code, and we are working from the top-level directory.

```console
$ git clone https://github.com/spglib/spglib
$ cd spglib
```

To manually install spglib you will need `cmake` with any make tool like
`make`, a C compiler (e.g. gcc, clang), and python development files (python-dev),
including numpy ones.

There are two ways of building spglib with the python bindings using either a
python-centric or cmake-centric approach

#### Python controlled

This is the primary installation method suitable for production that we use to
distribute the spglib package.

```console
$ pip install .
```

All build configurations are defined in the top-level `pyproject.toml` file.
We are using [scikit-build-core](https://github.com/scikit-build/scikit-build-core)
to build both the main spglib C library and the python apis. You can thus
further configure your local installation, e.g. to use OpenMP:

```console
$ pip install . --config-settings=cmake.define.SPGLIB_USE_OMP=ON
```

Currently `scikit-build-core` does not support editable installs for development.

#### Cmake controlled

This method is not suitable for production, and it is only meant for quick development

```console
$ cmake -B ./build -DSPGLIB_WITH_Fortran=ON
$ cmake --build ./build
$ cmake --install ./build
```

This will detect and install the python manually in the currently activated virtual
environment's site-package folder (e.g. `venv/lib64/python3.11/site-packages`),
otherwise defaulting to the system (`/usr/lib64/python3.11/site-packages`). You may
edit this location by passing a `Python_INSTALL_DIR` option.

## Test

You may execute the python tests locally from the git repository root:

```console
$ pytest
```

## How to import spglib module

**Change in version 1.9.0!**

For versions 1.9.x or later:

```{testsetup}
import spglib
```

For versions 1.8.x or before:

```python
from pyspglib import spglib
```

If the version is not sure:

```python
try:
    import spglib as spg
except ImportError:
    from pyspglib import spglib as spg
```

## Version number

In version 1.8.3 or later, the version number is obtained by
`spglib.__version__` or {func}`spglib.spglib.get_version`.

## Example

Examples are found in {path}`example/python_api` directory.

(py_variables)=

## Variables

(py_variables_crystal_structure)=

### Crystal structure (`cell`)

A crystal structure is given by a **tuple**. This tuple format is
supported at version 1.9.1 or later.

The tuple format is shown as follows. There are three or four elements
in the tuple: `cell = (lattice, positions, numbers)` or `cell = (lattice, positions, numbers, magmoms)` where `magmoms` represents
magnetic moments on atoms and is optional.

Lattice parameters `lattice` are given by a 3x3 matrix with floating
point values, where $\mathbf{a}, \mathbf{b}, \mathbf{c}$ are
given as rows, which results in the transpose of the definition for
C-API ({ref}`variables_lattice`). Fractional atomic positions
`positions` are given by a Nx3 matrix with floating point values,
where N is the number of atoms. Numbers to distinguish atomic species
`numbers` are given by a list of N integers.
The magnetic moments `magmoms` can be specified with `get_magnetic_symmetry`.
`magmoms` is a list of N floating-point values for collinear cases and a list of Nx3 in **cartesian coordinates** for non-collinear cases.

```python
lattice = [[a_x, a_y, a_z],
            [b_x, b_y, b_z],
            [c_x, c_y, c_z]]
positions = [[a_1, b_1, c_1],
               [a_2, b_2, c_2],
               [a_3, b_3, c_3],
               ...]
numbers = [n_1, n_2, n_3, ...]
magmoms = [m_1, m_2, m_3, ...]  # Works with get_magnetic_symmetry for a collinear case
# magmoms = [[m_1x, m_1y, m_1z], ...]  # For a non-collinear case
```

For example, the crystal structure (`cell`) of L1$_{2}$-type AlNi$_{3}$ is:

```python
lattice = [[1.0, 0.0, 0.0],
            [0.0, 1.0, 0.0],
            [0.0, 0.0, 1.0]]
positions = [[0.0, 0.0, 0.0], # Al
            [0.5, 0.5, 0.0], # Ni
            [0.0, 0.5, 0.5], # Ni
            [0.5, 0.0, 0.5]] # Ni
numbers = [1, 2, 2, 2]        # Al, Ni, Ni, Ni
```

```{note}
When a crystal structure is not properly given, `TypeError` will be raised.
For previous versions between 1.9.5 and 2.3.1, `None` will be returned for the invalid input.
```

### Symmetry tolerance (`symprec`, `angle_tolerance`, `mag_symprec`)

Distance tolerance in Cartesian coordinates to find crystal symmetry. For more
details, see {ref}`variables_symprec`, {ref}`variables_angle_tolerance`, and
{ref}`variables_mag_symprec`.

## API summary

### Version

- {py:func}`spglib.utils.get_version`

### Error

- {py:func}`spglib.error.get_error_message`

### Space-group symmetry search

- {py:func}`spglib.spg.get_symmetry`
- {py:func}`spglib.spg.get_symmetry_dataset`

### Space-group type search

- {py:func}`spglib.spg.get_spacegroup`

### Standardization and finding primitive cell

- {py:func}`spglib.cell.standardize_cell`
- {py:func}`spglib.cell.find_primitive`
- {py:func}`spglib.cell.refine_cell`

### Space-group dataset access

- {py:func}`spglib.spg.get_symmetry_from_database`
- {py:func}`spglib.spg.get_spacegroup_type`
- {py:func}`spglib.spg.get_spacegroup_type_from_symmetry`

### Magnetic symmetry

- {py:func}`spglib.msg.get_magnetic_symmetry`
- {py:func}`spglib.msg.get_magnetic_symmetry_dataset`
- {py:func}`spglib.msg.get_magnetic_spacegroup_type`
- {py:func}`spglib.msg.get_magnetic_spacegroup_type_from_symmetry`
- {py:func}`spglib.msg.get_magnetic_symmetry_from_database`

### Lattice reduction

- {py:func}`spglib.reduce.niggli_reduce`
- {py:func}`spglib.reduce.delaunay_reduce`

### Kpoints

- {py:func}`spglib.kpoints.get_ir_reciprocal_mesh`

```python
mapping, grid = get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
```

Irreducible k-points are obtained from a sampling mesh of k-points.
`mesh` is given by three integers by array and specifies mesh
numbers along reciprocal primitive axis. `is_shift` is given by the
three integers by array. When `is_shift` is set for each reciprocal
primitive axis, the mesh is shifted along the axis in half of adjacent
mesh points irrespective of the mesh numbers. When the value is not 0,
`is_shift` is set.

`mapping` and `grid` are returned. `grid` gives the mesh points in
fractional coordinates in reciprocal space. `mapping` gives mapping to
the irreducible k-point indices that are obtained by

```python
np.unique(mapping)
```

Here `np` means the numpy module. The grid point is accessed by
`grid[index]`.

When the search failed, `None` is returned.

An example is shown below:

```python
import numpy as np
import spglib

lattice = np.array([[0.0, 0.5, 0.5],
                    [0.5, 0.0, 0.5],
                    [0.5, 0.5, 0.0]]) * 5.4
positions = [[0.875, 0.875, 0.875],
            [0.125, 0.125, 0.125]]
numbers= [1,] * 2
cell = (lattice, positions, numbers)
print(spglib.get_spacegroup(cell, symprec=1e-5))
mesh = [8, 8, 8]

#
# Gamma centre mesh
#
mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])

# All k-points and mapping to ir-grid points
for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
    print("%3d ->%3d %s" % (i, ir_gp_id, gp.astype(float) / mesh))

# Irreducible k-points
print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
print(grid[np.unique(mapping)] / np.array(mesh, dtype=float))

#
# With shift
#
mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[1, 1, 1])

# All k-points and mapping to ir-grid points
for i, (ir_gp_id, gp) in enumerate(zip(mapping, grid)):
    print("%3d ->%3d %s" % (i, ir_gp_id, (gp + [0.5, 0.5, 0.5]) / mesh))

# Irreducible k-points
print("Number of ir-kpoints: %d" % len(np.unique(mapping)))
print((grid[np.unique(mapping)] + [0.5, 0.5, 0.5]) / mesh)
```