pympfit.mbis

pympfit.mbis

class pympfit.mbis._mbis.MBISGenerator[source]

Bases: ABC

Base class for generating electrostatic potential of a molecule on a grid.

classmethod generate(molecule: Molecule, conformer: Quantity, settings: MBISSettings, directory: str = None, minimize: bool = False, compute_mp: bool = True, n_threads: int = 1, memory: Quantity = <Quantity(500, 'mebibyte')>) tuple[Quantity, Quantity][source]

Generate the MBIS multipole moments for a molecule.

Parameters:
  • molecule – The molecule to generate the MBIS data for.

  • conformer – The molecule conformer to analyze.

  • settings – The settings to use when generating the MBIS data.

  • directory – The directory to run the calculation in. If none is specified, a temporary directory will be created and used.

  • minimize – Whether to energy minimize the conformer prior to computation using the same level of theory that will be used for MBIS.

  • compute_mp – Whether to compute the multipole moments.

  • n_threads – Number of threads to use for the calculation.

  • memory – The memory to make available for computation. Default is 500 MiB, as is the default in Psi4 (see psicode.org/psi4manual/master/psithoninput.html#memory-specification).

Returns:

  • The final conformer [A] which will be identical to conformer if

  • minimize=False, and the computed multipole moments.

class pympfit.mbis._mbis.MBISSettings(*, basis: str = 'def2-SVP', method: str = 'pbe0', limit: int = 3, e_convergence: int = 8, d_convergence: int = 8, dft_radial_points: int = 99, dft_spherical_points: int = 590, max_radial_moment: int = 4, max_moment: int = 3, mbis_d_convergence: int = 9, mbis_radial_points: int = 99, mbis_spherical_points: int = 590, guess: str = 'sad', multipole_units: str = 'AU', multipole_format: Literal['spherical', 'cartesian'] = 'spherical', mpfit_inner_radius: float = 6.78, mpfit_outer_radius: float = 12.45, mpfit_atom_radius: float = 3.0)[source]

Bases: BaseModel

Settings for MBIS calculation and related MPFIT operations.

basis: str
d_convergence: int
dft_radial_points: int
dft_spherical_points: int
e_convergence: int
guess: str
limit: int
max_moment: int
max_radial_moment: int
mbis_d_convergence: int
mbis_radial_points: int
mbis_spherical_points: int
method: str
model_config = {}

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

mpfit_atom_radius: float
mpfit_inner_radius: float
mpfit_outer_radius: float
multipole_format: Literal['spherical', 'cartesian']
multipole_units: str
class pympfit.mbis._mbis.MultipoleFormat(*values)[source]

Bases: str, Enum

Enumeration for multipole representation formats.

CARTESIAN = 'cartesian'
SPHERICAL = 'spherical'
pympfit.mbis._mbis.extract_mbis_charges(mbis_record: MoleculeMBISRecord) LibraryChargeParameter[source]

Return the MBIS charges (Q00 column) as a LibraryChargeParameter.

pympfit.mbis.psi4

Compute MBIS multipole data using Psi4.

class pympfit.mbis.psi4.Psi4MBISGenerator[source]

Bases: MBISGenerator

Compute the multipole moments of a molecule using Psi4.

pympfit.mbis.multipole_transform

Transform Cartesian multipoles to spherical harmonics representation.

This module provides functions to convert MBIS Cartesian multipoles to spherical harmonic representation for compatibility with GDMA-style output.

MBIS produces Cartesian multipoles with the following shapes: - q (charge): (N, 1) - mu (dipole): (N, 3) - theta (quadrupole): (N, 3, 3) - omega (octupole): (N, 3, 3, 3)

The spherical harmonic representation uses (2l+1) components per rank: - l=0 (monopole): 1 component -> Q00 - l=1 (dipole): 3 components -> Q10, Q11c, Q11s - l=2 (quadrupole): 5 components -> Q20, Q21c, Q21s, Q22c, Q22s - l=3 (octupole): 7 components -> Q30, Q31c, Q31s, Q32c, Q32s, Q33c, Q33s

References

The transformations are based on the standard relationships between Cartesian and spherical tensor components. See Stone, “The Theory of Intermolecular Forces”, 2nd ed., Oxford University Press, 2013.

pympfit.mbis.multipole_transform.cartesian_multipoles_to_flat(charges: ndarray[tuple[Any, ...], dtype[float64]], dipoles: ndarray[tuple[Any, ...], dtype[float64]] | None = None, quadrupoles: ndarray[tuple[Any, ...], dtype[float64]] | None = None, octupoles: ndarray[tuple[Any, ...], dtype[float64]] | None = None, max_moment: int = 4) ndarray[tuple[Any, ...], dtype[float64]][source]

Flatten MBIS Cartesian multipoles to a 2D array.

This keeps the Cartesian representation but flattens tensors. All unique components of symmetric tensors are stored. Quadrupoles are made traceless before storage.

Parameters:
  • charges – MBIS charges of shape (N,) or (N, 1).

  • dipoles – MBIS dipoles of shape (N, 3), or None.

  • quadrupoles – MBIS quadrupoles of shape (N, 3, 3), or None. Will be made traceless.

  • octupoles – MBIS octupoles of shape (N, 3, 3, 3), or None.

  • max_moment – Maximum multipole moment to include (1-4). 1=charges, 2=+dipoles, 3=+quadrupoles, 4=+octupoles.

Returns:

Flattened Cartesian multipole array of shape (N, n_components). Components for each rank are stored in the following order: - l=0: q (1 component, index 0) - l=1: x, y, z (3 components, indices 1-3) - l=2: xx, xy, xz, yy, yz, zz (6 components, indices 4-9, traceless) - l=3: xxx, xxy, xxz, xyy, xyz, xzz, yyy, yyz, yzz, zzz

(10 components, indices 10-19)

Return type:

NDArray[np.float64]

Notes

The total number of Cartesian components is: - max_moment=1: 1 (charges only) - max_moment=2: 1 + 3 = 4 - max_moment=3: 1 + 3 + 6 = 10 - max_moment=4: 1 + 3 + 6 + 10 = 20

Quadrupoles are automatically made traceless (Tr(Q) = 0) before storage, as this is the physically meaningful form for multipole expansions.

pympfit.mbis.multipole_transform.cartesian_to_spherical_dipole(mu: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert Cartesian dipole to spherical harmonics.

Parameters:

mu – Cartesian dipole array of shape (N, 3) where columns are [x, y, z].

Returns:

Spherical harmonic dipole array of shape (N, 3). Order: [Q10, Q11c, Q11s] = [z, x, y]

Return type:

NDArray[np.float64]

pympfit.mbis.multipole_transform.cartesian_to_spherical_multipoles(charges: ndarray[tuple[Any, ...], dtype[float64]], dipoles: ndarray[tuple[Any, ...], dtype[float64]] | None = None, quadrupoles: ndarray[tuple[Any, ...], dtype[float64]] | None = None, octupoles: ndarray[tuple[Any, ...], dtype[float64]] | None = None, max_moment: int = 4) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert MBIS Cartesian multipoles to spherical harmonic representation.

Parameters:
  • charges – MBIS charges of shape (N,) or (N, 1).

  • dipoles – MBIS dipoles of shape (N, 3), or None.

  • quadrupoles – MBIS quadrupoles of shape (N, 3, 3), or None.

  • octupoles – MBIS octupoles of shape (N, 3, 3, 3), or None.

  • max_moment – Maximum multipole moment to include (1-4). 1=charges, 2=+dipoles, 3=+quadrupoles, 4=+octupoles.

Returns:

Combined spherical harmonic multipole array of shape (N, n_components) where n_components = max_moment^2. Components are ordered as: - l=0: Q00 (index 0) - l=1: Q10, Q11c, Q11s (indices 1-3) - l=2: Q20, Q21c, Q21s, Q22c, Q22s (indices 4-8) - l=3: Q30, Q31c, Q31s, Q32c, Q32s, Q33c, Q33s (indices 9-15)

Return type:

NDArray[np.float64]

pympfit.mbis.multipole_transform.cartesian_to_spherical_octupole(omega: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert Cartesian octupole to spherical harmonics.

The transformation inverts the relationships:

Omega_xxx = sqrt(5/8) Q33c - sqrt(3/8) Q31c Omega_xxy = sqrt(5/8) Q33s - sqrt(1/24) Q31s Omega_xyy = -sqrt(5/8) Q33c - sqrt(1/24) Q31c Omega_yyy = -sqrt(5/8) Q33s - sqrt(3/8) Q31s Omega_xxz = sqrt(5/12) Q32c - 1/2 Q30 Omega_xyz = sqrt(5/12) Q32s Omega_yyz = -sqrt(5/12) Q32c - 1/2 Q30 Omega_xzz = sqrt(2/3) Q31c Omega_yzz = sqrt(2/3) Q31s Omega_zzz = Q30

Parameters:

omega – Cartesian octupole tensor of shape (N, 3, 3, 3).

Returns:

Spherical harmonic octupole array of shape (N, 7). Order: [Q30, Q31c, Q31s, Q32c, Q32s, Q33c, Q33s]

Return type:

NDArray[np.float64]

pympfit.mbis.multipole_transform.cartesian_to_spherical_quadrupole(theta: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert Cartesian quadrupole to spherical harmonics.

The transformation inverts:

Theta_xx = -1/2 Q20 + 1/2 sqrt(3) Q22c Theta_yy = -1/2 Q20 - 1/2 sqrt(3) Q22c Theta_zz = Q20 Theta_xy = 1/(2*sqrt(3)) Q22s Theta_xz = 1/(2*sqrt(3)) Q21c Theta_yz = 1/(2*sqrt(3)) Q21s

Parameters:

theta – Cartesian quadrupole tensor of shape (N, 3, 3).

Returns:

Spherical harmonic quadrupole array of shape (N, 5). Order: [Q20, Q21c, Q21s, Q22c, Q22s]

Return type:

NDArray[np.float64]

pympfit.mbis.multipole_transform.flat_to_cartesian_multipoles(multipoles: ndarray[tuple[Any, ...], dtype[float64]], max_moment: int = 4) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]] | None, ndarray[tuple[Any, ...], dtype[float64]] | None, ndarray[tuple[Any, ...], dtype[float64]] | None][source]

Unflatten Cartesian multipoles from a 2D array back to tensor form.

This is the inverse of cartesian_multipoles_to_flat.

Parameters:
  • multipoles – Flattened Cartesian multipole array of shape (N, n_components). Components for each rank are stored in the following order: - l=0: q (1 component, index 0) - l=1: x, y, z (3 components, indices 1-3) - l=2: xx, xy, xz, yy, yz, zz (6 components, indices 4-9) - l=3: xxx, xxy, xxz, xyy, xyz, xzz, yyy, yyz, yzz, zzz

    (10 components, indices 10-19)

  • max_moment – Maximum multipole moment included in the input (1-4). 1=charges, 2=charges+dipoles, 3=charges+dipoles+quadrupoles, 4=charges+dipoles+quadrupoles+octupoles.

Returns:

A tuple of (charges, dipoles, quadrupoles, octupoles) where: - charges: array of shape (N,) - dipoles: array of shape (N, 3) or None if max_moment < 2 - quadrupoles: array of shape (N, 3, 3) or None if max_moment < 3 - octupoles: array of shape (N, 3, 3, 3) or None if max_moment < 4

Return type:

tuple

pympfit.mbis.multipole_transform.spherical_to_cartesian_dipole(mu_sph: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert spherical harmonic dipole to Cartesian.

Parameters:

mu_sph – Spherical harmonic dipole array of shape (N, 3). Order: [Q10, Q11c, Q11s] = [z, x, y]

Returns:

Cartesian dipole array of shape (N, 3) where columns are [x, y, z].

Return type:

NDArray[np.float64]

pympfit.mbis.multipole_transform.spherical_to_cartesian_multipoles(multipoles: ndarray[tuple[Any, ...], dtype[float64]], max_moment: int = 4) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]] | None, ndarray[tuple[Any, ...], dtype[float64]] | None, ndarray[tuple[Any, ...], dtype[float64]] | None][source]

