def allign_axis(mol: Molecule, anchor: Atom): """Allign a molecule with the Cartesian X-axis; setting **anchor** as the origin.""" try: idx = mol.atoms.index(anchor) except ValueError as ex: raise MoleculeError("The passed anchor is not in mol") from ex xyz = mol.as_array() # Allign the molecule with the X-axis rotmat = optimize_rotmat(xyz, idx) xyz[:] = xyz @ rotmat.T xyz -= xyz[idx] xyz[:] = xyz.round(decimals=3) mol.from_array(xyz)
def __exit__(self, exc_type, exc_value, traceback) -> None: """Exit the context manager; update the Cartesian coordinates of :attr:`AsArray.mol`.""" Molecule.from_array(None, self._xyz, atom_subset=self.mol) self._xyz = None
def retrieve_results(mol: Molecule, results: Results, job_preset: str) -> None: """Unpack the :class:`results` from a PLAMS-facilitated calculation. Performs an inplace update of **results**: * The Cartesian coordinates of :attr:`Results.job.molecule` are updated. * Energies and frequencies are added to :attr:`Results.job.molecule.properties`. * Paramaters ---------- mol : |plams.Molecule|_ A PLAMS molecule. results : |plams.Results|_ A PLAMS :class:`Results` instance. job_preset : str The name of a job preset from :mod:`CAT.jobs`. Accepted values are ``"single point"``, ``"geometry optimization"`` or ``"frequency analysis"``. """ if job_preset not in JOB_PRESETS: raise ValueError(f'Invalid value for job_preset: {job_preset!r}') # Unpack arguments job = results.job name = job.name # Define more arguments freq = np.empty(1) nan_dict = { 'frequencies': np.nan, 'energy': { 'E': np.nan, 'H': np.nan, 'S': np.nan, 'G': np.nan } } try: if job.status in {'failed', 'crashed'}: raise _get_results_error(results) # Read all relevant results energy = mol.properties.energy.E = results.get_energy(unit='kcal/mol') if job_preset in ('geometry optimization', 'frequency analysis'): mol_new = results.get_main_molecule() or Molecule() mol.from_array(mol_new) if job_preset == 'frequency analysis': freq = mol.properties.frequencies = results.get_frequencies() energy = mol.properties.energy = get_thermo(mol, freq, energy) # Evaluate all results if not (energy and isinstance(freq, np.ndarray)): raise _get_results_error(results) log_succes(job, mol, job_preset, name) except Exception as ex: # Failed to retrieve results if job_preset == 'geometry optimization': mol.properties.is_opt = False mol.properties.soft_update(nan_dict) log_fail(job, mol, job_preset, name) logger.debug(f'{ex.__class__.__name__}: {ex}', exc_info=True) else: if job_preset == 'geometry optimization': mol.properties.is_opt = True if job.status != 'copied': return None # results.job is a copy from a previously run job. # Exchange the attributes of results.job wth those of the revious job job_old = config.default_jobmanager.hashes[job._hash]() log_copy(job, mol, job_preset, name, job_old) rmtree(job.path) for key, value in vars(job_old).items(): if key != 'molecule': setattr(job, key, value) return None