Interface with ASE & pymatgen

Supported versions of ASE/pymatgen can be installed from the requirements/optional-requirements.txt file, or via pip install matador-db[optional]. This allows for matador.crystal.Crystal objects to be converted to ase.Atoms and pymatgen.Structure objects, as shall be showcased below.

First, let’s use the builder functionality from ASE to create a crystal structure (example from the ase.build docs).

[1]:
import ase.build
gnr1 = ase.build.graphene_nanoribbon(
    3, 4, type='armchair', saturated=True, vacuum=3.5
)
print(gnr1)
Atoms(symbols='C48H16', pbc=[False, False, True], cell=[15.03671574711959, 7.0, 17.04])

Let’s attach some metadata using the Atoms.info property:

[2]:
gnr1.info = {
    "source": "ase.build.graphene_nanoribbon",
    "chiral_vector": (3, 4),
    "saturated": True,
    "vacuum": 3.5
}

We can now convert this to a matador-style dictionary, or a matador.crystal.Crystal object:

[3]:
from matador.utils.ase_utils import ase2dict
from matador.crystal import Crystal
gnr1_doc = ase2dict(gnr1)
print(gnr1_doc.keys())
print('----')
gnr1_crystal = ase2dict(gnr1, as_model=True)
print(gnr1_crystal)
dict_keys(['atom_types', 'positions_frac', 'lattice_cart', 'lattice_abc', 'num_atoms', 'stoichiometry', 'cell_volume', 'elems', 'num_fu', 'space_group', 'ase_info'])
----
C₃H: unknown
============
64  atoms. Pmma
(a, b, c) = 15.0367 Å, 7.0000 Å, 17.0400 Å
(α, β, γ) = 90.0000° 90.0000° 90.0000°

In the Crystal print out, the “unknown” means that matador could not find any metadata regarding the source of the structure, so let’s use the ASE metadata to update that.

[4]:
# all underlying data will be copied to the `_data` attribute of the Crystal,
# if we want, these keys can be promoted to the actual Crystal data itself
gnr1_crystal.update(gnr1_crystal._data["ase_info"])
print(gnr1_crystal)
C₃H: ase.build.graphene_nanoribbon
==================================
64  atoms. Pmma
(a, b, c) = 15.0367 Å, 7.0000 Å, 17.0400 Å
(α, β, γ) = 90.0000° 90.0000° 90.0000°

[5]:
print(gnr1_crystal.pdf.spg)
Pmma

We can now use matador functionality on this graphene nanoribbon:

[6]:
gnr1_crystal.pdf.plot(text_offset=(10, 0.2))
gnr1_crystal.pxrd.plot()
../../_images/notebooks_interactive_pymatgen_and_ase_interface_12_0.png
../../_images/notebooks_interactive_pymatgen_and_ase_interface_12_1.png
[7]:
from matador.crystal.network import draw_network
draw_network(gnr1_crystal.network)
print(gnr1_crystal.bonding_stats[0])
Calculated: 110592, Used: 1616, Ignored: 108976
Calculated distances in 0.003461122512817383 s
{'species': 'C', 'position': array([0.62267533, 0.5       , 0.        ]), 'bonds': [{'species': 'C', 'index': 1, 'length': 1.4199999999999997, 'is_image': False, 'position': array([0.70445889, 0.5       , 0.04166667])}, {'species': 'C', 'index': 15, 'length': 1.42, 'is_image': True, 'position': array([0.62267533, 0.5       , 0.91666667])}, {'species': 'C', 'index': 17, 'length': 1.4199999999999997, 'is_image': False, 'position': array([0.54089178, 0.5       , 0.04166667])}]}
../../_images/notebooks_interactive_pymatgen_and_ase_interface_13_1.png

We can now convert this Crystal object freely between ASE and pymatgen. Let’s make a pmg structure from the Crystal, modify it, then make a new Crystal:

[8]:
pmg_structure = gnr1_crystal.pmg_structure
for ind, site in enumerate(pmg_structure):
    if ind % 2 == 0:
        pmg_structure[ind] = "N"
print(pmg_structure)
Full Formula (H8 C24 N32)
Reduced Formula: HC3N4
abc   :  15.036716   7.000000  17.040000
angles:  90.000000  90.000000  90.000000
Sites (64)
  #  SP           a    b         c