Convert spherical harmonic multipoles to Cartesian representation.

Parameters:
  • multipoles – Spherical harmonic multipole array of shape (N, n_components) where n_components = max_moment^2. Components are ordered as: - l=0: Q00 (index 0) - l=1: Q10, Q11c, Q11s (indices 1-3) - l=2: Q20, Q21c, Q21s, Q22c, Q22s (indices 4-8) - l=3: Q30, Q31c, Q31s, Q32c, Q32s, Q33c, Q33s (indices 9-15)

  • max_moment – Maximum multipole moment included in the input (1-4). 1=charges, 2=+dipoles, 3=+quadrupoles, 4=+octupoles.

Returns:

A tuple of (charges, dipoles, quadrupoles, octupoles) where: - charges: array of shape (N,) - dipoles: array of shape (N, 3) or None if max_moment < 2 - quadrupoles: array of shape (N, 3, 3) or None if max_moment < 3 - octupoles: array of shape (N, 3, 3, 3) or None if max_moment < 4

Return type:

tuple

pympfit.mbis.multipole_transform.spherical_to_cartesian_octupole(o_sph: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert spherical harmonic octupole to Cartesian.

The transformation uses:

Omega_xxx = sqrt(5/8) Q33c - sqrt(3/8) Q31c Omega_xxy = sqrt(5/8) Q33s - sqrt(1/24) Q31s Omega_xyy = -sqrt(5/8) Q33c - sqrt(1/24) Q31c Omega_yyy = -sqrt(5/8) Q33s - sqrt(3/8) Q31s Omega_xxz = sqrt(5/12) Q32c - 1/2 Q30 Omega_xyz = sqrt(5/12) Q32s Omega_yyz = -sqrt(5/12) Q32c - 1/2 Q30 Omega_xzz = sqrt(2/3) Q31c Omega_yzz = sqrt(2/3) Q31s Omega_zzz = Q30

Parameters:

o_sph – Spherical harmonic octupole array of shape (N, 7). Order: [Q30, Q31c, Q31s, Q32c, Q32s, Q33c, Q33s]

Returns:

Cartesian octupole tensor of shape (N, 3, 3, 3).

Return type:

NDArray[np.float64]

pympfit.mbis.multipole_transform.spherical_to_cartesian_quadrupole(q_sph: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Convert spherical harmonic quadrupole to Cartesian.

The transformation uses:

Theta_xx = -1/2 Q20 + 1/2 sqrt(3) Q22c Theta_yy = -1/2 Q20 - 1/2 sqrt(3) Q22c Theta_zz = Q20 Theta_xy = 1/(2*sqrt(3)) Q22s Theta_xz = 1/(2*sqrt(3)) Q21c Theta_yz = 1/(2*sqrt(3)) Q21s

Parameters:

q_sph – Spherical harmonic quadrupole array of shape (N, 5). Order: [Q20, Q21c, Q21s, Q22c, Q22s]

Returns:

Cartesian quadrupole tensor of shape (N, 3, 3).

Return type:

NDArray[np.float64]

pympfit.mbis.storage

Store MBIS data in SQLite databases.

class pympfit.mbis.storage.MoleculeMBISRecord(*, tagged_smiles: str, conformer: ~typing.Annotated[~numpy.ndarray[float], ~pydantic.functional_validators.BeforeValidator(func=functools.partial(<function _array_validator at 0x76065cfbc4a0>, unit='angstrom'), json_schema_input_type=PydanticUndefined)], multipoles: ~typing.Annotated[~numpy.ndarray[float], ~pydantic.functional_validators.BeforeValidator(func=functools.partial(<function _array_validator at 0x76065cfbc4a0>, unit='AU'), json_schema_input_type=PydanticUndefined)], mbis_settings: ~pympfit.mbis._mbis.MBISSettings)[source]

Bases: BaseModel

Record containing MBIS results for a molecule conformer.

Includes molecule information, conformer coordinates, MBIS settings provenance, and multipole values for each atom.

conformer: partial(<function _array_validator at 0x76065cfbc4a0>, unit='angstrom'), json_schema_input_type=PydanticUndefined)]
property conformer_quantity: Quantity
classmethod from_molecule(molecule: Molecule, conformer: Quantity, multipoles: Quantity, mbis_settings: MBISSettings) MoleculeMBISRecord[source]

