Crystallography#

Notebook to explore crystallography functions in Anri.

[1]:
import anri

import urllib.request
[2]:
struc = anri.crystal.Structure.from_cif("../../../tests/data/cif/Fe.cif")

Now let’s generate some HKLs up to a d-star limit (with a given wavelength):

[3]:
dsmax = 0.75
wavelength = 0.18
struc.make_hkls(dsmax=dsmax, wavelength=wavelength)
[4]:
struc.allhkls
[4]:
Array([[ 1,  0,  0],
       [ 0,  1,  0],
       [ 0,  0,  1],
       [-1,  0,  0],
       [ 0, -1,  0],
       [ 0,  0, -1],
       [ 1,  1,  0],
       [ 0,  1, -1],
       [-1,  1,  0],
       [-1,  0,  1],
       [ 0, -1, -1],
       [ 0,  1,  1],
       [ 1, -1,  0],
       [ 1,  0,  1],
       [ 1,  0, -1],
       [-1, -1,  0],
       [-1,  0, -1],
       [ 0, -1,  1],
       [-1,  1,  1],
       [ 1,  1,  1],
       [ 1,  1, -1],
       [ 1, -1,  1],
       [ 1, -1, -1],
       [-1, -1,  1],
       [-1, -1, -1],
       [-1,  1, -1],
       [ 2,  0,  0],
       [ 0,  0,  2],
       [ 0,  2,  0],
       [ 0, -2,  0],
       [ 0,  0, -2],
       [-2,  0,  0]], dtype=int32)

Because we have a structure with atoms, we can simulate intensities. Calling rings_table will get the intensities for each hkl, and filter out the ones with very low intensity:

[5]:
struc.rings_table
[5]:
shape: (18, 7)
hkltthdsintensityring_id
i64i64i64f32f32f64u32
1105.0959670.4939561363.4480820
01-15.0959660.4939561363.4480820
-1105.0959670.4939561363.4480820
-1015.0959670.4939561363.4480820
0-1-15.0959670.4939561363.4480820
0027.2091650.698559930.1488731
0207.2091650.698559930.1488731
0-207.2091650.698559930.1488731
00-27.2091650.698559930.1488731
-2007.2091650.698559930.1488731

We can also get a dictionary grouped by ring ID:

[6]:
struc.rings_dict
[6]:
{0: shape: (12, 7)
 ┌─────┬─────┬─────┬──────────┬──────────┬─────────────┬─────────┐
 │ h   ┆ k   ┆ l   ┆ tth      ┆ ds       ┆ intensity   ┆ ring_id │
 │ --- ┆ --- ┆ --- ┆ ---      ┆ ---      ┆ ---         ┆ ---     │
 │ i64 ┆ i64 ┆ i64 ┆ f32      ┆ f32      ┆ f64         ┆ u32     │
 ╞═════╪═════╪═════╪══════════╪══════════╪═════════════╪═════════╡
 │ 1   ┆ 1   ┆ 0   ┆ 5.095967 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ 0   ┆ 1   ┆ -1  ┆ 5.095966 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ -1  ┆ 1   ┆ 0   ┆ 5.095967 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ -1  ┆ 0   ┆ 1   ┆ 5.095967 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ 0   ┆ -1  ┆ -1  ┆ 5.095967 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ …   ┆ …   ┆ …   ┆ …        ┆ …        ┆ …           ┆ …       │
 │ 1   ┆ 0   ┆ 1   ┆ 5.095966 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ 1   ┆ 0   ┆ -1  ┆ 5.095967 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ -1  ┆ -1  ┆ 0   ┆ 5.095967 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ -1  ┆ 0   ┆ -1  ┆ 5.095966 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 │ 0   ┆ -1  ┆ 1   ┆ 5.095966 ┆ 0.493956 ┆ 1363.448082 ┆ 0       │
 └─────┴─────┴─────┴──────────┴──────────┴─────────────┴─────────┘,
 1: shape: (6, 7)
 ┌─────┬─────┬─────┬──────────┬──────────┬────────────┬─────────┐
 │ h   ┆ k   ┆ l   ┆ tth      ┆ ds       ┆ intensity  ┆ ring_id │
 │ --- ┆ --- ┆ --- ┆ ---      ┆ ---      ┆ ---        ┆ ---     │
 │ i64 ┆ i64 ┆ i64 ┆ f32      ┆ f32      ┆ f64        ┆ u32     │
 ╞═════╪═════╪═════╪══════════╪══════════╪════════════╪═════════╡
 │ 2   ┆ 0   ┆ 0   ┆ 7.209165 ┆ 0.698559 ┆ 930.148873 ┆ 1       │
 │ 0   ┆ 0   ┆ 2   ┆ 7.209165 ┆ 0.698559 ┆ 930.148873 ┆ 1       │
 │ 0   ┆ 2   ┆ 0   ┆ 7.209165 ┆ 0.698559 ┆ 930.148873 ┆ 1       │
 │ 0   ┆ -2  ┆ 0   ┆ 7.209165 ┆ 0.698559 ┆ 930.148873 ┆ 1       │
 │ 0   ┆ 0   ┆ -2  ┆ 7.209165 ┆ 0.698559 ┆ 930.148873 ┆ 1       │
 │ -2  ┆ 0   ┆ 0   ┆ 7.209165 ┆ 0.698559 ┆ 930.148873 ┆ 1       │
 └─────┴─────┴─────┴──────────┴──────────┴────────────┴─────────┘}
