def calculate_t142_central_wbo(mol: oechem.OEMol,
                               params: Dict[str, List[List[int]]]) -> float:
    """Calculates the WBO between the central atoms in the t142 param in the molecule.

    (WBO is Wiberg Bond Order.)

    The `params` argument contains the parameters of the molecule (see
    `calculate_mol_params`).

    Returns -1 if the calculation fails.
    """
    # Only use first occurrence of the parameter.
    indices = params['t142'][0]

    # For torsion parameters such as t142, the central atoms should be at the
    # second and third index.
    central_indices = [indices[1], indices[2]]

    # Generate molecule conformer.
    oechem.OEAddExplicitHydrogens(mol)
    omega = oeomega.OEOmega()
    omega.SetMaxConfs(1)
    omega.SetCanonOrder(False)
    omega.SetSampleHydrogens(True)
    omega.SetEnergyWindow(15.0)  #unit?
    omega.SetRMSThreshold(1.0)
    # Don't generate random stereoisomer if not specified.
    omega.SetStrictStereo(True)
    status = omega(mol)

    if status is False:
        omega.SetStrictStereo(False)
        new_status = omega(mol)
        if new_status is False:
            logger.error("Failed to generate conformer for %s",
                         oechem.OEMolToSmiles(mol))
            return -1

    # Calculate the WBO between the two central atoms.
    conf = next(iter(mol.GetConfs()))
    charged_copy = oechem.OEMol(conf)
    results = oequacpac.OEAM1Results()

    if not AM1_CALCULATOR.CalcAM1(results, charged_copy):
        logger.error("Failed to assign partial charges to %s",
                     oechem.OEMolToSmiles(mol))
        return -2

    return results.GetBondOrder(central_indices[0], central_indices[1])
Example #2
0
    def _calc_properties(mol: oechem.OEMol) -> danceprops.DanceProperties:
        """
        Calculates properties of the given molecule and returns a
        DanceProperties object holding them.

        Based on Victoria Lim's am1wib.py - see
        https://github.com/vtlim/misc/blob/master/oechem/am1wib.py
        """
        props = danceprops.DanceProperties()

        for conf in mol.GetConfs():
            charged_copy = oechem.OEMol(conf)
            results = oequacpac.OEAM1Results()
            if not AM1.CalcAM1(results, charged_copy):
                logging.debug(
                    f"failed to assign partial charges to {mol.GetTitle()}")
                return props
            DanceGenerator._add_charge_props(mol, charged_copy, results)

            # Sum bond orders, bond lengths, and bond angles
            for atom in charged_copy.GetAtoms(oechem.OEIsInvertibleNitrogen()):
                nbors = list(atom.GetAtoms())  # (neighbors)
                ang1 = math.degrees(
                    oechem.OEGetAngle(charged_copy, nbors[0], atom, nbors[1]))
                ang2 = math.degrees(
                    oechem.OEGetAngle(charged_copy, nbors[1], atom, nbors[2]))
                ang3 = math.degrees(
                    oechem.OEGetAngle(charged_copy, nbors[2], atom, nbors[0]))
                props.tri_n_bond_angle = ang1 + ang2 + ang3

                for nbor in nbors:
                    bond_order = results.GetBondOrder(atom.GetIdx(),
                                                      nbor.GetIdx())
                    bond_length = oechem.OEGetDistance(charged_copy, atom,
                                                       nbor)
                    element = nbor.GetAtomicNum()

                    props.tri_n_bonds.append(
                        danceprops.DanceTriNBond(bond_order, bond_length,
                                                 element))
                    props.tri_n_bond_order += bond_order
                    props.tri_n_bond_length += bond_length

                break  # terminate after one trivalent nitrogen
            break  # terminate after one conformation

        return props