Create a new MoleculeMBISRecord from an existing molecule.

Takes care of creating the InChI and SMARTS representations.

Parameters:
  • molecule – The molecule to store in the record.

  • conformer – The coordinates [Angstrom] of this conformer with shape=(n_atoms, 3).

  • multipoles – The multipole moments [AU] for each atom in the molecule.

  • mbis_settings – The settings used to generate the MBIS stored in this record.

Return type:

The created record.

mbis_settings: MBISSettings
model_config = {'arbitrary_types_allowed': True}

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

multipoles: partial(<function _array_validator at 0x76065cfbc4a0>, unit='AU'), json_schema_input_type=PydanticUndefined)]
property multipoles_quantity: Quantity
tagged_smiles: str
class pympfit.mbis.storage.MoleculeMBISStore(database_path: str = 'mbis-store.sqlite', cache_size: None | int = None)[source]

Bases: object

Store and retrieve MBIS results for molecules in multiple conformers.

This class currently can only store the data in a SQLite database.

property db_version: int
property general_provenance: dict[str, str]
list() list[str][source]

List the molecules which exist in and may be retrieved from the store.

retrieve(smiles: str | None = None, basis: str | None = None, method: str | None = None) list[MoleculeMBISRecord][source]

Retrieve records stored in this data store.

