Source code for src.structure_data_builder
#!/usr/bin/env python3
"""
Provides a Builder which creates StructureData instances.
This class uses the Builder design pattern to create instances of
the StructureData class based on a given filename for an input .txt file.
"""
__author__ = "Peter Waddell"
__copyright__ = "Copyright 2024"
__credits__ = ["Peter Waddell"]
__version__ = "0.1.1"
__date__ = "2024/12/30"
__maintainer__ = "Peter Waddell"
__email__ = "pmwaddell9@gmail.com"
__status__ = "Prototype"
from orca_data_extraction.src.structure_data import StructureData
from orca_data_extraction.src.input_reader_json import InputReaderJSON
from orca_data_extraction.src.initial_geom import InitialGeometry
from orca_data_extraction.src.final_geom import FinalGeometry
from orca_data_extraction.src.mulliken_charges import MullikenCharges
from orca_data_extraction.src.mulliken_charge_sums import MullikenChargeSums
from orca_data_extraction.src.loewdin_charges import LoewdinCharges
from orca_data_extraction.src.loewdin_charge_sums import LoewdinChargeSums
from orca_data_extraction.src.homo_lumo_energies import HOMOLUMOEnergies
from orca_data_extraction.src.bond_lengths import BondLengths
from orca_data_extraction.src.bond_angles import BondAngles
from orca_data_extraction.src.polarizability import Polarizability
from orca_data_extraction.src.dipole_moments import DipoleMoments
[docs]
class StructureDataBuilder:
"""
A Builder which creates StructureData instances.
Attributes
----------
__input_filename : str
String of filename of .txt file that contains lists of desired atom
labels for each type of data that will be pulled from the .out file.
__input_reader : InputReaderJSON
Instance of InputReader used to retrieve the inputs for the
StructureData objects this instance builds.
"""
def __init__(self, input_filename):
"""
Parameters
----------
input_filename : str
String of filename of .txt file that contains lists of desired atom
labels for each type of data that will be pulled from the .out file.
"""
self.__input_filename = input_filename
# TODO: another opportunity for Dependency Injection???? or not????
self.__input_reader = InputReaderJSON(input_filename)
[docs]
def build(self, out_filename):
"""
Creates and returns an instance of StructureData based on the passed
.out filename and the input filename attribute.
Parameters
----------
out_filename : str
String of filename of desired .out file.
Returns
-------
StructureData
Instance of StructureData based on the passed .out filename and the
input filename attribute.
"""
def create_data_sections():
"""
Creates a dictionary to be passed to the StructureData constructor;
this dict is held as the __data_sections attribute of that object.
Returns
-------
dict
Dictionary mapping strings of section names to corresponding
DataSection subclasses related to the Schrödinger .out file,
which are instantiated based on inputs from __input_reader.
"""
def add_inputs_section(name, data_section, inputs=()):
"""
Adds a key-value pair to data_sections: the key is the name of
the particular DataSection subclass to be added, and the value
is the instance of this subclass.
Parameters
----------
name : str
Name of the DataSection subclass.
data_section : DataSection
Instance of the DataSection subclass.
inputs : tuple
Tuple of inputs from __input_reader for the particular
DataSection subclass.
"""
if inputs:
data_sections[name] = \
data_section(out_filename=out_filename,
outfile_contents=outfile_contents,
inputs=inputs)
data_sections = {}
# TODO: possibly abstract this to make this class plug-n-play
add_inputs_section('Initial Geometry', InitialGeometry,
self.__input_reader.get_initial_geom_inputs())
add_inputs_section('Final Geometry', FinalGeometry,
self.__input_reader.get_final_geom_inputs())
add_inputs_section('Bond Lengths', BondLengths,
self.__input_reader.get_bond_length_inputs())
add_inputs_section('Bond Angles', BondAngles,
self.__input_reader.get_bond_angle_inputs())
data_sections['Polarizability'] = \
Polarizability(out_filename=out_filename,
outfile_contents=outfile_contents)
data_sections['Dipole Moments'] = \
DipoleMoments(out_filename=out_filename,
outfile_contents=outfile_contents)
data_sections['HOMO LUMO Energies'] = \
HOMOLUMOEnergies(out_filename=out_filename,
outfile_contents=outfile_contents)
add_inputs_section('Mulliken Charges', MullikenCharges,
self.__input_reader.get_mulliken_charge_inputs())
add_inputs_section('Mulliken Charge Sums', MullikenChargeSums,
self.__input_reader.
get_mulliken_charge_sum_inputs())
add_inputs_section('Loewdin Charges', LoewdinCharges,
self.__input_reader.get_loewdin_charge_inputs())
add_inputs_section('Loewdin Charge Sums', LoewdinChargeSums,
self.__input_reader.
get_loewdin_charge_sum_inputs())
return data_sections
outfile_contents = self.__read_file(out_filename)
return StructureData(
out_filename, self.__input_filename, create_data_sections())
# TODO: probs will make this another class I guess for reading files I mean
@staticmethod
def __read_file(f):
"""
Converts a text file to a single string using .read().
Parameters
----------
f : str
Filename of the desired file to read.
Returns
-------
contents : str
String containing the full text of the file.
Raises
------
FileNotFoundError
If f is not the filename of a file in the current directory.
"""
try:
with open(f) as file_object:
contents = file_object.read()
except FileNotFoundError:
print(f"File {f} not found")
else:
file_object.close()
return contents