Tasks

Module collecting methods for force-field based conformer generation

qm_atlas.tasks.conformer_generation.generate_corina_conformers(mol, **kwargs)[source]

Generate a 3D conformer for mol using CORINA (explicit Hs are added first).

Parameters:

mol (Mol)

qm_atlas.tasks.conformer_generation.generate_omega_conformers(mol, **kwargs)[source]

Generate conformers for mol using OpenEye OMEGA.

Parameters:

mol (Mol)

qm_atlas.tasks.conformer_generation.generate_moe_conformers(mol, **kwargs)[source]

Generate conformers for mol using MOE.

Parameters:

mol (Mol)

qm_atlas.tasks.conformer_generation.generate_macromodel_conformers(mol, **kwargs)[source]

Generate conformers for mol using MacroModel.

Parameters:

mol (Mol)

qm_atlas.tasks.conformer_generation.generate_macrocycle_conformers(mol, **kwargs)[source]

Generate macrocycle conformers for mol using MacroModel.

Parameters:

mol (Mol)

qm_atlas.tasks.conformer_generation.generate_rdkit_conformers(mol, method='KDG', max_conformers=1000, rms_threshold=DEFAULT_RMSD_THRESHOLD, random_seed=1, scr=None)[source]
Calls rdkit to generate conformers and deduplicates them according to

the RMSD between them.

Parameters:
  • mol (Mol) – The input graph.

  • method (str) – The RDKit embedding method (a key of RDKIT_METHODS, e.g. “ETKDGv3”). Defaults to “KDG”.

  • max_conformers (int) – The maximal number of conformers to generate. Defaults to 1000.

  • rms_threshold (float) – The threshold value for the RMSD to use for the deduplication. Defaults to DEFAULT_RMSD_THRESHOLD.

  • random_seed (int) – A random seed to get reproducible results from the rdkit conformer generator. Defaults to 1.

  • scr (Path | None) – Unused; accepted for API compatibility with the other generators. Defaults to None.

Returns:

The molecule with conformers. Returns None if the code fails.

Return type:

Mol | None

class qm_atlas.tasks.conformer_generation.ConformerGeneratorOptions(**data)[source]

Base class for conformer generator backends.

Each concrete backend declares a unique backend literal that acts as the discriminator for (de)serialization within ConformerGeneratorConfig.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class qm_atlas.tasks.conformer_generation.MacromodelOptions(**data)[source]

Options for Macromodel conformer generation.

Parameters:
  • backend (Literal['macromodel'])

  • rms_threshold (float)

  • max_conformers (int)

  • mode (str)

  • force_field (int)

  • solvent_num (int)

  • license_buffer (int)

  • license_timeout (int)

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['macromodel']
rms_threshold: float
max_conformers: int
mode: str
force_field: int
solvent_num: int
license_buffer: int
license_timeout: int
class qm_atlas.tasks.conformer_generation.OmegaOptions(**data)[source]

Options for OpenEye Omega conformer generation.

Parameters:
  • backend (Literal['omega'])

  • rms_threshold (float)

  • max_conformers (int)

  • start_from_corina (bool)

  • n_cores (int)

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['omega']
rms_threshold: float
max_conformers: int
start_from_corina: bool
n_cores: int
class qm_atlas.tasks.conformer_generation.MoeOptions(**data)[source]

Options for MOE conformer generation.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['moe']
rms_threshold: float
max_conformers: int
mode: str
class qm_atlas.tasks.conformer_generation.CorinaOptions(**data)[source]

Options for CORINA conformer generation.

Parameters:

backend (Literal['corina'])

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['corina']
class qm_atlas.tasks.conformer_generation.RdkitOptions(**data)[source]

Options for RDKit conformer generation.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['rdkit']
method: str
max_conformers: int
rms_threshold: float
random_seed: int
classmethod validate_method(v)[source]
Return type:

str

Parameters:

v (str)

class qm_atlas.tasks.conformer_generation.MacrocycleOptions(**data)[source]

Options for Macrocycle conformer generation.

Parameters:
  • backend (Literal['macrocycle'])

  • max_conformers (int)

  • energy_cutoff (float)

  • rms_threshold (float)

  • num_cores (int)

  • license_buffer (int)

  • license_timeout (int)

  • extra_data (Any)

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['macrocycle']
max_conformers: int
energy_cutoff: float
rms_threshold: float
num_cores: int
license_buffer: int
license_timeout: int
qm_atlas.tasks.conformer_generation.get_generator_function(name)[source]

Get the conformer generator function for a given generator name.

Parameters:

name (str)

qm_atlas.tasks.conformer_generation.deserialize_conformer_generator_config(v)[source]

Convert a dict into the appropriate conformer generator options class.

Return type:

object

Parameters:

v (object)

qm_atlas.tasks.conformer_generation.join_conformers(mol_1, mol_2)[source]
Merges the conformers of two molecule objects representing the same graph.

For convenience either of the input molecules can be None, in this case the other is returned.

Parameters:
  • mol_1 (Mol | None) – An rdkit molecule or None.

  • mol_2 (Mol | None) – An rdkit molecule or None.

Returns:

A molecule representing the same graph, with all conformers set on either of the input molecules.

Return type:

Mol | None

qm_atlas.tasks.conformer_generation.generate_conformers_with_fallback(mol, conf_gens)[source]
Allows to specify fall-backs for failed conformer generations.

The conformer generators are called in order until one succeeds.

Parameters:
Returns:

The molecule with all conformers. Returns None if all generators fail.

Return type:

Mol | None

qm_atlas.tasks.conformer_generation.generate_joint_conformer_set(mol, conf_gens, rms_threshold=DEFAULT_RMSD_THRESHOLD, rmsd_method='tradeoff', num_cores=1, trace_dir=constants.DEFAULT_SCR, write_intermediates=False)[source]
Calls different conformer generators, merges their results and deduplicates

according to RMSD between conformers.

Parameters:
  • mol (Mol) – The rdkit molecule.

  • conf_gens (list[MacromodelOptions | OmegaOptions | MoeOptions | CorinaOptions | RdkitOptions | MacrocycleOptions]) – The conformer generator option objects to use. Each is a typed options object whose backend field selects the generator.

  • rms_threshold (float) – The rmsd threshold to use for the deduplication. Defaults to DEFAULT_RMSD_THRESHOLD. If you pass None, no deduplication will be performed.

  • rmsd_method (str) – The RMSD algorithm used during deduplication. Defaults to “tradeoff”.

  • num_cores (int) – Number of CPU cores to use for the deduplication. Defaults to 1.

  • trace_dir (Path) – Directory to write per-generator intermediate SDFs to when write_intermediates is True. Defaults to DEFAULT_SCR.

  • write_intermediates (bool) – If True, writes each generator’s conformers to trace_dir for debugging. Defaults to False.

Returns:

The molecule with all conformers. Returns None if all generators fail.

Return type:

Mol | None

class qm_atlas.tasks.conformer_generation.ConformerGenerationOptions(**data)[source]

Options for the generate_conformers task.

Parameters:
conf_gens: list[Annotated[MacromodelOptions | OmegaOptions | MoeOptions | CorinaOptions | RdkitOptions | MacrocycleOptions, FieldInfo(annotation=NoneType, required=True, discriminator='backend')]]
combination_name: Literal['joint_set', 'fallback']
rms_threshold: float
rmsd_method: str
classmethod deserialize_conf_gens(v)[source]

