Skip to content

Molecule

Molecule class for representing molecular structures and computed properties.

Molecule pydantic-model

Molecule(_stjames: Molecule | None = None, **kwargs)

Bases: BaseModel

Molecular structure with optional computed properties.

Can be created from SMILES, XYZ, or directly from atoms. Wraps stjames.Molecule internally but provides a cleaner interface.

Initialize from stjames.Molecule or keyword arguments.

Show JSON schema:
{
  "description": "Molecular structure with optional computed properties.\n\nCan be created from SMILES, XYZ, or directly from atoms. Wraps stjames.Molecule\ninternally but provides a cleaner interface.",
  "properties": {},
  "title": "Molecule",
  "type": "object"
}

Config:

  • arbitrary_types_allowed: True

name property writable

name: str | None

Optional molecule name.

charge property

charge: int

Molecular charge.

multiplicity property

multiplicity: int

Spin multiplicity.

atoms property

atoms: list[Atom]

List of atoms with positions.

num_atoms property

num_atoms: int

Number of atoms.

smiles property

smiles: str | None

SMILES string representation.

energy property

energy: float | None

Electronic energy (Hartree).

charges property

charges: list[float] | None

Partial charges on each atom.

spin_densities property

spin_densities: list[float] | None

Spin densities on each atom.

dipole property

dipole: tuple[float, float, float] | None

Dipole moment vector (Debye).

homo_lumo_gap property

homo_lumo_gap: float | None

HOMO-LUMO gap (Hartree).

vibrational_modes property

vibrational_modes: list[VibrationalMode] | None

Vibrational modes from frequency calculation.

frequencies property

frequencies: list[float] | None

Vibrational frequencies (cm^-1).

zero_point_energy property

zero_point_energy: float | None

Zero-point vibrational energy (Hartree).

thermal_energy_correction property

thermal_energy_correction: float | None

Thermal correction to energy (Hartree).

thermal_enthalpy_correction property

thermal_enthalpy_correction: float | None

Thermal correction to enthalpy (Hartree).

thermal_free_energy_correction property

thermal_free_energy_correction: float | None

Thermal correction to Gibbs free energy (Hartree).

cell property

cell: PeriodicCell | None

Unit cell for periodic boundary conditions.

gradient property

gradient: list[tuple[float, float, float]] | None

Nuclear gradient (Hartree/Bohr).

symmetry property

symmetry: str | int | None

Space group number (1–230) or point group symbol.

xrd_peaks property

xrd_peaks: list[tuple[int, int, int, float]] | None

XRD reflections as (h, k, l, intensity) tuples.

band_structure property

band_structure: BandStructure | None

Electronic band structure and DOS (periodic systems only).

band_gap property

band_gap: float | None

Band gap (Hartree).

density_of_states property

density_of_states: list[tuple[float, float]] | None

Total DOS as (energy in Hartree, k-weighted count) pairs (Fermi level = 0).

elastic_tensor property

elastic_tensor: tuple[tuple[float, float, float, float, float, float], tuple[float, float, float, float, float, float], tuple[float, float, float, float, float, float], tuple[float, float, float, float, float, float], tuple[float, float, float, float, float, float], tuple[float, float, float, float, float, float]] | None

Elastic stiffness matrix in GPa (Voigt order: xx yy zz yz xz xy).

from_smiles classmethod

from_smiles(smiles: str) -> Self

Create molecule from SMILES string.

Parameters:

Name Type Description Default
smiles str

SMILES string

required

Returns:

Type Description
Self

molecule instance

from_xyz classmethod

from_xyz(xyz_string: str, charge: int | None = None, multiplicity: int | None = None) -> Self

Create Molecule from XYZ string.

Parameters:

Name Type Description Default
xyz_string str

XYZ format string

required
charge int | None

charge

None
multiplicity int | None

spin multiplicity

None

Returns:

Type Description
Self

molecule

from_xyz_file classmethod

from_xyz_file(path: str | Path, charge: int | None = None, multiplicity: int | None = None) -> Self