---  ----  --------  ---  --------
  0  N     0.622675  0.5  0
  1  C     0.704459  0.5  0.041667
  2  N     0.704459  0.5  0.125
  3  C     0.622675  0.5  0.166667
  4  N     0.622675  0.5  0.25
  5  C     0.704459  0.5  0.291667
  6  N     0.704459  0.5  0.375
  7  C     0.622675  0.5  0.416667
  8  N     0.622675  0.5  0.5
  9  C     0.704459  0.5  0.541667
 10  N     0.704459  0.5  0.625
 11  C     0.622675  0.5  0.666667
 12  N     0.622675  0.5  0.75
 13  C     0.704459  0.5  0.791667
 14  N     0.704459  0.5  0.875
 15  C     0.622675  0.5  0.916667
 16  N     0.459108  0.5  0
 17  C     0.540892  0.5  0.041667
 18  N     0.540892  0.5  0.125
 19  C     0.459108  0.5  0.166667
 20  N     0.459108  0.5  0.25
 21  C     0.540892  0.5  0.291667
 22  N     0.540892  0.5  0.375
 23  C     0.459108  0.5  0.416667
 24  N     0.459108  0.5  0.5
 25  C     0.540892  0.5  0.541667
 26  N     0.540892  0.5  0.625
 27  C     0.459108  0.5  0.666667
 28  N     0.459108  0.5  0.75
 29  C     0.540892  0.5  0.791667
 30  N     0.540892  0.5  0.875
 31  C     0.459108  0.5  0.916667
 32  N     0.295541  0.5  0
 33  C     0.377325  0.5  0.041667
 34  N     0.377325  0.5  0.125
 35  C     0.295541  0.5  0.166667
 36  N     0.295541  0.5  0.25
 37  C     0.377325  0.5  0.291667
 38  N     0.377325  0.5  0.375
 39  C     0.295541  0.5  0.416667
 40  N     0.295541  0.5  0.5
 41  C     0.377325  0.5  0.541667
 42  N     0.377325  0.5  0.625
 43  C     0.295541  0.5  0.666667
 44  N     0.295541  0.5  0.75
 45  C     0.377325  0.5  0.791667
 46  N     0.377325  0.5  0.875
 47  C     0.295541  0.5  0.916667
 48  N     0.232764  0.5  0.031984
 49  H     0.232764  0.5  0.134683
 50  N     0.232764  0.5  0.281984
 51  H     0.232764  0.5  0.384683
 52  N     0.232764  0.5  0.531984
 53  H     0.232764  0.5  0.634683
 54  N     0.232764  0.5  0.781984
 55  H     0.232764  0.5  0.884683
 56  N     0.767236  0.5  0.009683
 57  H     0.767236  0.5  0.156984
 58  N     0.767236  0.5  0.259683
 59  H     0.767236  0.5  0.406984
 60  N     0.767236  0.5  0.509683
 61  H     0.767236  0.5  0.656984
 62  N     0.767236  0.5  0.759683
 63  H     0.767236  0.5  0.906984
/home/mevans/.local/conda/envs/matador_thesis/lib/python3.8/site-packages/pymatgen/core/__init__.py:49: UserWarning: Error loading .pmgrc.yaml: [Errno 2] No such file or directory: '/home/mevans/.pmgrc.yaml'. You may need to reconfigure your yaml file.
  warnings.warn(f"Error loading .pmgrc.yaml: {ex}. You may need to reconfigure your yaml file.")
[9]:
gnr1_doped_crystal = Crystal.from_pmg(pmg_structure)

Now we can plot the C-N, N-N and H-N pair distribution functions:

[10]:
gnr1_doped_crystal.pdf.plot_projected_pdf(keys=[("N", ), ("C", "N"), ("H", "N")])
../../_images/notebooks_interactive_pymatgen_and_ase_interface_18_0.png
[11]:
draw_network(gnr1_doped_crystal.network)
Calculated: 110592, Used: 1616, Ignored: 108976
Calculated distances in 0.003873586654663086 s
../../_images/notebooks_interactive_pymatgen_and_ase_interface_19_1.png