Source code for qm_atlas.wrappers.common

import logging
import subprocess
from pathlib import Path

import numpy as np
from rdkit import Chem

_logger = logging.getLogger(__name__)


[docs] def write_xyz(mol: Chem.Mol, output_xyz: Path | str, conf_id: int = -1): """Writes an xyz file from a molecule. Args: mol (Chem.Mol): The molecule output_xyz (Path | str): The xyz file to be created conf_id (int, optional): The conformer ID to consider. Defaults to -1. """ if isinstance(output_xyz, Path): output_xyz = str(output_xyz.resolve()) Chem.MolToXYZFile(mol, output_xyz, confId=conf_id)
[docs] def read_xyz_coordinates(xyz_file: Path) -> tuple[list[str], np.ndarray]: """Read atomic symbols and coordinates from an XYZ file. Parses a standard XYZ format file and extracts the atomic symbols and their 3D coordinates. Args: xyz_file: Path to XYZ file to read Returns: tuple[list[str], np.ndarray]: A tuple ``(symbols, coordinates)`` where ``symbols`` is the list of element symbols (strings) in order of appearance and ``coordinates`` is a numpy array of shape (n_atoms, 3) with atomic coordinates in Angstrom units. Examples: >>> symbols, coords = read_xyz_coordinates("molecule.xyz") >>> print(len(symbols)) # Number of atoms >>> print(coords.shape) # (n_atoms, 3) >>> print(coords[0]) # Coordinates of first atom in Angstrom """ mol_without_connectivity = Chem.MolFromXYZFile(str(xyz_file.resolve())) coordinates = mol_without_connectivity.GetConformer().GetPositions() symbols = [atom.GetSymbol() for atom in mol_without_connectivity.GetAtoms()] return symbols, coordinates
[docs] def run_command( command: str, env: dict[str, str] | None = None, timeout: int | None = None, cwd: Path | str | None = None, ) -> tuple[str, str]: """Runs a shell command Args: command (str): The command to run env (dict[str, str], optional): Environment variables to set. Defaults to None. timeout (int, optional): Timeout in seconds. Defaults to None. cwd (Path | str, optional): Working directory for the command. Defaults to None. Raises: RuntimeError: If the command fails or times out Returns: tuple[str | None, str | None]: stdout and stderr from the command """ try: result = subprocess.run( command, shell=True, check=True, capture_output=True, text=True, env=env, timeout=timeout, cwd=cwd, ) return result.stdout, result.stderr except subprocess.CalledProcessError as exc: _logger.error(f"Command '{command}' failed with error: {exc.stderr}") _logger.error(f"stdout: {exc.stdout}") raise RuntimeError(f"Command '{command}' failed") from exc except subprocess.TimeoutExpired as exc: _logger.error(f"Command '{command}' timed out after {timeout} seconds") raise RuntimeError(f"Command '{command}' timed out after {timeout} seconds") from exc