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)
| 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 |
| … | … | … | … | … | … | … |
| 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 |
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)}
[ ]: