Source code for aiida_aimall.workchains.input

"""Base input workchain"""
from aiida.engine import WorkChain, if_
from aiida.engine.processes import ExitCode
from aiida.orm import SinglefileData, Str, StructureData

from aiida_aimall.workchains.calcfunctions import (
    generate_structure_data,
    get_molecule_str_from_smiles,
    xyzfile_to_StructureData,
)


[docs]class BaseInputWorkChain(WorkChain): """A workchain to generate and validate inputs. Provided an .xyz file as `SinglefileData`, molecule `StructureData`, or SMILES of the molecule validates that only one is provided. Then, prepares the input into a format for future GaussianCalculations. Attributes: structure (aiida.orm.StructureData): StructureData of molecule to run smiles (aiida.orm.Str): smiles string of molecule xyz_file (aiida.orm.SinglefileData): file data of an xyz file Note: This is a base class that is used by other WorkChains (:func:`aiida_aimall.workchains.subparam.SubstituentParameterWorkChain`, and :func:`aiida_aimall.workchains.qc_programs.GaussianToAIMWorkChain`) """ @classmethod
[docs] def define(cls, spec): super().define(spec) spec.input( "structure", valid_type=StructureData, required=False, help="StructureData of molecule to run", ) spec.input( "smiles", valid_type=Str, required=False, help="smiles string of molecule" ) spec.input( "xyz_file", valid_type=SinglefileData, required=False, help="file data of an xyz file", ) spec.exit_code( 200, "ERROR_MULTIPLE_INPUTS", "the process received two or more of the following inputs: structure, smiles, xyz_file", ) spec.exit_code( 201, "ERROR_NO_INPUTS", "None of structure, smiles, xyz_file were provided, at least one must be", ) spec.outline( cls.validate_input, if_(cls.is_xyz_input)(cls.create_structure_from_xyz), if_(cls.is_smiles_input)( cls.get_molecule_inputs_step, cls.string_to_StructureData ), if_(cls.is_structure_input)(cls.structure_in_context), )
[docs] def is_xyz_input(self): """Validates if xyz_file was provided as input""" if "xyz_file" in self.inputs: return True return False
[docs] def is_smiles_input(self): """Validates if smiles was provided as input""" if "smiles" in self.inputs: return True return False
[docs] def is_structure_input(self): """Validates if structure was provided as input""" if "structure" in self.inputs: return True return False
# pylint:disable=inconsistent-return-statements
[docs] def validate_input(self): """Check that only one of smiles, structure, or xyz_file was input""" if "smiles" in self.inputs and ( "xyz_file" in self.inputs or "structure" in self.inputs ): return ExitCode(200) if "xyz_file" in self.inputs and ( "smiles" in self.inputs or "structure" in self.inputs ): return ExitCode(200) if "structure" in self.inputs and ( "xyz_file" in self.inputs or "smiles" in self.inputs ): return ExitCode(200) if ( "structure" not in self.inputs and "xyz_file" not in self.inputs and "smiles" not in self.inputs ): return ExitCode(201)
[docs] def create_structure_from_xyz(self): """Convert the xyzfile to StructureData. Calls :func:`aiida_aimall.workchains.calcfunctions.xyzfile_to_StructureData`""" self.ctx.structure = xyzfile_to_StructureData(self.inputs.xyz_file)
[docs] def structure_in_context(self): """Store the input structure in context, to make consistent with the results of xyz_file or SMILES input.""" self.ctx.structure = self.inputs.structure
[docs] def get_molecule_inputs_step(self): """Given list of substituents and previously done smiles, get input. Calls :func:`aiida_aimall.workchains.calcfunctions.get_molecule_str_from_smiles`""" self.ctx.smiles_geom = get_molecule_str_from_smiles(self.inputs.smiles)
[docs] def string_to_StructureData(self): """Convert an xyz string of molecule geometry to StructureData. Calls :func:`aiida_aimall.workchains.calcfunctions.generate_structure_data`""" self.ctx.structure = generate_structure_data(self.ctx.smiles_geom)