Basic Usage¶
Overview¶
At the heart of the nmrcryspy workflow is the definition of a Gauss_Newton_Solver object describing the minimization framework to be used in the minimization. Each Gauss_Newton_Solver object holds a list of Geometric functions and NMR functions objects which are used to calculate geometric or NMR properties which are used during the refinement.
The following examples take parts from the script in examples/zsm12.py to describe the components that make up this library.
Target Functions¶
When performing a minimization we will need to choose the information we want to optimize against (our target) and some way to predict that target. Currently, we offer simple pairwise atom-atom distance based Geometric functions targets as well as machine learning based nmr_api: targets. These functions provide methods to construct residual vectors and Jacobian matricies.
Consider the example below of a Geometric functions object for a silicon-oxygen distance created in Python.
# Import objects for the Distance Function
from nmrcryspy.geometric import Distance_Function
# Create a dictionary of data
distance_dict = {
"SiO": {"mu": 1.6, "sigma": 0.01}
}
#Pass this data to the Distance_Function() class
zeolite_dists = Distance_Function(distance_dict)
This target function uses known Si-O distance distribution data to calculate the following residual:
where \(\mu\) is the distributions mean distance (in angstroms) and \(\sigma\) is the distributions standard deviation (in angstroms).
The NMR fit functions are slightly more complicated as they require the checkpoint files (.chk) for creating the machine learning (ML) functions. We will also need to point to a data file for the ML function and provide some additional data for use in the refinement.
Consider the example below of a NMR functions object for a silicon-oxygen distance created in Python.
# Import objects for the Shielding Function
from nmrcryspy.nmr import ShieldingTensor_Function
# Point to the location of the relevant checkpoint file
checkpoint_file_path = (
"/Users/mvenetos/Documents/Jupyter Testing Grounds/eigenn_testing/EigennBestTensor.ckpt"
)
# Create a dictionary of standard deviation data for each eigenvalue
shielding_dict = {"sigma_11": 0.4, "sigma_22": 2.5, "sigma_33": 0.7}
zeolite_shieldings = ShieldingTensor_Function(
sigma_errors=shielding_dict,
checkpoint=shielding_chk,
root="/Users/mvenetos/Box Sync/All Manuscripts/zeolite " "refinements/ZSM12_temp/",
data_file="ZSM12_CS.json", #data_file together with root give the location of the ML data
)
Note
We parameterize a shielding eigenvalues using the standard convention convention
with parameters sigma_11 \(\geq\) sigma_22 \(\geq\) sigma_33.
For more information on how to use the ML functions (particularly the construction for data_file objects) see the code for matTEN
Minimization Framework¶
Once we have the target functions identified we can now put them into a minimization framework. Currently, nmrcryspy offers a Gauss-Newton (Gauss_Newton_Solver) optimizer. In addition to the target functions, the optimizer also takes a pymatgen.Structure object and some hyper-parameters for the optimization itself.
Consider the example below of a Gauss_Newton_Solver object for a zeolite refinement created in Python.
# Import objects for the Gauss_Newton_Solver
from nmrcryspy import Gauss_Newton_Solver
# Import the structure of the zeolite from a .cif file
file_path = (
"/Users/mvenetos/Box Sync/All Manuscripts/"
"zeolite refinements/ZSM-12_calcined.cif"
)
s = CifParser(file_path).get_structures(False)[0]
# Create a dictionary of data
# Note this is a fraction of the data and utility functions exist to create this
data = {
"Bond_Distances": [
{
"bond": "SiO",
"pairs": [
{"atom 1": 0, "atom 2": 56, "true_pair": [0, 56]},
],
},
]
"Shielding_Tensor": [
{
"index": 0,
"target": "shielding",
"neighbor_idx": [
0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,
],
},
]
}
#Pass this data to the Gauss_Newton_Solver() class
gn = Gauss_Newton_Solver(
fit_function=[zeolite_shieldings, zeolite_dists],
structure=s,
data_dictionary=data,
max_iter=2,
tolerance_difference=1e-8,
)