Create molecule from XYZ file.

Parameters:

Name Type Description Default
path str | Path

path to XYZ file

required
charge int | None

charge

None
multiplicity int | None

spin multiplicity

None

Returns:

Type Description
Self

molecule

molecules_from_sdf classmethod

molecules_from_sdf(path: str | Path) -> list[Self]

Read all records from an SDF file as a list of molecules.

Each record becomes one Molecule, in file order, with atom ordering preserved across records -- so a multi-conformer SDF reads as a consistent ensemble.

Parameters:

Name Type Description Default
path str | Path

path to the SDF file

required

Returns:

Type Description
list[Self]

one Molecule per record

from_stjames classmethod

from_stjames(stj: Molecule) -> Self

Create from stjames.Molecule.

Parameters:

Name Type Description Default
stj Molecule

stjames.Molecule

required

Returns:

Type Description
Self

molecule

from_atoms classmethod

from_atoms(atoms: list[Atom], charge: int = 0, multiplicity: int = 1, cell: PeriodicCell | None = None) -> Self

Create molecule from a list of atoms.

Parameters:

Name Type Description Default
atoms list[Atom]

list of Atom objects

required
charge int

molecular charge (default 0)

0
multiplicity int

spin multiplicity (default 1)

1
cell PeriodicCell | None

PeriodicCell for periodic boundary conditions

None

Returns:

Type Description
Self

molecule instance

to_xyz

to_xyz() -> str

Convert to XYZ format string.

to_dict

to_dict() -> dict[str, Any]

Convert to dictionary representation.

to_stjames

to_stjames() -> stjames.Molecule

Convert to stjames.Molecule.

distance

distance(i: int, j: int) -> float

Calculate distance between two atoms.

Parameters:

Name Type Description Default
i int

first atom index (1-based)

required
j int

second atom index (1-based)

required

Returns:

Type Description
float

distance in Angstroms

angle

angle(i: int, j: int, k: int, degrees: bool = True) -> float

Calculate angle between three atoms (i-j-k).

Parameters:

Name Type Description Default
i int

first atom index (1-based)

required
j int

central atom index (1-based)

required
k int

third atom index (1-based)

required
degrees bool

return angle in degrees (default) or radians

True

Returns:

Type Description
float

angle in degrees or radians

dihedral

dihedral(i: int, j: int, k: int, l: int, degrees: bool = True) -> float

Calculate dihedral angle between four atoms (i-j-k-l).

Parameters:

Name Type Description Default
i int

first atom index (1-based)

required
j int

second atom index (1-based)

required
k int

third atom index (1-based)

required
l int

fourth atom index (1-based)

required
degrees bool

return angle in degrees (default) or radians

True

Returns:

Type Description
float

dihedral angle in degrees (0-360) or radians

perturb

perturb(stddev: float = 0.005) -> Molecule

Return a copy with random Gaussian noise added to each atom position.

Useful for breaking symmetry before resubmitting an optimization (e.g. when a calculation is stuck in a saddle point or converges to an unwanted geometry).

Parameters:

Name Type Description Default
stddev float

standard deviation of the Gaussian displacement (Angstroms)

0.005

Returns:

Type Description
Molecule

new Molecule with perturbed coordinates

displace_along_mode

displace_along_mode(mode: VibrationalMode, displacement: float) -> Molecule

Return a copy with atom positions displaced along a vibrational normal mode.

Requires a prior frequency calculation. For a transition state, the imaginary mode has a negative frequency and points toward the reactant or product.

Parameters:

Name Type Description Default
mode VibrationalMode

vibrational mode to displace along, from vibrational_modes

required
displacement float

displacement distance along the normalized mode (Angstroms)

required

Returns:

Type Description
Molecule

new Molecule with displaced coordinates

Raises:

Type Description
ValueError

mode has no displacements or zero-norm displacements

load_named_ligands

load_named_ligands(path: Path | str) -> dict[str, Molecule]

Load named ligands from a multi-molecule file.

Molecule names are read from the title field of each record. Use this when ligand identity needs to be preserved - for example, building a ligand dict for an RBFE workflow where names are used as keys throughout submission and results. Every record must therefore have a unique name; duplicates raise rather than silently collapsing into one ligand.

Supported formats (all carry per-molecule name fields): - SDF / MOL (.sdf, .mol) - name from the title line - MOL2 (.mol2) - name from the @<TRIPOS>MOLECULE block

Parameters:

Name Type Description Default
path Path | str

path to an SDF, MOL, or MOL2 file

required

Returns:

Type Description
dict[str, Molecule]

dict mapping ligand name to Molecule, in file order

Raises:

Type Description
ValueError

no valid molecules are found, the format is unsupported, or two records share a name

smiles_to_stjames

smiles_to_stjames(smiles: str) -> stjames.Molecule

Convert a SMILES string to a stjames.Molecule object.

Parameters:

Name Type Description Default
smiles str

string representing the SMILES notation of the molecule

required

Returns:

Type Description
Molecule

stjames.Molecule object created from the given SMILES string

Atom pydantic-model

Bases: Base

A single atom.

:param atomic_number: atomic number :param position: Cartesian coordinates, in Å :param mass: mass, in Daltons; if None, most common isotopologue will be used

Show JSON schema:
{
  "description": "A single atom.\n\n:param atomic_number: atomic number\n:param position: Cartesian coordinates, in \u00c5\n:param mass: mass, in Daltons; if None, most common isotopologue will be used",
  "properties": {
    "atomic_number": {
      "minimum": 0,
      "title": "Atomic Number",
      "type": "integer"
    },
    "position": {
      "maxItems": 3,
      "minItems": 3,
      "prefixItems": [
        {
          "type": "number"
        },
        {
          "type": "number"
        },
        {
          "type": "number"
        }
      ],
      "title": "Position",
      "type": "array"
    },
    "mass": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Mass"
    }
  },
  "required": [
    "atomic_number",
    "position"
  ],
  "title": "Atom",
  "type": "object"
}

Fields:

  • atomic_number (NonNegativeInt)
  • position (Vector3D)
  • mass (float | None)

atomic_symbol property

atomic_symbol: str

Atom(atomic_number=2, position=[0, 1, 2]).atomic_symbol 'He'

edited

edited(atomic_number: int | None = None, position: Sequence[float] | None = None, mass: float | None = None) -> Self

Create a new Atom with the specified changes.

a = Atom(atomic_number=2, position=[0, 1, 2]) a2 = a.edited(3) a is a2 False a2 Atom(3, [0.00000, 1.00000, 2.00000])

from_xyz classmethod

from_xyz(xyz_line: str) -> Self

Atom.from_xyz("H 0 0 0") Atom(1, [0.00000, 0.00000, 0.00000])

VibrationalMode pydantic-model

Bases: Base

Vibrational mode from frequency analysis.

:param frequency: vibrational frequency, in cm⁻¹ :param reduced_mass: reduced mass, in amu :param force_constant: force constant, in mDyne/Å :param displacements: atomic displacement vectors, in Å :param ir_intensity: infrared intensity, in km/mol :param symmetry_label: irreducible representation of mode, interpreted per Molecule.symmetry point group (e.g. "A1", "B2g", "E'")

