Ejemplo n.º 1
0
    def _run(self, molName):

        self.molName = molName

        logger.info("Molecule: {}".format(self.molName))

        molFile = os.path.join(home("test-charge"), self.molName + ".mol2")
        self.mol = Molecule(molFile)

        self.new_mols = {}
        self.extras = {}

        self.new_mols["Gasteiger"] = fitGasteigerCharges(self.mol)
        try:
            self.new_mols["AM1-BCC"] = fitChargesWithAntechamber(self.mol,
                                                                 type="bcc")
        except:
            pass

        qm = Psi4()
        qm.theory = "B3LYP"
        qm.basis = "6-311++G**"

        workDir = os.path.join("tmp", self.molName)
        os.makedirs(workDir, exist_ok=True)

        for factor in [-10, -5, -4, -3, -2, -1]:
            logger.info("Factor: {}".format(factor))
            key = "ESP b {}".format(factor)
            np.random.seed(20181114)  # Make ESP grid generation deterministic
            self.new_mols[key], self.extras[key] = fitESPCharges(
                self.mol, qm, workDir, restraint_factor=10**factor)
Ejemplo n.º 2
0
def _fit_initial_charges(mol, args, atom_types):

    from parameterize.charge import fitGasteigerCharges
    from parameterize.parameterization.util import guessBondType

    logger.info("=== Initial atomic charge fitting ===")

    if args.charge_type == "None":
        logger.info("Initial atomic charges are taken from {}".format(
            args.filename))

    elif args.charge_type in ("Gasteiger", "AM1-BCC", "ESP"):
        if args.min_type == "mm":
            logger.info("Method: Gasteiger")

            # TODO move to _prepare_molecule
            if np.any(mol.bondtype == "un"):
                logger.info("Guessing bond types")
                mol = guessBondType(mol)

            mol = fitGasteigerCharges(mol, atom_types=atom_types)

            charge = int(round(np.sum(mol.charge)))
            if args.charge != charge:
                logger.warning(
                    f"Molecular charge is {args.charge}, but Gasteiger atomic charges add up to {charge}!"
                )
                args.charge = charge

            # Print the initial charges
            logger.info("Initial atomic charges:")
            for name, charge in zip(mol.name, mol.charge):
                logger.info("   {:4s}: {:6.3f}".format(name, charge))
            logger.info("Molecular charge: {:6.3f}".format(np.sum(mol.charge)))

        elif args.min_type in ("None", "qm"):
            logger.info("Initial atomic charges are not required")

        else:
            raise AssertionError()

    else:
        raise AssertionError()

    return mol
Ejemplo n.º 3
0
def _fit_charges(mol, args, qm, atom_types):

    from parameterize.charge import (
        fitGasteigerCharges,
        fitChargesWithAntechamber,
        fitESPCharges,
        symmetrizeCharges,
    )
    from parameterize.parameterization.util import (
        guessBondType,
        getFixedChargeAtomIndices,
        getDipole,
        _qm_method_name,
    )
    from parameterize.parameterization.detect import detectEquivalentAtoms

    logger.info("=== Atomic charge fitting ===")
    logger.info("Method: {}".format(args.charge_type))

    if args.charge_type == "None":

        # TODO move to argument validation
        if len(args.fix_charge) > 0:
            logger.warning("Flag --fix-charge does not have effect!")

        logger.info("Atomic charges are taken from {}".format(args.filename))

    elif args.charge_type == "Gasteiger":

        # TODO move to argument validation
        if len(args.fix_charge) > 0:
            logger.warning("Flag --fix-charge does not have effect!")

        # TODO move to _prepare_molecule
        if np.any(mol.bondtype == "un"):
            logger.info("Guessing bond types")
            mol = guessBondType(mol)

        mol = fitGasteigerCharges(mol, atom_types=atom_types)

        charge = int(round(np.sum(mol.charge)))
        if args.charge != charge:
            logger.warning(
                f"Molecular charge is {args.charge}, but Gasteiger atomic charges add up to {charge}!"
            )
            args.charge = charge

    elif args.charge_type == "AM1-BCC":

        # TODO move to argument validation
        if len(args.fix_charge) > 0:
            logger.warning("Flag --fix-charge does not have effect!")

        mol = fitChargesWithAntechamber(mol, type="bcc", molCharge=args.charge)
        mol = symmetrizeCharges(mol)

    elif args.charge_type == "ESP":

        # Detect equivalent atom groups
        logger.info("Equivalent atom groups:")
        atom_groups = [
            group for group in detectEquivalentAtoms(mol)[0] if len(group) > 1
        ]
        for atom_group in atom_groups:
            logger.info("    {}".format(", ".join(mol.name[list(atom_group)])))

        # Select the atoms with fixed charges
        fixed_atom_indices = getFixedChargeAtomIndices(mol, args.fix_charge)

        # Create an ESP directory
        espDir = os.path.join(args.outdir, "esp", _qm_method_name(qm))
        os.makedirs(espDir, exist_ok=True)

        charge = int(round(np.sum(mol.charge)))
        if args.charge != charge:
            logger.warning(
                "Molecular charge is set to {}, but atomic charges add up to {}"
                "".format(args.charge, charge))
            if len(args.fix_charge) > 0:
                raise RuntimeError(
                    "Flag --fix-charge cannot be used when atomic charges are inconsistent with passed "
                    "molecular charge {}".format(args.charge))
            mol.charge[:] = args.charge / mol.numAtoms

        # Set random number generator seed
        if args.seed:
            np.random.seed(args.seed)

        # Fit ESP charges
        mol, extra = fitESPCharges(mol, qm, espDir, fixed=fixed_atom_indices)

        # Print QM dipole
        logger.info(
            "QM dipole: {:6.3f} {:6.3f} {:6.3f}; total: {:6.3f}".format(
                *extra["qm_dipole"]))

    else:
        raise ValueError()

    # Print MM dipole
    mm_dipole = getDipole(mol)
    logger.info("MM dipole: {:6.3f} {:6.3f} {:6.3f}; total: {:6.3f}".format(
        *mm_dipole))

    # Print the new charges
    logger.info("Atomic charges:")
    for name, charge in zip(mol.name, mol.charge):
        logger.info("   {:4s}: {:6.3f}".format(name, charge))
    logger.info("Molecular charge: {:6.3f}".format(np.sum(mol.charge)))

    return mol