Each entry in the dict is an individual ring, grouped by \(d^*\). This is useful for further indexing procedures etc.
There are some other helpful methods:
[7]:
struc.ringhkls  # dict, grouped by d-star
[7]:
{0.4939559996128082: Array([[ 1,  1,  0],
        [ 0,  1, -1],
        [-1,  1,  0],
        [-1,  0,  1],
        [ 0, -1, -1],
        [ 0,  1,  1],
        [ 1, -1,  0],
        [ 1,  0,  1],
        [ 1,  0, -1],
        [-1, -1,  0],
        [-1,  0, -1],
        [ 0, -1,  1]], dtype=int32),
 0.6985592842102051: Array([[ 2,  0,  0],
        [ 0,  0,  2],
        [ 0,  2,  0],
        [ 0, -2,  0],
        [ 0,  0, -2],
        [-2,  0,  0]], dtype=int32)}
[8]:
struc.ringhkls_arr # just a single array of all hkls with meaningful intensities
[8]:
Array([[ 1,  1,  0],
       [ 0,  1, -1],
       [-1,  1,  0],
       [-1,  0,  1],
       [ 0, -1, -1],
       [ 0,  1,  1],
       [ 1, -1,  0],
       [ 1,  0,  1],
       [ 1,  0, -1],
       [-1, -1,  0],
       [-1,  0, -1],
       [ 0, -1,  1],
       [ 2,  0,  0],
       [ 0,  0,  2],
       [ 0,  2,  0],
       [ 0, -2,  0],
       [ 0,  0, -2],
       [-2,  0,  0]], dtype=int32)
[9]:
struc.ringtth  # the unique two-theta values of the rings
[9]:
Array([5.095967, 7.209165], dtype=float32)
[10]:
struc.ringds  # the unique d* values of the rings
[10]:
Array([0.493956 , 0.6985593], dtype=float32)
[11]:
struc.ringmult  # the multiplicities of the rings
[11]:
Array([12,  6], dtype=int32)

We can confirm against ImageD11 too:

[12]:
from ImageD11.unitcell import unitcell
uc = unitcell(struc.lattice_parameters, struc.sgno)
uc
[12]:
Unitcell | [ 2.8630355  2.8630355  2.8630355 90.        90.        90.       ] | 229
[13]:
uc.makerings(dsmax, tol=0.0001)
[14]:
import jax.numpy as jnp
jnp.array(uc.ringds)
[14]:
Array([0.493956 , 0.6985593], dtype=float32)
[15]:
(struc.ringds - jnp.array(uc.ringds)).sum()
[15]:
Array(0., dtype=float32)
[16]:
uc.ringhkls
[16]:
{np.float64(0.49395599962805037): [(-1, 0, -1),
  (0, -1, -1),
  (-1, -1, 0),
  (0, 1, -1),
  (-1, 1, 0),
  (1, 0, -1),
  (-1, 0, 1),
  (1, -1, 0),
  (0, -1, 1),
  (1, 1, 0),
  (0, 1, 1),
  (1, 0, 1)],
 np.float64(0.6985592738895483): [(-2, 0, 0),
  (0, -2, 0),
  (0, 0, -2),
  (0, 0, 2),
  (0, 2, 0),
  (2, 0, 0)]}
[17]:
struc.ringhkls
[17]:
{0.4939559996128082: Array([[ 1,  1,  0],
        [ 0,  1, -1],
        [-1,  1,  0],
        [-1,  0,  1],
        [ 0, -1, -1],
        [ 0,  1,  1],
        [ 1, -1,  0],
        [ 1,  0,  1],
        [ 1,  0, -1],
        [-1, -1,  0],
        [-1,  0, -1],
        [ 0, -1,  1]], dtype=int32),
 0.6985592842102051: Array([[ 2,  0,  0],
        [ 0,  0,  2],
        [ 0,  2,  0],
        [ 0, -2,  0],
        [ 0,  0, -2],
        [-2,  0,  0]], dtype=int32)}
[ ]: