Esempio n. 1
0
    def __init__(self,
                 filename=None,
                 name=None,
                 rtf=None,
                 prm=None,
                 netcharge=None,
                 method=FFTypeMethod.CGenFF_2b6,
                 basis=BasisSet._6_31G_star,
                 solvent=True,
                 theory=Theory.B3LYP,
                 execution=Execution.Inline,
                 qmcode=Code.PSI4,
                 outdir="./"):
        # filename -- a mol2 format input geometry
        # rtf, prm -- rtf, prm files
        # method  -- if rtf, prm == None, guess atom types according to this method ( of enum FFTypeMethod )
        self.basis = basis
        self.theory = theory
        self.solvent = solvent

        self.solvent_name = "vacuum"
        if solvent:
            self.solvent_name = "water"

        if theory == Theory.RHF:
            self.theory_name = "rhf"
        if theory == Theory.B3LYP:
            self.theory_name = "b3lyp"

        if basis == BasisSet._6_31G_star:
            self.basis_name = "6-31g-star"
        elif basis == BasisSet._cc_pVDZ:
            self.basis_name = "cc-pVDZ"
        else:
            raise ValueError("Unknown Basis Set")

        self.execution = execution
        self.qmcode = qmcode
        self.method = method
        self.outdir = outdir

        if not (filename.endswith(".mol2")):
            raise ValueError("Input file must be mol2 format")

        super().__init__(filename=filename, name=name)

        if (len(self.bonds) == 0):
            print("No bonds found. Guessing them")
            self.bonds = self._guessBonds()
        (a, b) = guessAnglesAndDihedrals(self.bonds, cyclicdih=True)
        self.natoms = self.serial.shape[0]
        self.angles = a
        self.dihedrals = b
        ee = detectEquivalents(self)
        self._soft_dihedrals = detectSoftDihedrals(self, ee)
        self._equivalent_atom_groups = ee[
            0]  # list of groups of equivalent atoms
        self._equivalent_atoms = ee[
            1]  # list of equivalent atoms, indexed by atom
        self._equivalent_group_by_atom = ee[
            2]  # mapping from atom index to equivalent atom group
        if netcharge is None:
            self.netcharge = int(round(np.sum(self.charge)))
        else:
            self.netcharge = int(round(netcharge))

        # Canonicalise the atom naming.
        self._rename_mol()

        if rtf and prm:
            # If the user has specified explicit RTF and PRM files go ahead and load those
            self._rtf = RTF(rtf)
            self._prm = PRM(prm)
        else:
            # Otherwise make atom types using the specified method
            # (Right now only MATCH)
            fftype = FFType(self, method=self.method)
            self._rtf = fftype._rtf
            self._prm = fftype._prm
        if not self._rtf or not self._prm:
            raise ValueError("RTF and PRM not defined")

        self.impropers = np.array(self._rtf.impropers)

        self.report()
Esempio n. 2
0
    def __init__(self,
                 mol,
                 method=FFTypeMethod.CGenFF_2b6,
                 acCharges=None,
                 tmpDir=None):

        # Find the executables
        if method == FFTypeMethod.GAFF or method == FFTypeMethod.GAFF2:
            antechamber_binary = shutil.which("antechamber")
            if not antechamber_binary:
                raise RuntimeError("antechamber executable not found")

            parmchk2_binary = shutil.which("parmchk2")
            if not parmchk2_binary:
                raise RuntimeError("parmchk2 executable not found")

        elif method == FFTypeMethod.CGenFF_2b6:
            match_binary = shutil.which("match-typer")
            if not match_binary:
                raise RuntimeError("match-typer executable not found")

        else:
            raise ValueError('method')

        # Create a temporary directory
        with TemporaryDirectory() as tmpdir:

            # HACK to keep the files
            tmpdir = tmpdir if tmpDir is None else tmpDir

            if method == FFTypeMethod.GAFF or method == FFTypeMethod.GAFF2:

                # Write the molecule to a file
                mol.write(os.path.join(tmpdir, 'mol.mol2'))

                # Run antechamber
                if method == FFTypeMethod.GAFF:
                    atomtype = "gaff"
                elif method == FFTypeMethod.GAFF2:
                    atomtype = "gaff2"
                else:
                    raise ValueError('method')
                cmd = [
                    antechamber_binary, '-at', atomtype, '-nc',
                    str(mol.netcharge), '-fi', 'mol2', '-i', 'mol.mol2', '-fo',
                    'prepi', '-o', 'mol.prepi'
                ]
                if acCharges is not None:
                    cmd += ['-c', acCharges]
                returncode = subprocess.call(cmd, cwd=tmpdir)
                if returncode != 0:
                    raise RuntimeError('"antechamber" failed')

                # Run parmchk2
                returncode = subprocess.call([
                    parmchk2_binary, '-f', 'prepi', '-i', 'mol.prepi', '-o',
                    'mol.frcmod', '-a', 'Y'
                ],
                                             cwd=tmpdir)
                if returncode != 0:
                    raise RuntimeError('"parmchk2" failed')

                # Read the results
                self._rtf = AmberRTF(mol, os.path.join(tmpdir, 'mol.prepi'),
                                     os.path.join(tmpdir, 'mol.frcmod'))
                self._prm = AmberPRM(os.path.join(tmpdir, 'mol.prepi'),
                                     os.path.join(tmpdir, 'mol.frcmod'))

            elif method == FFTypeMethod.CGenFF_2b6:

                # Write the molecule to a file
                mol.write(os.path.join(tmpdir, 'mol.pdb'))

                # Run match-type
                returncode = subprocess.call([
                    match_binary, '-charge',
                    str(mol.netcharge), '-forcefield', 'top_all36_cgenff_new',
                    'mol.pdb'
                ],
                                             cwd=tmpdir)
                if returncode != 0:
                    raise RuntimeError('"match-typer" failed')

                # Read the results
                self._rtf = RTF(os.path.join(tmpdir, 'mol.rtf'))
                self._prm = PRM(os.path.join(tmpdir, 'mol.prm'))

            else:
                raise ValueError('method')