Show JSON schema:
{
  "description": "Vibrational mode from frequency analysis.\n\n:param frequency: vibrational frequency, in cm\u207b\u00b9\n:param reduced_mass: reduced mass, in amu\n:param force_constant: force constant, in mDyne/\u00c5\n:param displacements: atomic displacement vectors, in \u00c5\n:param ir_intensity: infrared intensity, in km/mol\n:param symmetry_label: irreducible representation of mode, interpreted per Molecule.symmetry point group (e.g. \"A1\", \"B2g\", \"E'\")",
  "properties": {
    "frequency": {
      "title": "Frequency",
      "type": "number"
    },
    "reduced_mass": {
      "title": "Reduced Mass",
      "type": "number"
    },
    "force_constant": {
      "title": "Force Constant",
      "type": "number"
    },
    "displacements": {
      "items": {
        "maxItems": 3,
        "minItems": 3,
        "prefixItems": [
          {
            "type": "number"
          },
          {
            "type": "number"
          },
          {
            "type": "number"
          }
        ],
        "type": "array"
      },
      "title": "Displacements",
      "type": "array"
    },
    "ir_intensity": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Ir Intensity"
    },
    "symmetry_label": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Symmetry Label"
    }
  },
  "required": [
    "frequency",
    "reduced_mass",
    "force_constant",
    "displacements"
  ],
  "title": "VibrationalMode",
  "type": "object"
}

Fields:

  • frequency (float)
  • reduced_mass (float)
  • force_constant (float)
  • displacements (Vector3DPerAtom)
  • ir_intensity (float | None)
  • symmetry_label (str | None)

PeriodicCell pydantic-model

Bases: Base

Unit cell for periodic systems.

:param lattice_vectors: 3x3 matrix of lattice vectors, in Å :param is_periodic: periodicity in each dimension

Show JSON schema:
{
  "description": "Unit cell for periodic systems.\n\n:param lattice_vectors: 3x3 matrix of lattice vectors, in \u00c5\n:param is_periodic: periodicity in each dimension",
  "properties": {
    "lattice_vectors": {
      "maxItems": 3,
      "minItems": 3,
      "prefixItems": [
        {
          "maxItems": 3,
          "minItems": 3,
          "prefixItems": [
            {
              "type": "number"
            },
            {
              "type": "number"
            },
            {
              "type": "number"
            }
          ],
          "type": "array"
        },
        {
          "maxItems": 3,
          "minItems": 3,
          "prefixItems": [
            {
              "type": "number"
            },
            {
              "type": "number"
            },
            {
              "type": "number"
            }
          ],
          "type": "array"
        },
        {
          "maxItems": 3,
          "minItems": 3,
          "prefixItems": [
            {
              "type": "number"
            },
            {
              "type": "number"
            },
            {
              "type": "number"
            }
          ],
          "type": "array"
        }
      ],
      "title": "Lattice Vectors",
      "type": "array"
    },
    "is_periodic": {
      "default": [
        true,
        true,
        true
      ],
      "maxItems": 3,
      "minItems": 3,
      "prefixItems": [
        {
          "type": "boolean"
        },
        {
          "type": "boolean"
        },
        {
          "type": "boolean"
        }
      ],
      "title": "Is Periodic",
      "type": "array"
    }
  },
  "required": [
    "lattice_vectors"
  ],
  "title": "PeriodicCell",
  "type": "object"
}

Fields:

  • lattice_vectors (Matrix3x3)
  • is_periodic (Bool3)

Validators:

  • check_tensor_3D → lattice_vectors
  • check_pbc → is_periodic

from_string classmethod

from_string(string: str) -> Self

Create a PeriodicCell from a string representation.

PeriodicCell.from_string("[(1, -2, 3.0), [4e1, +5, 6], (7.1, 8, 9)]") PeriodicCell(lattice_vectors=((1.0, -2.0, 3.0), (40.0, 5.0, 6.0), (7.1, 8.0, 9.0)), is_periodic=(True, True, True)) PeriodicCell.from_string("[(a, -2, 3.0), [4e1, +5, 6], (7.1, 8, 9)]") Traceback (most recent call last): ... ValueError: Could not parse cell from string: [(a, -2, 3.0), [4e1, +5, 6], (7.1, 8, 9)] PeriodicCell.from_string("[(1, -2, 3.0), [4e1, +5, 6], (7.1, 8, 9, 10)]") Traceback (most recent call last): ... ValueError: Cell must be a 3x3 matrix: got [(1, -2, 3.0), [4e1, +5, 6], (7.1, 8, 9, 10)] PeriodicCell.from_string("[('a', -2, 3.0), [4e1, +5, 6], (7.1, 8, 9)]") Traceback (most recent call last): ValueError: Cell must be a 3x3 matrix of numbers: got [('a', -2, 3.0), [4e1, +5, 6], (7.1, 8, 9)]

