Given a cif file I want to obtain the graph representation (as a data structure) of a certain material. I am trying with this cif file which represents the unit cell of CrN.
I am trying to use pymatgen's StructureGraph class but I have had some problems. In this link they suggest to use the with_local_env_strategy()
method, however when I try to use it I get an error. Here my code:
from pymatgen.analysis.graphs import StructureGraph
from pymatgen.analysis.local_env import NearNeighbors
from pymatgen.core import Structure
filename = 'CrN.cif'
structure = Structure.from_file(filename)
nn = NearNeighbors()
strategy = nn.get_all_nn_info(structure)
strucGraph = StructureGraph.with_local_env_strategy(supercell, strategy, weights=False, edge_properties=False)
The error:
Since I am not an expert in the materials subject (I am only a systems engineer and a mathematician), I made these 2 possible solutions:
Using the get_neighbors()
method which, given a spherical neighborhood of a given radius, obtains the nearest neighbors:
from pymatgen.core import Structure
import networkx as nx
import numpy as np
filename = 'CrN.cif'
structure = Structure.from_file(filename)
supercell = structure.copy()
supercell.make_supercell([2,2,2])
G = nx.Graph()
for i, site in enumerate(supercell):
G.add_node(i)
G.nodes[i]["Species"] = label_set[site.species]
G.nodes[i]["position"] = (site.x, site.y, site.z)
for i, site in enumerate(supercell):
neighbors = [(n.index, n.nn_distance) for n in supercell.get_neighbors(site, r=3)]
for n in neighbors:
G.add_edge(i, n[0], weight=n[1])
The second method is a little more customizable, the code I put here takes into account Euclidean distance, however, for the criterion of connection of 2 atoms can be used other criteria, such as energy.
def space_euclidean_distance(p1, p2):
dist = np.sqrt(np.sum((p1-p2)**2, axis=0))
return dist
lattice = supercell.lattice
fractional_coords = supercell.frac_coords
# Convert the fractional coordinates to Cartesian coordinates using the lattice vectors
cartesian_coords = lattice.get_cartesian_coords(fractional_coords)
distances = []
N = len(cartesian_coords)
for i in range(N):
p1 = cartesian_coords[i]
dist_i = {}
for j in range(N):
p2 = cartesian_coords[j]
if j != i:
dist_i[j] = space_euclidean_distance(p1, p2)
distances.append(dist_i)
G2 = nx.Graph()
for i, site in enumerate(supercell):
G2.add_node(i)
G2.nodes[i]["Species"] = label_set[site.species]
for i in range(N):
for key, value in distances[i].items():
if value <= 2.5: #metric for connection of 2 atoms
G2.add_edge(i, key, weight=value)