Source code for src.bond_lengths

#!/usr/bin/env python3
"""
The BondLengths class calculates or searches for and stores bond length data
from an ORCA .out file.
"""
__author__ = "Peter Waddell"
__copyright__ = "Copyright 2024"
__credits__ = ["Peter Waddell"]
__version__ = "0.1.0"
__date__ = "2024/02/27"
__maintainer__ = "Peter Waddell"
__email__ = "pmwaddell9@gmail.com"
__status__ = "Prototype"

import math

from orca_data_extraction.src.data_section_with_inputs import DataSectionWithInputs
from orca_data_extraction.src.final_geom import FinalGeometry


[docs] class BondLengths(DataSectionWithInputs): """ Finds and stores bond length data from an ORCA .out file. Methods ------- _search Search the .out file for bond length data. __calc_atom_angle Manually calcs the "bond length" of the 2 atoms in the input bond tuple. get_datum Gives the bond length from _data for a certain bond. """ def __init__(self, out_filename, outfile_contents, inputs): """ Parameters ---------- out_filename : str Name of the ORCA .out file that will be searched. outfile_contents : str String containing the full text of the ORCA .out file. inputs : tuple Tuple of 'bond tuples' (i.e. tuples of two strings of atom labels, e.g. ('1 H', '0 O')) for which bond length data will be searched. """ super().__init__(out_filename, outfile_contents, inputs) self._section_name = 'Bond Lengths' def _search(self, bond_tuple): return self.__calc_atom_distance(bond_tuple) def __calc_atom_distance(self, bond_tuple): """ Manually calcs the distance between two atoms in the input bond tuple. Of course, these can be any two atoms whose coordinates appear in the .out file; they do not have to be bound to each other in any way. Parameters ---------- bond_tuple : tuple Tuple containing two atom labels, representing the desired bond. Returns ------- str String containing the distance between the two atoms in Angstroms, as calculated from sqrt((x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2). Raises ------ TypeError This occurs when one of the atom labels in the input bond tuple does not have corresponding data in _input_geoms. """ final_geom = \ FinalGeometry(out_filename=self._out_filename, outfile_contents=self._outfile_contents, inputs=(bond_tuple[0], bond_tuple[1])) atom0, atom1 = bond_tuple[0], bond_tuple[1] # I've decided DRY here is more trouble than its worth... try: atom0_x = float(final_geom.get_datum(atom0)['x']) atom0_y = float(final_geom.get_datum(atom0)['y']) atom0_z = float(final_geom.get_datum(atom0)['z']) except TypeError: print(f'Manual calculation failed for bond {atom0}-{atom1}:' f'{atom0} geometry data not found.') return None try: atom1_x = float(final_geom.get_datum(atom1)['x']) atom1_y = float(final_geom.get_datum(atom1)['y']) atom1_z = float(final_geom.get_datum(atom1)['z']) except TypeError: print(f'Manual calculation failed for bond {atom0}-{atom1}:' f'{atom1} geometry data not found.') return None return str( round(math.sqrt(((atom0_x - atom1_x) ** 2) + ((atom0_y - atom1_y) ** 2) + ((atom0_z - atom1_z) ** 2)), 5) )
[docs] def get_datum(self, bond_tuple): """ Gives the bond length from _data for a certain bond. Parameters ---------- bond_tuple : tuple Tuple containing two atom labels, representing the desired bond. Returns ------- str String consisting of the length of the corresponding bond in Angstroms. Raises ------ KeyError This occurs when the input 'bond' tuple can't be found as a key in the dict containing the bond length data. """ # In order to find the bond length no matter which atom is listed first # in the bond tuple, this override is necessary. try: return self._data[bond_tuple] except KeyError: try: flipped_bond_tuple = (bond_tuple[1], bond_tuple[0]) return self._data[flipped_bond_tuple] except KeyError: print(f'ERROR: {bond_tuple} not found in ' f'{self._out_filename} (Bond Lengths).') return None