Deserialize conformer generator configs from dicts.

Return type:

object

Parameters:

v (object)

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

qm_atlas.tasks.conformer_generation.generate_conformers(mol, conformer_generation_options, num_cores=1, trace_dir=constants.DEFAULT_SCR, write_intermediates=False)[source]

Main entry point for conformer generation. Dispatches to the appropriate method based on the combination_name.

Return type:

Mol | None

Parameters:
class qm_atlas.tasks.calculate_properties.PropertyCalculatorOptions(**data)[source]

Base class for property calculator options. Not used directly, but serves as a common parent for all calculator option classes.

Parameters:
  • property_prefix (str | None)

  • extra_data (Any)

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property_prefix: str | None
get_property_prefix()[source]
Return type:

str

get_property_names()[source]

Generate property names based on non-default settings. Must be implemented by each calculator options class.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types. Must be implemented by each calculator options class.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.XtbSinglePointOptions(**data)[source]

Options for xtb.calculate_single_point (exposed CLI parameters only).

To customise the input beyond the exposed fields, supply a fully rendered template_str; unknown keyword arguments are rejected.

Parameters:
  • property_prefix (str | None)

  • backend (Literal['xtb_single_point'])

  • solvation_model (str | None)

  • solvent (str | None)

  • calculate_fukui (bool)

  • xtb_command_add (list[str] | None)

  • template_str (str | None)

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['xtb_single_point']
solvation_model: str | None
solvent: str | None
calculate_fukui: bool
xtb_command_add: list[str] | None
template_str: str | None
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix based on solvation settings.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.TurbomoleSinglePointOptions(**data)[source]

Options for turbomole.single_point.run_ridft.

To customise the input beyond the exposed fields, supply a fully rendered control_template; unknown keyword arguments are rejected.

Parameters:
  • property_prefix (str | None)

  • backend (Literal['turbomole_single_point'])

  • basis (str)

  • functional (list[str])

  • grid (str)

  • scf_conv (int)

  • scfiterlimit (int)

  • ricore (int | None)

  • use_disp (bool)

  • use_cosmo (bool)

  • klamt (bool)

  • solvent (str)

  • control_template (str | None)

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['turbomole_single_point']
basis: str
functional: list[str]
grid: str
scf_conv: int
scfiterlimit: int
ricore: int | None
use_disp: bool
use_cosmo: bool
klamt: bool
solvent: str
control_template: str | None
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.TurbomoleFreehOptions(**data)[source]

Options for turbomole.freeh.calculate_freeh.

To customise the input beyond the exposed fields, supply a fully rendered control_template; unknown keyword arguments are rejected.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['turbomole_freeh']
basis: str
functional: list[str] | tuple[str, ...]
grid: str
scf_conv: int
scfiterlimit: int
scfdamp: str
ricore: int | None
use_disp: bool
use_cosmo: bool
klamt: bool
solvent: str
freeh_settings: str
control_template: str | None
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.TurbomoleFukuiOptions(**data)[source]

Options for turbomole.fukui.calculate_fukui.

To customise the input beyond the exposed fields, supply a fully rendered control_template; unknown keyword arguments are rejected.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['turbomole_fukui_indices']
basis: str
functional: list[str] | tuple[str, ...]
grid: str
scf_conv: int
scfiterlimit: int
scfdamp: str
ricore: int | None
use_disp: bool
use_cosmo: bool
klamt: bool
solvent: str
charge_schemes: list[str] | None
control_template: str | None
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_atom_property_names()[source]
Return type:

dict[str, str]

get_scalar_property_names()[source]
Return type:

dict[str, str]

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.TurbomoleNmrShieldingOptions(**data)[source]

Options for turbomole.nmr_shielding.calculate_nmr_shieldings (exposed CLI parameters only).

To customise the input beyond the exposed fields, supply a fully rendered control_template; unknown keyword arguments are rejected.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['turbomole_nmr_shielding']
basis: str
functional: list[str] | tuple[str, ...]
grid: str
scf_conv: int
scfiterlimit: int
ricore: int | None
use_disp: bool
use_cosmo: bool
klamt: bool
solvent: str
control_template: str | None
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.TurbomoleVcdOptions(**data)[source]

Options for turbomole.vcd.calculate_vcd (exposed CLI parameters only).

To customise the input beyond the exposed fields, supply a fully rendered control_template; unknown keyword arguments are rejected.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['turbomole_vcd']
basis: str
functional: list[str] | tuple[str, ...]
grid: str
scf_conv: int
scfiterlimit: int
ricore: int | None
use_disp: bool
use_cosmo: bool
klamt: bool
solvent: str
control_template: str | None
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.JaguarHydrogenAbstractionOptions(**data)[source]

Options for jaguar.bond_dissociation.get_hydrogen_abstraction_energies.

Note: Internal parameters like keep_files, scr, and n_cores are not exposed via CLI.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['jaguar_h_abstraction_energies']
atom_idcs: list[int] | str
geo_opt_settings: dict[str, str] | None
single_point_settings: dict[str, str] | None
jaguar_options: dict[str, str] | None
license_buffer: int
license_timeout: int
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

class qm_atlas.tasks.calculate_properties.JaguarQmDescriptorsOptions(**data)[source]

Options for jaguar.qm_descriptors.calculate_descriptors (exposed CLI parameters only).

Note: Internal parameters like keep_files, scr, and n_cores are not exposed via CLI.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['jaguar_properties']
properties: list[str] | tuple[str, ...]
basis: str
functional: list[str] | tuple[str, ...]
jaguar_options: dict[str, str] | None
license_buffer: int
license_timeout: int
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]

Generate property names based on non-default settings.

Return type:

dict[str, str]

get_property_types()[source]

Map output keys to Property types.

Return type:

dict[str, type]

qm_atlas.tasks.calculate_properties.create_calculation_config(backend, **kwargs)[source]

Convenience function to create a CalculationConfig object based on the backend and provided options.

Return type:

XtbSinglePointOptions | TurbomoleSinglePointOptions | TurbomoleFreehOptions | TurbomoleFukuiOptions | TurbomoleNmrShieldingOptions | TurbomoleVcdOptions | JaguarHydrogenAbstractionOptions | JaguarQmDescriptorsOptions

Parameters:

backend (str)

qm_atlas.tasks.calculate_properties.calculate_property(mol, conf_id, config, suppress_errors=True, scr=DEFAULT_SCR, n_cores=1, keep_files=False)[source]

Calculate a molecular property for a single conformer using a specified calculator.

Dispatches to the appropriate calculator backend based on the backend specified in the config object. Operates on a single conformer identified by its ID within a molecule.

Parameters:
  • mol (Mol) – RDKit molecule containing the conformer to analyze.

  • conf_id (int) – ID of the conformer within the molecule to calculate the property for.

  • config (XtbSinglePointOptions | TurbomoleSinglePointOptions | TurbomoleFreehOptions | TurbomoleFukuiOptions | TurbomoleNmrShieldingOptions | TurbomoleVcdOptions | JaguarHydrogenAbstractionOptions | JaguarQmDescriptorsOptions) – Configuration object specifying the calculator to use and its options. The backend attribute determines which backend is used. Available config options are: - XtbSinglePointOptions for xtb single-point calculations - TurbomoleSinglePointOptions for turbomole single-point calculations - TurbomoleFreehOptions for turbomole freeh calculations - TurbomoleFukuiOptions for turbomole Fukui index calculations - TurbomoleNmrShieldingOptions for turbomole NMR shielding calculations - TurbomoleVcdOptions for turbomole VCD calculations - JaguarHydrogenAbstractionOptions for Jaguar hydrogen abstraction energy calculations - JaguarQmDescriptorsOptions for Jaguar QM descriptor calculations

  • suppress_errors (bool) – If True, suppresses exceptions during calculation and returns None on failure. If False, exceptions are propagated. Defaults to True.

  • scr (Path) – Scratch directory path for temporary calculation files. Defaults to DEFAULT_SCR.

  • n_cores (int) – Number of CPU cores to use for the calculation. Defaults to 1.

  • keep_files (bool) – If True, preserves temporary calculation files after completion. If False, cleans up temporary files. Defaults to False.

Returns:

Dictionary mapping property names to Property objects. Each Property object contains the calculated value and associated metadata. Returns None if the calculation failed and suppress_errors is True.

Return type:

dict[str, Property] | None

Raises:
  • ValueError – If config.backend is not found in CALCULATOR_REGISTRY.

  • RuntimeError – If the underlying calculator function raises an error and suppress_errors is False.

Examples

>>> from rdkit import Chem, AllChem
>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMolecule(mol)
>>> config = XtbSinglePointOptions()
>>> props = calculate_property(mol, 0, config)
>>> energy = props["energy"].get_property_value()
qm_atlas.tasks.calculate_properties.calculate_property_conformer(conf, config, suppress_errors=True, scr=DEFAULT_SCR, n_cores=1, keep_files=False)[source]

Calculate a molecular property for a conformer using a specified calculator.

Convenience wrapper around calculate_property that accepts an RDKit Conformer object directly instead of requiring the separate molecule and conformer ID. Extracts the owning molecule and conformer ID automatically.

Parameters:
Returns:

Dictionary mapping property names to Property objects containing calculated values and metadata.

Return type:

dict[str, Property] | None

Raises:
  • ValueError – If config.backend is not found in CALCULATOR_REGISTRY.

  • RuntimeError – If the underlying calculator function raises an error and suppress_errors is False.

Examples

>>> from rdkit import Chem, AllChem
>>> mol = Chem.MolFromSmiles("CC")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMolecule(mol)
>>> conformer = mol.GetConformer()
>>> config = XtbSinglePointOptions()
>>> props = calculate_property_conformer(conformer, config)
qm_atlas.tasks.calculate_properties.calculate_property_mol(mol, config, n_cores=1, show_progress=False, scr=DEFAULT_SCR, keep_files=False)[source]

Calculate a molecular property for all conformers of a molecule. Uses multiprocessing if multiple CPU cores are specified.

Automatically handles conformer iteration and returns results organized by conformer.

Parameters:
Returns:

List of property dictionaries, one for each conformer in the input molecule. Each element is either a dict of calculated Property objects or None if the calculation failed. The list length matches the number of conformers in the input molecule.

Return type:

list[dict[str, Property] | None]

Raises:

ValueError – If config.backend is not found in CALCULATOR_REGISTRY.

Examples

>>> from rdkit import Chem, AllChem
>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMultipleConfs(mol, 3)
>>> config = XtbSinglePointOptions()
>>> all_props = calculate_property_mol(mol, config)
>>> # all_props is a list of 3 property dicts, one for each conformer
>>> energy_conf_0 = all_props[0]["energy"].get_property_value()
qm_atlas.tasks.calculate_properties.calculate_property_mols(mols, config, n_cores=1, show_progress=False, scr=DEFAULT_SCR, keep_files=False)[source]

Calculate a molecular property for all conformers across multiple molecules in parallel.

High-level function for batch property calculation. All conformers from all molecules are processed in parallel to maximize computational efficiency. Results are automatically reorganized by molecule in the output.

Parameters:
Returns:

Nested list organized as: output[mol_idx][conf_idx] = properties_dict Each properties_dict contains calculated Property objects or None if the calculation failed. Output list length matches input list length. Inner list lengths match the number of conformers for each molecule.

Return type:

list[list[dict[str, Property] | None]]

Raises:

ValueError – If config.backend is not found in CALCULATOR_REGISTRY.

Notes

  • All conformers from all molecules are flattened for parallel processing, then reorganized into the original molecule structure before returning.

  • Failed calculations return None in the output while other calculations continue.

  • Progress title in the progress bar is derived from the calculator name.

Examples

>>> from rdkit import Chem, AllChem
>>> mols = [Chem.MolFromSmiles("CCO"), Chem.MolFromSmiles("CC")]
>>> for mol in mols:
...     mol = Chem.AddHs(mol)
...     AllChem.EmbedMultipleConfs(mol, 2)
>>> config = XtbSinglePointOptions()
>>> results = calculate_property_mols(
...     mols, config,
...     n_cores=4, show_progress=True
... )
>>> # results[0] contains property dicts for 2 conformers of first molecule
>>> # results[1] contains property dicts for 2 conformers of second molecule
qm_atlas.tasks.calculate_properties.extract_cosmo_output(calculated_properties, remove_from_dict=False)[source]

Extract and optionally remove COSMO output string from calculated properties.

Utility function to retrieve COSMO (conductor-like screening model) output data from a property dictionary. COSMO outputs are typically large text blocks containing detailed solvation calculations that are stored separately from scalar properties.

Parameters:
  • calculated_properties (dict[str, Property] | None) – Dictionary of calculated Property objects, typically returned from a calculator function. Can be None, in which case None is returned.

  • remove_from_dict (bool) – If True, removes the COSMO output from the dictionary after extraction (destructive operation). If False, leaves the dictionary unchanged. Defaults to False.

Returns:

COSMO output string if found in the properties dictionary, or None if: - calculated_properties is None - The COSMO_OUTPUT_KEY is not present in the dictionary

Return type:

str | None

Notes

  • This function is useful for processing and storing COSMO data separately from other property data when needed for archival or memory management.

  • The COSMO_OUTPUT_KEY constant is imported from qm_atlas.constants.

  • When remove_from_dict=True, the dictionary is modified in-place.

Examples

>>> from qm_atlas.tasks.calculate_properties import (
...     calculate_property, extract_cosmo_output
... )
>>> props = calculate_property(mol, 0, "turbomole_single_point")
>>> cosmo_str = extract_cosmo_output(props)  # Retrieve without removing
>>> if cosmo_str:
...     print("COSMO output found")
>>> # To extract and clean up the dictionary:
>>> cosmo_str = extract_cosmo_output(props, remove_from_dict=True)
>>> # props now no longer contains COSMO data
qm_atlas.tasks.calculate_properties.get_xtb_energies_and_weights(molobj, final_xtb_sp_configs=None, show_progress=True, scr=DEFAULT_SCR)[source]

Calculate XTB solvation energies and Boltzmann weights for all conformers.

Runs single-point XTB calculations for each solvation config on every conformer of molobj, then computes normalized Boltzmann weights per solvent.

Parameters:
  • molobj (Mol) – Molecule with one or more conformers.

  • final_xtb_sp_configs (list[XtbSinglePointOptions] | None) – List of XTB single-point configs (one per solvent). Defaults to XTB_SP_SOLVENT_CONFIGS (water, woctanol, chcl3).

  • show_progress (bool) – Show tqdm progress bar.

  • scr (Path) – Scratch directory for xTB calculations.

Return type:

list[dict]

Returns:

List of dicts, one per conformer. Each dict contains energy_{solvent} and weight_{solvent} keys for every config.

Geometry optimization workflows supporting multiple drivers.

This module provides a unified interface for geometry optimization using different computational chemistry backends. Currently, the following optimization drivers are supported:

  • Turbomole/jobex: DFT-level geometry optimization.

  • xtb-driven Turbomole: DFT-level geometry optimization using the xtb optimizer and turbomole for the energy/gradient calculations.

  • xtb only: semi-empirical geometry optimization (fast).

All functions follow the same interface and support parallel execution.

class qm_atlas.tasks.optimize.OptimizationOptions(**data)[source]

Base class for geometry optimization backends.

Each concrete backend declares a unique backend literal that acts as the discriminator for (de)serialization within OptimizationConfig.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class qm_atlas.tasks.optimize.XtbOptions(**data)[source]

Options specific to the xtb optimization driver.

Parameters:
  • backend (Literal['xtb'])

  • max_num_steps (Annotated[int, Ge(ge=1)])

  • method (str)

  • opt_level (Literal['crude', 'sloppy', 'loose', 'lax', 'normal', 'tight', 'verytight', 'extreme'])

  • solvation_model (str | None)

  • solvent (str | None)

  • constrain (bool)

  • torsions_fixed (bool)

  • heavy_atom_torsions_fixed (bool)

  • angles_fixed (bool)

  • bonds_fixed (bool)

  • force_constant (float)

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['xtb']
max_num_steps: int
method: str
opt_level: Literal['crude', 'sloppy', 'loose', 'lax', 'normal', 'tight', 'verytight', 'extreme']
solvation_model: str | None
solvent: str | None
constrain: bool
torsions_fixed: bool
heavy_atom_torsions_fixed: bool
angles_fixed: bool
bonds_fixed: bool
force_constant: float
check_solvation()[source]
Return type:

XtbOptions

class qm_atlas.tasks.optimize.JobexOptions(**data)[source]

Options specific to the Turbomole jobex optimization driver.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['jobex']
max_num_steps: int
energy_conv: int
geom_conv: int
functional: list[str]
basis: str
scf_conv: int
scfiterlimit: int
use_disp: bool
use_cosmo: bool
solvent: str
class qm_atlas.tasks.optimize.XtbTurbomoleOptions(**data)[source]

Options specific to the xtb-driven Turbomole optimization driver.

Parameters:
  • backend (Literal['xtb_turbomole'])

  • max_num_steps (Annotated[int, Ge(ge=1)])

  • opt_level (Literal['crude', 'sloppy', 'loose', 'lax', 'normal', 'tight', 'verytight', 'extreme'])

  • functional (list[str])

  • basis (str)

  • scf_conv (int)

  • scfiterlimit (int)

  • use_disp (bool)

  • use_cosmo (bool)

  • solvent (str)

  • constrain (bool)

  • torsions_fixed (bool)

  • heavy_atom_torsions_fixed (bool)

  • angles_fixed (bool)

  • bonds_fixed (bool)

  • force_constant (float)

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['xtb_turbomole']
max_num_steps: int
opt_level: Literal['crude', 'sloppy', 'loose', 'lax', 'normal', 'tight', 'verytight', 'extreme']
functional: list[str]
basis: str
scf_conv: int
scfiterlimit: int
use_disp: bool
use_cosmo: bool
solvent: str
constrain: bool
torsions_fixed: bool
heavy_atom_torsions_fixed: bool
angles_fixed: bool
bonds_fixed: bool
force_constant: float
qm_atlas.tasks.optimize.optimize_with_fallback(mol, conf_id, config, treat_unconverged_as_failure=True, suppress_errors=True, log_errors=True, n_cores=1, scr=DEFAULT_SCR, keep_files=False)[source]

Optimize a conformer with automatic fallback to alternative drivers on failure.

Attempts to optimize a single conformer using the specified optimization driver. If optimization fails (raises an exception) or does not converge (when treat_unconverged_as_failure=True), automatically attempts fallback drivers in the order specified. This provides robustness by allowing optimization to fall back to less sophisticated but more stable methods.

Parameters:
  • mol (Mol) – RDKit molecule containing the conformer to optimize.

  • conf_id (int) – ID of the conformer within the molecule to optimize.

  • config (list[XtbOptions | JobexOptions | XtbTurbomoleOptions]) – Primary optimization configuration or list of configurations to try in order.

  • treat_unconverged_as_failure (bool) – If True, treats unconverged optimizations as failures and attempts fallbacks. If False, returns the results of the primary optimization even if unconverged. Defaults to True.

  • suppress_errors (bool) – If True, returns (None, None) on failure instead of raising an exception. If False, raises RuntimeError on optimization failure. Defaults to True.

  • log_errors (bool) – If True, logs an error when all optimization attempts fail. Set to False in bulk/parallel runs where a summary warning is emitted instead. Defaults to True.

  • n_cores (int) – Number of CPU cores to use for the optimization. Defaults to 1.

  • scr (Path) – Path to the scratch directory for temporary files. Defaults to DEFAULT_SCR.

  • keep_files (bool) – If True, keeps intermediate files generated during optimization. Defaults to False.

Returns:

The optimized coordinates and the dict of calculated properties, or (None, None) if optimization failed and suppress_errors=True.

Return type:

tuple[ndarray | None, dict[str, Property] | None]

qm_atlas.tasks.optimize.optimize_conformer(conformer, config, treat_unconverged_as_failure=True, suppress_errors=True, n_cores=1, scr=DEFAULT_SCR, keep_files=False)[source]

Run geometry optimization on a single conformer.

Optimizes the 3D coordinates of a conformer using the specified computational chemistry backend. The conformer’s parent molecule must have proper connectivity information (bonds, charges, etc.).

Parameters:
  • conformer (Conformer) – RDKit conformer to optimize. Must have a parent molecule with proper connectivity information.

  • config (list[XtbOptions | JobexOptions | XtbTurbomoleOptions]) – Optimization configuration(s) to try in order (each selects a backend and its options).

  • n_cores (int) – Number of CPU cores to use for the optimization. Defaults to 1.

  • scr (Path) – Path to the scratch directory for temporary files. Defaults to DEFAULT_SCR.

  • treat_unconverged_as_failure (bool) – If True, treats unconverged optimizations as failures and attempts fallbacks. If False, returns the results of the primary optimization even if unconverged. Defaults to True.

  • suppress_errors (bool) – If True, returns (None, None) on failure instead of raising an exception. If False, raises RuntimeError on optimization failure. Defaults to True.

  • keep_files (bool) – If True, keeps intermediate files generated during optimization. Defaults to False.

Returns:

The conformer with optimized coordinates, or None if

optimization failed and suppress_errors=True.

Return type:

tuple[Conformer | None, dict[str, Property] | None]

Raises:
  • RuntimeError – If optimization fails and suppress_errors=False.

  • KeyError – If an invalid driver is specified.

Examples

>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMolecule(mol)
>>> conformer = mol.GetConformer()
>>> opt_conf = optimize_conformer(conformer, config=[XtbTurbomoleOptions()], n_cores=4)
qm_atlas.tasks.optimize.optimize_mol(mol, config, treat_unconverged_as_failure=True, n_cores=1, scr=DEFAULT_SCR, keep_files=False, show_progress=True)[source]

Run geometry optimization on all conformers of a molecule in parallel.

Optimizes all conformers in a molecule using the specified driver. Conformers are processed in parallel to utilize multiple CPU cores efficiently.

Parameters:
  • mol (Mol) – RDKit molecule with one or more conformers to optimize.

  • config (list[XtbOptions | JobexOptions | XtbTurbomoleOptions]) – Optimization configuration(s) to try in order (each selects a backend and its options; later entries act as fallbacks).

  • treat_unconverged_as_failure (bool) – If True, treats unconverged optimizations as failures and attempts the next fallback configuration. Defaults to True.

  • n_cores (int) – Number of CPU cores to use for parallel processing. Defaults to 1 (sequential).

  • scr (Path) – Path to the scratch directory for temporary files. Defaults to DEFAULT_SCR.

  • keep_files (bool) – If True, keeps intermediate files generated during optimization. Defaults to False.

  • show_progress (bool) – If True, displays a progress bar. Defaults to True.

Returns:

New molecule with optimized conformers. Failed conformers

are either removed or kept with original coordinates, depending on keep_failures setting.

Return type:

tuple[Mol, list[dict[str, Property]]]

Raises:

ValueError – If an invalid driver is specified.

Examples

>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMultipleConfs(mol, 5)
>>> opt_mol = optimize_mol(mol, config=[XtbTurbomoleOptions()], n_cores=4)
qm_atlas.tasks.optimize.optimize_mols(molecules, config, n_cores=1, treat_unconverged_as_failure=True, scr=DEFAULT_SCR, keep_files=False, show_progress=True)[source]

Run geometry optimization on all conformers of multiple molecules in parallel.

Optimizes all conformers in a list of molecules using the specified driver. All conformers are processed in parallel, regardless of which molecule they belong to. This is most efficient when optimizing many conformers (>10).

Parameters:
  • molecules (list[Mol]) – List of RDKit molecules with conformers to optimize. All molecules should have the same structure (connectivity, charges, etc.) for optimal performance.

  • config (list[XtbOptions | JobexOptions | XtbTurbomoleOptions]) – Optimization configuration(s) to try in order (each selects a backend and its options; later entries act as fallbacks).

  • n_cores (int) – Number of CPU cores to use for parallel processing. The actual number of processes spawned will be min(n_cores, total_num_conformers). Defaults to 1 (sequential processing).

  • treat_unconverged_as_failure (bool) – If True, treats unconverged optimizations as failures and attempts the next fallback configuration. Defaults to True.

  • scr (Path) – Path to the scratch directory for temporary files. Defaults to DEFAULT_SCR.

  • keep_files (bool) – If True, keeps intermediate files generated during optimization. Defaults to False.

  • show_progress (bool) – If True, displays a progress bar. Defaults to True.

Return type:

tuple[list[Mol], list[list[dict[str, Property]]]]

Returns:

List of molecules with optimized conformers. The output list has the same length as the input list, with conformers reorganized by molecule.

Raises:
  • ValueError – if molecules have no conformers.

  • KeyError – If an invalid driver is specified.

Examples

>>> mols = [Chem.MolFromSmiles("CCO"), Chem.MolFromSmiles("CC")]
>>> for mol in mols:
...     mol = Chem.AddHs(mol)
...     AllChem.EmbedMultipleConfs(mol, 3)
>>> opt_mols = optimize_mols(mols, config=[XtbTurbomoleOptions()], n_cores=8)
qm_atlas.tasks.optimize.update_mol(mol, new_coordinates_lst)[source]

Update a molecule with new optimized coordinates.

Creates a new molecule with updated conformers, replacing the original ones. Failed optimizations (None coordinates) are either removed or kept with original coordinates based on the keep_failures flag.

Parameters:
  • mol (Mol) – RDKit molecule with conformers to update.

  • new_coordinates_lst (list[ndarray | None]) – List of coordinate arrays (one per original conformer). Each element is either a (n_atoms, 3) numpy array or None if optimization failed. The list length must match mol.GetNumConformers().

Return type:

tuple[Mol, list[int]]

Returns:

New RDKit Molecule with updated conformers. The output molecule is a copy of the input, with all conformers replaced.

Raises:

ValueError – If the number of coordinate arrays doesn’t match the number of conformers, or if coordinate shapes are invalid.

Examples

>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMultipleConfs(mol, 2)
>>> coords1 = np.array([[0,0,0], [1,1,1], ...])  # 8 atoms
>>> coords2 = None  # Failed optimization
>>> opt_mol = update_mol(mol, [coords1, coords2])
qm_atlas.tasks.optimize.adapt_positions(conformer, coordinates, rmsd_warning_threshold=3.0, contact_scale=conformer_geometry.NONBONDED_CONTACT_SCALE)[source]

Create a conformer with updated atom positions.

Takes a template conformer and new coordinate values, creating a new conformer with updated atom positions. Checks that the new coordinates are still consistent with the bond table of the molecule, i.e. that all declared bonds are intact and that no new bond was formed (see check_geometry_consistency()).

Parameters:
  • conformer (Conformer) – Template RDKit conformer to use as basis. Its parent molecule must have the same number of atoms as the coordinates array.

  • coordinates (ndarray | None) – Array of shape (n_atoms, 3) with new atomic coordinates in Angstroms. If None, raises RuntimeError.

  • rmsd_warning_threshold (float) – If the RMSD between old and new coordinates exceeds this value (in Angstroms), logs a warning. This can indicate unphysical geometry changes. Defaults to 3.0.

  • contact_scale (float | None) – Scale factor applied to the sum of the covalent radii below which two atoms that are not bonded are considered to have formed a bond. Pass None to skip that test. Defaults to NONBONDED_CONTACT_SCALE.

Return type:

Conformer

Returns:

New RDKit Conformer with updated atom positions.

Raises:
  • RuntimeError – If coordinates is None or if the new coordinates are not consistent with the bond table of the molecule.

  • ValueError – If the number of coordinates doesn’t match the number of atoms.

Examples

>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMolecule(mol)
>>> conf = mol.GetConformer()
>>> new_coords = np.random.rand(mol.GetNumAtoms(), 3)  # Optimized coords
>>> new_conf = adapt_positions(conf, new_coords)
qm_atlas.tasks.optimize.check_displacement(conformer, new_conformer, rmsd_warning_threshold=3.0)[source]

Check and log the RMSD displacement between two conformers.

Calculates the root-mean-square displacement (RMSD) between the original and optimized geometries. Logs informational or warning messages if the displacement is unusually large, which can indicate unphysical geometry changes.

Parameters:
  • conformer (Conformer) – Original RDKit conformer (before optimization).

  • new_conformer (Conformer) – Optimized RDKit conformer (after optimization).

  • rmsd_warning_threshold (float) – Displacement threshold (in Angstroms) above which a warning is logged. Values > 3.0 Å may indicate the optimization converged to a different tautomer or isomer. Defaults to 3.0.

Return type:

None

Returns:

None. Results are logged using the logging module.

Notes

Uses RDKit’s alignment algorithm to calculate best-fit RMSD, which accounts for rigid-body transformations (translation/rotation).

Examples

>>> mol = Chem.MolFromSmiles("CCO")
>>> mol = Chem.AddHs(mol)
>>> AllChem.EmbedMolecule(mol)
>>> conf = mol.GetConformer()
>>> # ... optimize ...
>>> new_conf = Chem.Conformer(conf)
>>> check_displacement(conf, new_conf)  # Logs RMSD
class qm_atlas.tasks.cosmo_properties.CosmoConfig(**data)[source]
Parameters:
  • level (Literal['bp-tzvpd', 'bp-tzvp', 'dmol3-pbe'])

  • temperature_Celsius (float)

  • solvents_dirs (list[Path])

  • use_config_cosmo_dir (bool)

  • property_prefix (str | None)

  • extra_data (Any)

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

level: Literal['bp-tzvpd', 'bp-tzvp', 'dmol3-pbe']
temperature_Celsius: float
solvents_dirs: list[Path]
use_config_cosmo_dir: bool
property_prefix: str | None
get_property_prefix()[source]

Get the property prefix. Must be implemented by subclasses.

Return type:

str

get_property_names()[source]
Return type:

dict[str, str]

get_property_types()[source]
Return type:

dict[str, type]

class qm_atlas.tasks.cosmo_properties.CosmoLogPConfig(**data)[source]
Parameters:
  • level (Literal['bp-tzvpd', 'bp-tzvp', 'dmol3-pbe'])

  • temperature_Celsius (float)

  • solvents_dirs (list[Path])

  • use_config_cosmo_dir (bool)

  • property_prefix (str | None)

  • backend (Literal['cosmo_logp'])

  • is_woctanol (bool)

  • solvent_names (list[str])

  • eq_phases (bool)

  • extra_data (Any)

backend: Literal['cosmo_logp']
is_woctanol: bool
solvent_names: list[str]
eq_phases: bool
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]
Return type:

dict[str, str]

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

level: Literal['bp-tzvpd', 'bp-tzvp', 'bp-tzvp', 'dmol3-pbe']
temperature_Celsius: float
solvents_dirs: list[Path]
use_config_cosmo_dir: bool
class qm_atlas.tasks.cosmo_properties.CosmoDeltaGConfig(**data)[source]
Parameters:
  • level (Literal['bp-tzvpd', 'bp-tzvp', 'dmol3-pbe'])

  • temperature_Celsius (float)

  • solvents_dirs (list[Path])

  • use_config_cosmo_dir (bool)

  • property_prefix (str | None)

  • backend (Literal['cosmo_delta_g'])

  • solvent_name (str)

  • extra_data (Any)

backend: Literal['cosmo_delta_g']
solvent_name: str
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]
Return type:

dict[str, str]

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

level: Literal['bp-tzvpd', 'bp-tzvp', 'bp-tzvp', 'dmol3-pbe']
temperature_Celsius: float
solvents_dirs: list[Path]
use_config_cosmo_dir: bool
class qm_atlas.tasks.cosmo_properties.CosmoDescriptorsConfig(**data)[source]
Parameters:
  • level (Literal['bp-tzvpd', 'bp-tzvp', 'dmol3-pbe'])

  • temperature_Celsius (float)

  • solvents_dirs (list[Path])

  • use_config_cosmo_dir (bool)

  • property_prefix (str | None)

  • backend (Literal['cosmo_descriptors'])

  • solvent_name (str)

  • extra_data (Any)

backend: Literal['cosmo_descriptors']
solvent_name: str
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]
Return type:

dict[str, str]

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

level: Literal['bp-tzvpd', 'bp-tzvp', 'bp-tzvp', 'dmol3-pbe']
temperature_Celsius: float
solvents_dirs: list[Path]
use_config_cosmo_dir: bool
class qm_atlas.tasks.cosmo_properties.CosmoPsaConfig(**data)[source]
Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

backend: Literal['cosmo_psa']
smoothen: bool
on_charges: bool
lower_limit: float
upper_limit: float
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]
Return type:

dict[str, str]

get_property_types()[source]
Return type:

dict[str, type]

class qm_atlas.tasks.cosmo_properties.CosmoPermConfig(**data)[source]
Parameters:
  • level (Literal['bp-tzvpd', 'bp-tzvp', 'dmol3-pbe'])

  • temperature_Celsius (float)

  • solvents_dirs (list[Path])

  • use_config_cosmo_dir (bool)

  • property_prefix (str | None)

  • backend (Literal['cosmo_perm'])

  • micelle_file (Path | None)

  • micelle_name (str)

  • pH (float)

  • extra_data (Any)

backend: Literal['cosmo_perm']
micelle_file: Path | None
micelle_name: str
pH: float
property_prefix: str | None
get_property_prefix()[source]

Determine property prefix.

Return type:

str

get_property_names()[source]
Return type:

dict[str, str]

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

qm_atlas.tasks.cosmo_properties.calculate_cosmo_psa(compound_conformers, config, scr=DEFAULT_SCR, keep_files=False, n_cores=1)[source]

Thin wrapper around extract_psa_from_cosmo_file() that unpacks config and renames the output property.

Return type:

list[dict[str, ScalarProperty]]

Parameters:
qm_atlas.tasks.cosmo_properties.calculate_logp(compound_conformers, config, scr=DEFAULT_SCR, keep_files=False, n_cores=1)[source]

Thin wrapper around calculate_logp() that unpacks config and renames the output property.

Return type:

dict[str, ScalarProperty]

Parameters:
qm_atlas.tasks.cosmo_properties.calculate_delta_g(compound_conformers, config, scr=DEFAULT_SCR, keep_files=False, n_cores=1)[source]

Thin wrapper around calculate_delta_g() that unpacks config and renames the output property.

Return type:

dict[str, ScalarProperty]

Parameters:
qm_atlas.tasks.cosmo_properties.calculate_descriptors(compound_conformers, config, scr=DEFAULT_SCR, keep_files=False, n_cores=1)[source]

Thin wrapper around calculate_descriptors() that unpacks config and renames the output properties.

Return type:

list[dict[str, ScalarProperty]]

Parameters:
qm_atlas.tasks.cosmo_properties.calculate_perm(compound_conformers, config, scr=DEFAULT_SCR, keep_files=False, n_cores=1)[source]

Thin wrapper around calculate_cosmoperm() that unpacks config and renames the output property.

Return type:

dict[str, ScalarProperty]

Parameters:
qm_atlas.tasks.cosmo_properties.run_cosmo_calculation(conformer_cosmo_files, config, scr=DEFAULT_SCR, keep_files=False, n_cores=1)[source]

Dispatch to the COSMO calculator selected by config.backend (see CALCULATOR_REGISTRY) and return its named properties.

Return type:

dict[str, ScalarProperty] | list[dict[str, ScalarProperty]]

Parameters:

Tautomer generation and selection tasks.

Covers three pipeline steps:

  1. generate_tautomers() — run unicon, add the original molecule, deduplicate.

  2. generate_tautomer_conformers() — run fast conformer generation for each tautomer.

  3. select_stable_tautomers() — filter by XTB energy threshold, strip conformers, remove explicit hydrogens.

qm_atlas.tasks.tautomer_generation.generate_tautomers(molobj, scr)[source]

Generate tautomers for a molecule using unicon.

Runs unicon, appends the original molecule, then deduplicates by canonical SMILES so the returned list contains only structurally distinct tautomers.

Parameters:
  • molobj (Mol) – Input molecule (should already be neutralized).

  • scr (Path) – Scratch directory for unicon intermediate files.

Return type:

list[Mol]

Returns:

List of unique tautomer Mol objects (always includes the original).

Raises:

ValueError – If the deduplicated tautomer list is empty.

qm_atlas.tasks.tautomer_generation.generate_tautomer_conformers(tautomers, options=TAUTOMER_CONFORMER_OPTIONS, scr=DEFAULT_SCR, n_cores=1, show_progress=True)[source]

Generate fast conformers for each tautomer.

Calls generate_fast_conformers() on every tautomer in the list.

Parameters:
  • tautomers (list[Mol]) – List of tautomer Mol objects (no conformers required).

  • options (ConformerGenerationOptions) – Conformer generation options. Defaults to TAUTOMER_CONFORMER_OPTIONS (Omega → RDKit fallback, max 5 confs).

  • scr (Path) – Scratch directory for xTB calculations.

  • n_cores (int) – Number of CPU cores.

  • show_progress (bool) – Show tqdm progress bar during optimization.

Return type:

list[Mol]

Returns:

List of tautomers with conformers embedded (same order as input).

Raises:

ValueError – If any tautomer produces zero conformers.

qm_atlas.tasks.tautomer_generation.select_stable_tautomers(tautomers, xtb_sp_config=XTB_SP_CONFIG, threshold_kcal_mol=7.0, n_cores=1, scr=DEFAULT_SCR, show_progress=True)[source]

Filter tautomers by XTB energy, keeping those within the energy threshold.

Runs XTB single-point calculations on the conformers of each tautomer, takes the minimum energy per tautomer, converts to kcal/mol relative to the lowest tautomer, and keeps those below threshold_kcal_mol.

After filtering, conformers are stripped and explicit hydrogens removed so the returned molecules are clean graph-level objects ready for the next step.

Parameters:
  • tautomers (list[Mol]) – Tautomers with conformers (output of generate_tautomer_conformers()).

  • xtb_sp_config (XtbSinglePointOptions) – XTB single-point options for tautomer screening.

  • threshold_kcal_mol (float) – Energy window above the lowest tautomer (kcal/mol).

  • n_cores (int) – Number of CPU cores.

  • scr (Path) – Scratch directory for xTB.

  • show_progress (bool) – Show tqdm progress bar.

Return type:

list[Mol]

Returns:

Filtered list of tautomers as graph-level Mol objects (no conformers, no explicit Hs).

Protonation-state generation task.

This module exposes a pluggable backend registry for generating protonation states. Three backends are currently implemented:

All backends return a ProtonationResult containing ProtomerEntry items (per-protomer mol + optional abundance) and ProtonationPkaTransition items (per-transition pKa / atom index). Backends that do not provide a piece of information leave the corresponding field as None (or the transition list empty).

class qm_atlas.tasks.protonation.ProtomerEntry(mol, abundance=None)[source]

A single protomer produced by a protonation backend.

Parameters:
mol: Mol
abundance: float | None = None
class qm_atlas.tasks.protonation.ProtonationPkaTransition(parent_smiles, child_smiles, pka_value, pka_type, atom_index=None)[source]

A pKa transition reported by a protonation backend.

Protomers are referred to by canonical isomeric SMILES so callers can map them onto registered state names regardless of mol identity.

Parameters:
  • parent_smiles (str)

  • child_smiles (str)

  • pka_value (float)

  • pka_type (str)

  • atom_index (int | None)

parent_smiles: str
child_smiles: str
pka_value: float
pka_type: str
atom_index: int | None = None
class qm_atlas.tasks.protonation.ProtonationResult(protomers=<factory>, transitions=<factory>)[source]

Unified return value of run_protonation().

Parameters:
protomers: list[ProtomerEntry]
transitions: list[ProtonationPkaTransition]
class qm_atlas.tasks.protonation.ProtonationOptions(**data)[source]

Base class for protonation backends.

Each concrete backend declares a unique backend literal that acts as the discriminator for (de)serialization within ProtonationConfig.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class qm_atlas.tasks.protonation.MokaBlabberConfig(**data)[source]

Generate protonation states with MoKa’s blabber_sd tool.

Parameters:
  • backend (Literal['moka_blabber'])

  • ph (str)

  • abundance_threshold (float | None)

  • remove_zero_charged (bool)

backend: Literal['moka_blabber']
ph: str
abundance_threshold: float | None
remove_zero_charged: bool
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class qm_atlas.tasks.protonation.MokaIonicSpeciesConfig(**data)[source]

Enumerate ionic species using MoKa pKa prediction.

Uses qm_atlas.wrappers.moka.process.generate_ionic_species().

Parameters:
  • lower_ph_threshold (float | None)

  • upper_ph_threshold (float | None)

  • backend (Literal['moka_ionic_species'])

backend: Literal['moka_ionic_species']
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

lower_ph_threshold: float | None
upper_ph_threshold: float | None
class qm_atlas.tasks.protonation.MokaSingleChargeConfig(**data)[source]

Enumerate singly-charged ions using MoKa pKa prediction.

Uses qm_atlas.wrappers.moka.process.generate_single_charge_ions().

Parameters:
  • lower_ph_threshold (float | None)

  • upper_ph_threshold (float | None)

  • backend (Literal['moka_single_charge'])

backend: Literal['moka_single_charge']
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

lower_ph_threshold: float | None
upper_ph_threshold: float | None
qm_atlas.tasks.protonation.deserialize_protonation_config(data)[source]

Deserialize a protonation config from a dict using its backend field.

Return type:

ProtonationOptions

Parameters:

data (Any)

qm_atlas.tasks.protonation.run_protonation(mol, config, scr, keep_files=False)[source]

Run a protonation backend on mol and return the unified result.

Parameters:
  • mol (Mol) – Parent molecule.

  • config (ProtonationOptions) – Backend-specific configuration (a concrete ProtonationOptions subclass).

  • scr (Path) – Scratch directory for backend intermediates.

  • keep_files (bool) – Whether to keep the backend intermediate files. Used for debugging. Defaults to False.

Return type:

ProtonationResult

Returns:

ProtonationResult with the protomers produced by the backend and, where supported, the pKa transitions linking them.

Boltzmann weighting and conformer-property averaging utilities.

These helpers operate on already-calculated per-conformer scalar properties. They are used by the calculate_boltzmann_weights and aggregate_conformer_properties command-line interfaces.

qm_atlas.tasks.boltzmann.energy_to_j_per_mol(energies, unit)[source]