Optionally filters according to a set of criteria.

set_provenance(general_provenance: dict[str, str], software_provenance: dict[str, str]) None[source]

Set the stores provenance information.

Parameters:
  • general_provenance – A dictionary storing provenance about the store such as the author, which QCArchive data set it was generated from, when it was generated etc.

  • software_provenance – A dictionary storing the provenance of the software and packages used to generate the data in the store.

property software_provenance: dict[str, str]
store(*records: MoleculeMBISRecord) None[source]

Store the MBIS calculated for a given molecule in the data store.

Parameters:

records – The records to store.

Return type:

The records as they appear in the store.

Utilities for storing MBIS data in a SQLite database.

class pympfit.mbis.storage.db.DBConformerRecord(**kwargs)[source]

Bases: Base

Database representation of a conformer record.

coordinates
id
mbis_settings
mbis_settings_id
multipoles
parent_id
tagged_smiles
class pympfit.mbis.storage.db.DBGeneralProvenance(**kwargs)[source]

Bases: Base

Database representation of general provenance information.

key
parent_id
value
class pympfit.mbis.storage.db.DBInformation(**kwargs)[source]

Bases: Base

Track current database settings and version.

general_provenance
software_provenance
version
class pympfit.mbis.storage.db.DBMBISSettings(**kwargs)[source]

Bases: _UniqueMixin, Base

Database representation of MBISSettings.

basis
d_convergence
classmethod db_to_instance(db_instance: DBMBISSettings) MBISSettings[source]

Convert a database record to a MBISSettings instance.

dft_radial_points
dft_spherical_points
e_convergence
guess
id
limit
max_moment
max_radial_moment
mbis_d_convergence
mbis_radial_points
mbis_spherical_points
method
mpfit_atom_radius
mpfit_inner_radius
mpfit_outer_radius
multipole_format
multipole_units
class pympfit.mbis.storage.db.DBMoleculeRecord(**kwargs)[source]

Bases: Base

Database representation of a molecule record.

conformers
smiles
class pympfit.mbis.storage.db.DBSoftwareProvenance(**kwargs)[source]

Bases: Base

Database representation of software provenance information.

key
parent_id
value