Esempio n. 3
0
    def __init__(self,
                 filename=None,
                 name=None,
                 rtf=None,
                 prm=None,
                 netcharge=None,
                 method=FFTypeMethod.CGenFF_2b6,
                 qm=None,
                 outdir="./",
                 mol=None,
                 acCharges=None):

        if filename is not None and not filename.endswith('.mol2'):
            raise ValueError('Input file must be mol2 format')

        if mol is None:
            super().__init__(filename=filename, name=name)
        else:
            for v in mol.__dict__:
                self.__dict__[v] = deepcopy(mol.__dict__[v])

        # Guess bonds
        if len(self.bonds) == 0:
            logger.warning('No bonds found! Guessing them...')
            self.bonds = self._guessBonds()

        # Guess angles and dihedrals
        self.angles, self.dihedrals = guessAnglesAndDihedrals(self.bonds,
                                                              cyclicdih=True)

        # Detect equivalent atoms
        equivalents = detectEquivalents(self)
        self._equivalent_atom_groups = equivalents[
            0]  # List of groups of equivalent atoms
        self._equivalent_atoms = equivalents[
            1]  # List of equivalent atoms, indexed by atom
        self._equivalent_group_by_atom = equivalents[
            2]  # Mapping from atom index to equivalent atom group

        # Detect rotatable dihedrals
        self._rotatable_dihedrals = detectSoftDihedrals(self, equivalents)

        # Set total charge
        if netcharge is None:
            self.netcharge = int(round(np.sum(self.charge)))
        else:
            self.netcharge = int(round(netcharge))

        # Canonicalise the names
        self._rename()

        # Assign atom types, charges, and initial parameters
        self.method = method
        if rtf and prm:
            # If the user has specified explicit RTF and PRM files go ahead and load those
            self._rtf = RTF(rtf)
            self._prm = PRM(prm)
            logger.info('Reading FF parameters from %s and %s' % (rtf, prm))
        elif method == FFTypeMethod.NONE:
            pass  # Don't assign any atom types
        else:
            # Otherwise make atom types using the specified method
            fftype = FFType(self, method=self.method, acCharges=acCharges)
            logger.info('Assigned atom types with %s' % self.method.name)
            self._rtf = fftype._rtf
            self._prm = fftype._prm

        if hasattr(self, '_rtf'):
            self.atomtype[:] = [
                self._rtf.type_by_name[name] for name in self.name
            ]
            self.charge[:] = [
                self._rtf.charge_by_name[name] for name in self.name
            ]
            self.impropers = np.array(self._rtf.impropers)

            # Check if atom type names are compatible
            for type_ in self._rtf.types:
                if re.match(FFMolecule._ATOM_TYPE_REG_EX, type_):
                    raise ValueError(
                        'Atom type %s is incompatable. It cannot finish with "x" + number!'
                        % type_)

        # Set atom masses
        # TODO: maybe move to molecule
        if self.masses.size == 0:
            if hasattr(self, '_rtf'):
                self.masses[:] = [
                    self._rtf.mass_by_type[self._rtf.type_by_index[i]]
                    for i in range(self.numAtoms)
                ]
            else:
                self.masses[:] = [
                    vdw.massByElement(element) for element in self.element
                ]

        self.qm = qm if qm else Psi4()
        self.outdir = outdir