Datatypes
Molecular NMR parameters, spectra and calculation results are stored in Python objects in the HQS NMR Tool. These data structures are all Pydantic
data classes and the data can be accessed as attributes of the class. See NMRResultSpectrum1D
for an example.
Note that for the full signature of each datatype you can check out the API-documentation. Here we will just point out the most important attributes of each class.
NMRResultSpectrum1D
The NMRResultSpectrum1D
is used to store all of the input and output of a NMR spectrum calculation when using the calculate_spectrum routine. It comprises:
-
The molecular NMR parameters of datatype
NMRParameters
used for the calculation (molecule_parms
). -
All the parameters handed to
calculate_spectrum
in form of aNMRCalculationParameters
object (calculation_parms
). -
The calculated spectrum of datatype
NMRSpectrum1D
(spectrum
).
Assuming we have obtained an object called result_spectrum
of datatype NMRResultSpectrum1D
the attributes can be accessed as follows:
molecule_parms = result.molecule_parms
calculation_parms = result.calculation_parms
spectrum = result.spectrum
In the following we will elaborate on the datatype of each of these objects in more detail.
NMRResultGreensFunction1D
The NMRResultGreensFunction1D
is the analog datatype to NMRResultSpectrum1D
when using calculate_greens_function instead of calculate_spectrum. The only difference is that instead of the attribute spectrum
it has the attribute greens_function
, which stores a NMRGreensFunction1D
datatype.
Assuming we have an object called result_greens_function
of datatype NMRResultGreensFunction1D
the greens_function
attribute can be accessed as follows:
greens_function = result_greens_function.greens_function
NMRParameters
The NMRParameters
datatype is defined in the hqs_nmr_parameters
repository and holds the reduced set of molecular parameters required for an NMR calculation,
The class holds:
- A list of chemical
shifts
in ppm for every nucleus in the system that has NMR parameters. - A List of isotopes for every nucleus, in the same ordering as
shifts
. TheNamedTuple
Isotope
has the two attributesmass_number
andsymbol
. - A list containing pairs of atomic indices and the associated J-coupling values. The atomic indices refer to the ordering in the
shifts
andisotopes
lists.
For an example you may run the following code:
from hqs_nmr_parameters.examples import molecules
# Obtain example molecule.
nmr_parameters = molecules["C10H7Br"].spin_system()
print(type(nmr_parameters)) # NMRParameters
print(nmr_parameters.shifts)
print(nmr_parameters.isotopes)
print(nmr_parameters.j_couplings)
NMRParameters
objects are used as an input when calculating a spectrum using the calculate_spectrum or calculate_greens_function method.
NMRCalculationParameters
The NMRCalculationParameters
datatype is defined in the hqs_nmr
repository and stores all possible customization options when performing spectra calculations with calculate_spectrum
or calculate_greens_function
.
The only parameter the user always has to specify is the spectrometer frequency in MHz, so the most simple and often already sufficient instantiation of this datatype may look as follows:
from hqs_nmr.datatypes import NMRCalculationParameters
calculation_parms = NMRCalculationParameters(frequency_MHz=500)
Another important option the user can set is the homoisotope
, which is the Isotope specified as Isotope(mass, symbol)
to define the frequency of the rotating frame. Furthermore, the object contains multiple attributes allowing to improve the resolution. For a detailed explanation of the available customization options check out the tutorial notebooks or take a look at the API-documentation.
NMRSolverSettings
The NMRSolverSettings
datatype is also defined in the hqs_nmr
repository and stores customization options specific for the solver backend. It is stored as an attribute of a NMRCalculationParmameters
object and typically does not need to be altered.
It is however important to know that by default a spin-dependent clustering of the molecule into overlapping clusters is performed (for details check here). This is an extremely accurate approximation especially at high field, however in some cases this might not be wanted. In these cases you can set the attribute solve_exactly=True
, such that the spectrum of the entire molecule is calculated at once and symmetries will be exploited where applicable, but no approximations are made. Note that this can lead to a significant increase in runtime, so typically it is more advisable to increase the size of the clusters instead. To do so the attribute max_cluster_size
has to be specified:
from hqs_nmr.datatypes import NMRSolverSettings
solver_settings = NMRSolverSettings(max_cluster_size=16)
To see all customization options check the API-documentation.
NMRSpectrum1D
The NMRSpectrum1D
datatype holds an NMR spectrum comprising the frequencies in ppm (omegas_ppm
), an array with the individual spin contributions to the spectrum (values
), the full-width-half-maximum in ppm (fwhm_ppm
) and the reference energy (reference_energy
) to allow easy conversion of attributes from ppm into other units.
Assuming we have performed a NMR spectrum calculation using calculate_spectrum and obtained as output an NMRResultSpectrum1D
object we called result_spectrum
, we can obtain an object of datatype NMRSpectrum1D
as an attribute of this object:
spectrum = result_spectrum.spectrum
The values
are a numpy array where each row holds the contribution of the corresponding spin, i.e.:
spectrum.values[0,:]
holds the contribution of the first spin (index 0). The total spectrum that would be measured experimentally can be calculated using
import numpy as np
np.sum(spectrum.values, axis=0)
NMRGreensFunction1D
The NMRGreensFunction1D
datatype basically has the same attributes as NMRSpectrum1D
, however values
is a complex array, as it stores the full NMR Green's function and not just the spectral function. This datatype is typically only used, if one wants to perform post-processing steps that require also the real part of the Green's function.
Assuming we have performed a NMR Green's function calculation using calculate_greens_function and obtained as output an NMRResultGreensFunction1D
object called result_greens_function
, we can obtain an object of datatype NMRGreensFunction1D
as an attribute of this object:
greens_function = result_greens_function.greens_function
The total spectrum can then be obtained as follows:
import numpy as np
np.sum(- np.imag(greens_function.values), axis=0)
Serialization (Saving and Loading)
The datatypes described above have a common interface for data serialization. There exists a function called to_json
common to all classes that can take a class object and a file name (with or without the full path) to store the data as a JSON
file. For example, if we have an object called spectrum
of the data class NMRSpectrum1D
and want to save it as spectrum_data.json
:
from hqs_nmr.datatypes import to_json
to_json(spectrum, "spectrum_data.json")
There is also the inverse method from_json
to load the data again. It needs as additional information the type of class the JSON
file has stored, e.g.:
from hqs_nmr.datatypes import from_json, NMRSpectrum1D
spectrum = from_json(NMRSpectrum1D, "spectrum_data.json")