Source code for molsystem.qcschema
# -*- coding: utf-8 -*-
"""Interface to qcschema."""
import json
import logging
from seamm_util import Q_
logger = logging.getLogger(__name__)
[docs]
class QCSchemaMixin:
"""A mixin for handling QCSchema."""
[docs]
def to_qcschema_dict(self, properties=None):
"""Create a dictionary compliant with QCSchema."""
result = {
"schema_name": "qcschema_molecule",
"schema_version": 2,
}
# Symbols and coordinates (in Bohr)
result["symbols"] = [*self.atoms.symbols]
factor = Q_(1.0, "Å").m_as("a_0")
xyz = []
# round() below helps tests work across platforms. 9 digits are enough!
for row in self.atoms.get_coordinates(fractionals=False):
for val in row:
xyz.append(round(val * factor, 9))
result["geometry"] = xyz
# Charge and multiplicity
result["molecular_charge"] = self.charge
result["molecular_multiplicity"] = self.spin_multiplicity
# Bonds, if any
bonds = []
index = {j: i for i, j in zip(range(self.n_atoms), self.atoms.ids)}
for row in self.bonds.bonds():
bonds.append((index[row["i"]], index[row["j"]], row["bondorder"]))
if len(bonds) > 0:
result["connectivity"] = bonds
# Molecules (fragments in QCSchema speak)
result["fragments"] = self.find_molecules(as_indices=True)
result["name"] = f"{self.system.name} / {self.name}"
if "name" in self.atoms:
result["atom_labels"] = self.atoms.get_column_data("name")
return result
[docs]
def to_qcschema_json(self):
"""Create the QCSchema JSON for the molecule."""
data = self.to_qcschema_dict()
return json.dumps(data)
[docs]
def from_qcschema_dict(self, data):
"""Reset the molecule from the QCSchema data."""
self.clear()
self.periodicity = 0
symbols = data["symbols"]
factor = Q_(1.0, "a_0").m_as("Å")
Xs = []
Ys = []
Zs = []
for x, y, z in zip(*[iter(data["geometry"])] * 3):
Xs.append(x * factor)
Ys.append(y * factor)
Zs.append(z * factor)
ids = self.atoms.append(x=Xs, y=Ys, z=Zs, symbol=symbols)
if "atom_labels" in data:
if "name" not in self.atoms:
self.atoms.add_attribute("name", values=data["atom_labels"])
else:
self.atoms["name"] = data["atom_labels"]
if "connectivity" in data and len(data["connectivity"]) > 0:
Is = []
Js = []
orders = []
for i, j, order in data["connectivity"]:
Is.append(i)
Js.append(j)
orders.append(order)
i = [ids[x - 1] for x in Is]
j = [ids[x - 1] for x in Js]
self.bonds.append(i=i, j=j, bondorder=orders)
[docs]
def from_qcschema_json(self, json_data):
"""Reset the molecule from the QCSchema JSON."""
data = json.loads(json_data)
self.from_qcschema_dict(data)