def call_qcengine( self, molecule: Ligand, extras: Optional[Dict[str, str]] = None, ) -> qcel.models.AtomicResult: """ Calculate the requested property using qcengine for the given molecule. Args: molecule: The QUBEKit ligand that the calculation should be ran on. extras: Any extra calculation keywords that are program specific. Returns: The full qcelemental atomic result so any required information can be extracted. """ qc_mol = molecule.to_qcschema() # default keywords keywords = { "scf_type": "df", # make sure we always use an ultrafine grid "dft_spherical_points": 590, "dft_radial_points": 99, } if extras is not None: keywords.update(extras) task = qcel.models.AtomicInput( molecule=qc_mol, driver=self.driver, model=self.qc_model, keywords=keywords, ) result = qcng.compute(task, self.program, local_options=self.local_options) return result
def optimise( self, molecule: Ligand, allow_fail: bool = False, return_result: bool = False, extras: Optional[Dict[str, Any]] = None, ) -> Tuple[Ligand, Optional[qcel.models.OptimizationResult]]: """ For the given specification in the class run an optimisation on the ligand. Run the specified optimisation on the ligand the final coordinates are extracted and stored in the ligand. The optimisation schema is dumped to file along with the optimised geometry and the trajectory. Args: molecule: The molecule which should be optimised allow_fail: If we should not raise an error if the molecule fails to be optimised, this will extract the last geometry from the trajectory and return it. return_result: If the full result json should also be returned useful for extracting the trajectory. extras: A dictionary of extras that should be used to update the optimiser keywords. Returns: A new copy of the molecule at the optimised coordinates. """ # first validate the settings self._validate_specification() # now validate that the programs are installed self.check_available(program=self.program, optimiser=self.optimiser) # now we need to distribute the job model = self.qc_model specification = qcel.models.procedures.QCInputSpecification( model=model, keywords={"dft_spherical_points": 590, "dft_radial_points": 99} ) initial_mol = molecule.to_qcschema() optimiser_keywords = self.build_optimiser_keywords() if extras is not None: optimiser_keywords.update(extras) opt_task = qcel.models.OptimizationInput( initial_molecule=initial_mol, input_specification=specification, keywords=optimiser_keywords, ) opt_result = qcng.compute_procedure( input_data=opt_task, procedure=self.optimiser, raise_error=False, local_options=self.local_options, ) # dump info to file result_mol = self.handle_output(molecule=molecule, opt_output=opt_result) # check if we can/have failed and raise the error if not opt_result.success and not allow_fail: raise RuntimeError( f"{opt_result.error.error_type}: {opt_result.error.error_message}" ) full_result = opt_result if return_result else None return result_mol, full_result