Convert a sequence of energies to J/mol.

Parameters:
  • energies (Sequence[float]) – Energy values in unit.

  • unit (str) – The energy unit (case-insensitive). One of the keys of ENERGY_UNIT_TO_J_PER_MOL.

Returns:

The energies converted to J/mol.

Return type:

ndarray

Raises:

ValueError – If unit is not a recognised energy unit.

qm_atlas.tasks.boltzmann.compute_boltzmann_weights(energies, unit, temperature)[source]

Compute normalised Boltzmann weights for a set of conformer energies.

Weights are computed relative to the lowest-energy conformer to avoid numerical overflow, then normalised so they sum to one.

Parameters:
Returns:

Normalised Boltzmann weights, one per input energy.

Return type:

list[float]

Raises:

ValueError – If energies is empty or temperature is not positive.

qm_atlas.tasks.boltzmann.compute_relative_energies(energies, from_unit, to_unit)[source]

Compute per-conformer energy differences to the lowest-energy conformer.

Parameters:
Returns:

Energy differences to the lowest-energy conformer, expressed in to_unit. The lowest-energy conformer has a value of 0.

Return type:

list[float]

Raises:

ValueError – If energies is empty or a unit is not recognised.

qm_atlas.tasks.boltzmann.plain_average(values, axis=None)[source]

Return the arithmetic mean of values.

Parameters:
  • values (Sequence[float] | ndarray) – Per-conformer property values. May be multi-dimensional, in which case axis selects the axis to average over.

  • axis (int | None) – Axis to average over. None (default) averages the flattened input and returns a float.

Returns:

The unweighted average; a float when the result is scalar, otherwise an array.

Return type:

float | ndarray

Raises:

ValueError – If values is empty.

qm_atlas.tasks.boltzmann.weighted_average(values, weights, axis=None)[source]

Return the weighted mean of values using weights.

Weights are normalised internally, so they need not sum to one.

Parameters:
  • values (Sequence[float] | ndarray) – Per-conformer property values. May be multi-dimensional, in which case axis selects the axis to average over.

  • weights (Sequence[float] | ndarray) – Per-conformer weights (e.g. Boltzmann weights), one per entry along axis.

  • axis (int | None) – Axis to average over. None (default) averages the flattened input and returns a float.

Returns:

The weighted average; a float when the result is scalar, otherwise an array.

Return type:

float | ndarray

Raises:

ValueError – If the inputs are empty, differ in length, or the weights sum to zero.

Handle writing of calculated molecular properties.

class qm_atlas.tasks.common.Property(*args, **kwargs)[source]

Abstract base class for a calculated molecular property.

Subclasses must implement: - get_property_value: Return the calculated property value - set_property_on_mol: Set the calculated property value on a molecule - from_mol: Read the calculated property value back from a molecule

get_property_value()[source]

Get the calculated property value.

Return type:

Any

set_property_on_mol(mol, property_name)[source]
Set the calculated property value on a molecule.

The molecule is modified in place.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

Raises:

NotImplementedError – If the method is not implemented in a subclass

classmethod from_mol(mol, property_name)[source]

Read the calculated property value back from a molecule.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the molecule

Returns:

A property instance holding the value read from the molecule.

Return type:

Property

Raises:
class qm_atlas.tasks.common.ScalarProperty(calculated_property)[source]

Class for scalar calculated molecular properties.

Parameters:

calculated_property (float)

get_property_value()[source]

Get the scalar calculated property value.

Return type:

float

set_property_on_mol(mol, property_name)[source]

Set the scalar calculated property value on a molecule as a property.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

classmethod from_mol(mol, property_name)[source]

Read a scalar property value from a molecule.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the molecule

Returns:

The scalar value stored on the molecule.

Return type:

ScalarProperty

Raises:

KeyError – If the property is not present on the molecule.

class qm_atlas.tasks.common.TensorProperty(calculated_property)[source]

Class for tensor-valued calculated molecular properties. These could be vectors, matrices, or higher-dimensional tensors.

Parameters:

calculated_property (ndarray | list)

get_property_value()[source]

Get the tensor-valued calculated property value.

Return type:

ndarray

set_property_on_mol(mol, property_name)[source]

Set the tensor calculated property value on a molecule as a property.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

classmethod from_mol(mol, property_name)[source]

Read a tensor property value from a molecule.

The value is expected to have been stored as a JSON-serialized list.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the molecule

Returns:

The tensor value stored on the molecule.

Return type:

TensorProperty

Raises:

KeyError – If the property is not present on the molecule.

class qm_atlas.tasks.common.AtomBasedProperty(calculated_property)[source]

Class for atom-based calculated molecular properties.

Parameters:

calculated_property (list[float] | dict[int, float])

get_property_value()[source]

Get the atom-based calculated property value.

Return type:

list[float] | dict[int, float]

set_property_on_mol(mol, property_name)[source]

Set the atom-based calculated property value on a molecule as a property.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

classmethod from_mol(mol, property_name)[source]

Read an atom-based property value from a molecule.

Every atom must carry the property; the values are returned as a list ordered by atom index.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the atoms

Returns:

The per-atom values ordered by atom index.

Return type:

AtomBasedProperty

Raises:

KeyError – If any atom is missing the property.

class qm_atlas.tasks.common.BondBasedProperty(calculated_property)[source]

Class for bond-based calculated molecular properties.

Parameters:

calculated_property (dict[tuple[int, int], float])

get_property_value()[source]

Get the bond-based calculated property value.

Return type:

dict[tuple[int, int], float]

set_property_on_mol(mol, property_name)[source]

Set the bond-based calculated property value on a molecule as a property.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

classmethod from_mol(mol, property_name)[source]

Read a bond-based property value from a molecule.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the molecule

Returns:

The per-bond values keyed by atom-index pairs.

Return type:

BondBasedProperty

Raises:

KeyError – If the property is not present on the molecule.

class qm_atlas.tasks.common.StringProperty(calculated_property)[source]

Class for string-valued calculated molecular properties.

Parameters:

calculated_property (str)

get_property_value()[source]

Get the string-valued calculated property value.

Return type:

str

set_property_on_mol(mol, property_name)[source]

Set the string-valued calculated property value on a molecule as a property.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

classmethod from_mol(mol, property_name)[source]

Read a string property value from a molecule.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the molecule

Returns:

The string value stored on the molecule.

Return type:

StringProperty

Raises:

KeyError – If the property is not present on the molecule.

class qm_atlas.tasks.common.BoolProperty(calculated_property)[source]

Class for boolean calculated molecular properties.

Parameters:

calculated_property (bool)

get_property_value()[source]

Get the boolean calculated property value.

Return type:

bool

set_property_on_mol(mol, property_name)[source]

Set the boolean calculated property value on a molecule as a property.

Parameters:
  • mol (Mol) – RDKit molecule to set the property on

  • property_name (str) – Name to use for the property on the molecule

classmethod from_mol(mol, property_name)[source]

Read a boolean property value from a molecule.

Parameters:
  • mol (Mol) – RDKit molecule to read the property from

  • property_name (str) – Name of the property on the molecule

Returns:

The boolean value stored on the molecule.

Return type:

BoolProperty

Raises:

KeyError – If the property is not present on the molecule.