Data models for periodic system properties.

BandStructure pydantic-model

Bases: BaseModel

Electronic band structure for a periodic system.

Eigenvalues are shifted so the Fermi level is at 0.

:param kpoint_distances: cumulative distances along the k-path, in units of 2π/Å; length = n_kpoints :param eigenvalues: eigenvalues in Hartree (Fermi level = 0); shape (n_bands, n_kpoints) :param high_symmetry_points: high-symmetry k-point labels and their cumulative path distances in 2π/Å (e.g. [("Γ", 0.0), ("X", 1.23)]) :param total_density_of_states: density of states from a separate uniform k-mesh; list of (energy in Hartree, k-weighted count) pairs (Fermi level = 0) :param band_gap: band gap in Hartree :param valence_band_maximum: valence band maximum in Hartree (Fermi level = 0) :param conduction_band_minimum: conduction band minimum in Hartree (Fermi level = 0)

Show JSON schema:
{
  "description": "Electronic band structure for a periodic system.\n\nEigenvalues are shifted so the Fermi level is at 0.\n\n:param kpoint_distances: cumulative distances along the k-path, in units of 2\u03c0/\u00c5; length = n_kpoints\n:param eigenvalues: eigenvalues in Hartree (Fermi level = 0); shape (n_bands, n_kpoints)\n:param high_symmetry_points: high-symmetry k-point labels and their cumulative path distances in 2\u03c0/\u00c5 (e.g. [(\"\u0393\", 0.0), (\"X\", 1.23)])\n:param total_density_of_states: density of states from a separate uniform k-mesh; list of (energy in Hartree, k-weighted count) pairs (Fermi level = 0)\n:param band_gap: band gap in Hartree\n:param valence_band_maximum: valence band maximum in Hartree (Fermi level = 0)\n:param conduction_band_minimum: conduction band minimum in Hartree (Fermi level = 0)",
  "properties": {
    "kpoint_distances": {
      "items": {
        "type": "number"
      },
      "title": "Kpoint Distances",
      "type": "array"
    },
    "eigenvalues": {
      "items": {
        "items": {
          "type": "number"
        },
        "type": "array"
      },
      "title": "Eigenvalues",
      "type": "array"
    },
    "high_symmetry_points": {
      "items": {
        "maxItems": 2,
        "minItems": 2,
        "prefixItems": [
          {
            "type": "string"
          },
          {
            "type": "number"
          }
        ],
        "type": "array"
      },
      "title": "High Symmetry Points",
      "type": "array"
    },
    "total_density_of_states": {
      "items": {
        "maxItems": 2,
        "minItems": 2,
        "prefixItems": [
          {
            "type": "number"
          },
          {
            "type": "number"
          }
        ],
        "type": "array"
      },
      "title": "Total Density Of States",
      "type": "array"
    },
    "band_gap": {
      "title": "Band Gap",
      "type": "number"
    },
    "valence_band_maximum": {
      "title": "Valence Band Maximum",
      "type": "number"
    },
    "conduction_band_minimum": {
      "title": "Conduction Band Minimum",
      "type": "number"
    }
  },
  "required": [
    "kpoint_distances",
    "eigenvalues",
    "high_symmetry_points",
    "total_density_of_states",
    "band_gap",
    "valence_band_maximum",
    "conduction_band_minimum"
  ],
  "title": "BandStructure",
  "type": "object"
}

Fields:

  • kpoint_distances (list[float])
  • eigenvalues (list[list[float]])
  • high_symmetry_points (list[tuple[str, float]])
  • total_density_of_states (list[tuple[float, float]])
  • band_gap (float)
  • valence_band_maximum (float)
  • conduction_band_minimum (float)