예제 #1
0
    def test_restrained_dihedrals(self):

        quad = [2, 0, 1, 3]
        angle = np.rad2deg(dihedralAngle(self.h2o2_90.coords[quad, :, 0]))
        self.assertEqualFloat(89.999544881803772, angle, tol=1e-7)

        with TemporaryDirectory(dir=self.testDir) as tmpDir:
            self.qm.molecule = self.h2o2_90
            self.qm.theory = "BLYP"  # HF fails
            self.qm.basis = "3-21G"
            self.qm.optimize = True
            self.qm.restrained_dihedrals = np.array([quad])
            self.qm.directory = tmpDir
            result = self.qm.run()[0]
            self.assertFalse(result.errored)
            angle = np.rad2deg(dihedralAngle(result.coords[quad, :, 0]))
            self.assertEqualFloat(89.999541178019271, angle, tol=1e-7)

        with TemporaryDirectory(dir=self.testDir) as tmpDir:
            self.qm.restrained_dihedrals = None
            self.qm.directory = tmpDir
            result = self.qm.run()[0]
            self.assertFalse(result.errored)
            angle = np.rad2deg(dihedralAngle(result.coords[quad, :, 0]))
            if isinstance(self.qm, Psi4):
                self.assertEqualFloat(179.5169310744747, angle,
                                      tol=1e-3)  # Unstable results
            else:
                self.assertEqualFloat(-168.9488713666722, angle,
                                      tol=1e-5)  # Unstable results
예제 #2
0
파일: test.py 프로젝트: shozebhaider/htmd
    def test_restrained_dihedrals(self):

        quad = [2, 0, 1, 3]
        angle = np.rad2deg(dihedralAngle(self.h2o2_90.coords[quad, :, 0]))
        self.assertAlmostEqual(89.999544881803772, angle, places=5)

        with TemporaryDirectory(dir=self.testDir) as tmpDir:
            self.qm.molecule = self.h2o2_90
            self.qm.theory = 'BLYP' # HF fails
            self.qm.basis = '3-21G'
            self.qm.optimize = True
            self.qm.restrained_dihedrals = np.array([quad])
            self.qm.directory = tmpDir
            result = self.qm.run()[0]
            self.assertFalse(result.errored)
            angle = np.rad2deg(dihedralAngle(result.coords[quad, :, 0]))
            self.assertAlmostEqual(89.999541178019271, angle, places=5)

        with TemporaryDirectory(dir=self.testDir) as tmpDir:
            self.qm.restrained_dihedrals = None
            self.qm.directory = tmpDir
            result = self.qm.run()[0]
            self.assertFalse(result.errored)
            angle = np.rad2deg(dihedralAngle(result.coords[quad, :, 0]))
            self.assertAlmostEqual(179.51690845119924, angle, places=3) # Unstable results
예제 #3
0
파일: fake.py 프로젝트: shozebhaider/htmd
    def retrieve(self):

        ff = FFEvaluate(self.molecule, self._parameters)

        results = []
        for iframe in range(self.molecule.numFrames):
            self.molecule.frame = iframe

            directory = os.path.join(self.directory, '%05d' % iframe)
            os.makedirs(directory, exist_ok=True)
            pickleFile = os.path.join(directory, 'data.pkl')

            if self._completed(directory):
                with open(pickleFile, 'rb') as fd:
                    result = pickle.load(fd)
                logger.info('Loading QM data from %s' % pickleFile)

            else:
                result = QMResult()
                result.errored = False
                result.coords = self.molecule.coords[:, :, iframe:iframe + 1].copy()

                if self.optimize:
                    opt = nlopt.opt(nlopt.LN_COBYLA, result.coords.size)
                    opt.set_min_objective(lambda x, _: ff.calculateEnergies(x.reshape((-1, 3)))['total'])
                    if self.restrained_dihedrals is not None:
                        for dihedral in self.restrained_dihedrals:
                            indices = dihedral.copy()
                            ref_angle = dihedralAngle(self.molecule.coords[indices, :, iframe])
                            def constraint(x, _):
                                coords = x.reshape((-1, 3))
                                angle = dihedralAngle(coords[indices])
                                return np.sin(.5*(angle - ref_angle))
                            opt.add_equality_constraint(constraint)
                    opt.set_xtol_abs(1e-3) # Similar to Psi4 default
                    opt.set_maxeval(1000*opt.get_dimension())
                    opt.set_initial_step(1e-3)
                    result.coords = opt.optimize(result.coords.ravel()).reshape((-1, 3, 1))
                    logger.info('Optimization status: %d' % opt.last_optimize_result())

                result.energy = ff.calculateEnergies(result.coords[:, :, 0])['total']
                result.dipole = getDipole(self.molecule)

                if self.optimize:
                    assert opt.last_optimum_value() == result.energy # A self-consistency test

                # Compute ESP values
                if self.esp_points is not None:
                    assert self.molecule.numFrames == 1
                    result.esp_points = self.esp_points
                    distances = cdist(result.esp_points, result.coords[:, :, 0])  # Angstrom
                    distances *= const.physical_constants['Bohr radius'][0] / const.angstrom  # Angstrom --> Bohr
                    result.esp_values = np.dot(np.reciprocal(distances), self.molecule.charge)  # Hartree/Bohr

                with open(pickleFile, 'wb') as fd:
                    pickle.dump(result, fd)

            results.append(result)

        return results
예제 #4
0
    def _calcDihedralAngles(self, mol, dihedrals, sincos=True):
        from moleculekit.dihedral import dihedralAngle
        metric = np.zeros((np.size(mol.coords, 2), len(dihedrals)))

        for i, dih in enumerate(dihedrals):
            metric[:, i] = np.rad2deg(dihedralAngle(mol.coords[dih, :, :]))

        if sincos:
            sc_metric = np.zeros((np.size(metric, 0), np.size(metric, 1) * 2))
            sc_metric[:, 0::2] = np.sin(metric * np.pi / 180.)
            sc_metric[:, 1::2] = np.cos(metric * np.pi / 180.)
            metric = sc_metric
        return metric.astype(np.float32)
예제 #5
0
    def _setup(self):

        if len(self.dihedrals) != len(self.qm_results):
            raise ValueError('The number of dihedral and QM result sets has to be the same!')

        # Get dihedral names
        self._names = ['-'.join(self.molecule.name[dihedral]) for dihedral in self.dihedrals]

        # Get all equivalent dihedrals
        all_equivalent_dihedrals = detectParameterizableDihedrals(self.molecule)
        all_equivalent_dihedrals = {tuple(dihedrals[0]): dihedrals for dihedrals in all_equivalent_dihedrals}

        # Choose the selected dihedrals
        equivalent_dihedrals = []
        for dihedral, name in zip(self.dihedrals, self._names):
            if tuple(dihedral) not in all_equivalent_dihedrals:
                raise ValueError('{} is not a parameterizable dihedral!'.format(name))
            equivalent_dihedrals.append(all_equivalent_dihedrals[tuple(dihedral)])

        # Get dihedral atom types
        self._dihedral_atomtypes = [findDihedralType(tuple(self.molecule.atomtype[dihedral]), self.parameters) for dihedral in self.dihedrals]

        # Get reference QM energies and rotamer coordinates
        self._reference_energies = []
        self._coords = []
        for results in self.qm_results:
            self._reference_energies.append(np.array([result.energy for result in results]))
            self._coords.append([result.coords for result in results])

        # Calculate dihedral angle values
        # [# of scans, # of dihedrals, # of conformations, # of equivalents]
        self._angle_values = []
        for scan_coords in self._coords:
            scan_angle_values = []
            for equivalent_indices in equivalent_dihedrals:
                angle_values = []
                for coords in scan_coords:
                    angle_values.append([dihedralAngle(coords[indices, :, 0]) for indices in equivalent_indices])
                scan_angle_values.append(np.array(angle_values))
            self._angle_values.append(scan_angle_values)

        # Calculated initial MM energies
        ff = FFEvaluate(self.molecule, self.parameters)
        self._initial_energies = []
        for scan_coords in self._coords:
            energies = [ff.calculateEnergies(coords[:, :, 0])['total'] for coords in scan_coords]
            self._initial_energies.append(np.array(energies))

        # Make result directories
        os.makedirs(self.result_directory, exist_ok=True)
예제 #6
0
    def minimize(self, coords, restrained_dihedrals):
        if restrained_dihedrals is not None:
            for dihedral in restrained_dihedrals:
                indices = dihedral.copy()
                ref_angle = dihedralAngle(coords[indices, :, 0])

                def constraint(x, _):
                    coords = x.reshape((-1, 3))
                    angle = dihedralAngle(coords[indices])
                    return np.sin(0.5 * (angle - ref_angle))

                self.opt.add_equality_constraint(constraint)

        self.opt.set_xtol_abs(1e-3)  # Similar to Psi4 default
        self.opt.set_maxeval(1000 * self.opt.get_dimension())
        self.opt.set_initial_step(1e-3)
        return self.opt.optimize(coords.ravel()).reshape((-1, 3, 1))
예제 #7
0
파일: fake.py 프로젝트: shozebhaider/htmd
    def retrieve(self):

        prmtop = self._get_prmtop()
        system = prmtop.createSystem()
        groups = {force.getForceGroup() for force in system.getForces()}

        if self.optimize:
            if self.restrained_dihedrals is not None:
                restraint = openmm.PeriodicTorsionForce()
                restraint.setForceGroup(max(groups) + 1)

                for dihedral in self.restrained_dihedrals:
                    restraint.addTorsion(*tuple(map(int, dihedral)), periodicity=1, phase=0,
                                         k=-1000 * unit.kilocalorie_per_mole)

                system.addForce(restraint)

        simulation = app.Simulation(prmtop.topology, system,
                                    openmm.VerletIntegrator(1 * unit.femtosecond),
                                    openmm.Platform.getPlatformByName('CPU'))

        results = []
        molecule_copy = self.molecule.copy()
        for iframe in range(self.molecule.numFrames):
            self.molecule.frame = iframe
            molecule_copy.frame = iframe

            directory = os.path.join(self.directory, '%05d' % iframe)
            os.makedirs(directory, exist_ok=True)
            pickleFile = os.path.join(directory, 'data.pkl')

            if self._completed(directory):
                with open(pickleFile, 'rb') as fd:
                    results.append(pickle.load(fd))
                logger.info('Loading QM data from %s' % pickleFile)
                continue

            simulation.context.setPositions(self.molecule.coords[:, :, iframe] * unit.angstrom)
            if self.optimize:
                if self.restrained_dihedrals is not None:
                    for i, dihedral in enumerate(self.restrained_dihedrals):
                        ref_angle = np.rad2deg(dihedralAngle(self.molecule.coords[dihedral, :, iframe]))
                        parameters = restraint.getTorsionParameters(i)
                        parameters[5] = ref_angle * unit.degree
                        restraint.setTorsionParameters(i, *parameters)
                    restraint.updateParametersInContext(simulation.context)
                simulation.minimizeEnergy(tolerance=0.001 * unit.kilocalorie_per_mole)
            state = simulation.context.getState(getEnergy=True, getPositions=True, groups=groups)

            result = QMResult()
            result.charge = self.charge
            result.errored = False
            result.energy = state.getPotentialEnergy().value_in_unit(unit.kilocalorie_per_mole)
            result.coords = state.getPositions(asNumpy=True).value_in_unit(unit.angstrom).reshape((-1, 3, 1))
            result.dipole = getDipole(self.molecule)

            if self.esp_points is not None:
                assert self.molecule.numFrames == 1
                result.esp_points = self.esp_points
                distances = cdist(result.esp_points, result.coords[:, :, 0])  # Angstrom
                distances *= const.physical_constants['Bohr radius'][0] / const.angstrom  # Angstrom --> Bohr
                result.esp_values = np.dot(np.reciprocal(distances), self.molecule.charge)  # Hartree/Bohr

            results.append(result)

            with open(pickleFile, 'wb') as fd:
                pickle.dump(result, fd)

            self.molecule.write(os.path.join(directory, 'mol-init.mol2'))  # Write an optimiz
            molecule_copy.coords[:, :, iframe] = result.coords[:, :, 0]
            molecule_copy.write(os.path.join(directory, 'mol.mol2'))  # Write an optimiz

        return results
예제 #8
0
파일: fake.py 프로젝트: shozebhaider/htmd
 def constraint(x, _):
     coords = x.reshape((-1, 3))
     angle = dihedralAngle(coords[indices])
     return np.sin(.5*(angle - ref_angle))
예제 #9
0
    def minimize(self, coords, restrained_dihedrals=None, maxeval=None):
        from simtk import unit
        from simtk.openmm import app, PeriodicTorsionForce
        import simtk.openmm as mm
        from scipy.optimize import minimize

        forceidx = []
        if restrained_dihedrals:
            f = PeriodicTorsionForce()

            for dihedral in restrained_dihedrals:
                theta0 = dihedralAngle(coords[dihedral])
                f.addTorsion(
                    *tuple(map(int, dihedral)),
                    periodicity=1,
                    phase=theta0,
                    k=-10000 * unit.kilocalories_per_mole
                )

            fidx = self.system.addForce(f)
            forceidx.append(fidx)

        if coords.ndim == 3:
            coords = coords[:, :, 0]

        natoms = coords.shape[0]

        integrator = mm.LangevinIntegrator(0, 0, 0)
        sim = app.Simulation(
            self.structure.topology,
            self.system,
            integrator,
            self.platform,
            self.platprop,
        )

        def goalFunc(x):
            sim.context.setPositions(x.reshape((natoms, 3)) * unit.angstrom)
            state = sim.context.getState(getEnergy=True, getForces=True)
            energy = state.getPotentialEnergy().value_in_unit(
                unit.kilocalories_per_mole
            )
            forces = state.getForces(asNumpy=True).value_in_unit(
                unit.kilocalories_per_mole / unit.angstrom
            )
            grad = -forces.reshape(-1)
            return energy, grad

        force_tolerance = 0.1  # kcal/mol/A
        max_attempts = 50
        best_result = None
        best_force = np.inf
        for i in range(max_attempts):
            result = minimize(
                goalFunc,
                coords.reshape(-1),
                method="L-BFGS-B",
                jac=True,
                options={"ftol": 0, "gtol": force_tolerance},
            )
            max_force = np.abs(result.jac).max()

            if max_force < best_force:
                best_force = max_force
                best_result = result

            if max_force > force_tolerance:
                # Try to continue minimization by restarting the minimizer
                result = minimize(
                    goalFunc,
                    result.x,
                    method="L-BFGS-B",
                    jac=True,
                    options={"ftol": 0, "gtol": force_tolerance},
                )
                max_force = np.abs(result.jac).max()

            if max_force < best_force:
                best_force = max_force
                best_result = result

            if max_force <= force_tolerance:
                break

        if best_force > force_tolerance:
            logger.warning(
                "Did not manage to minimize structure to the desired force tolerance. Best minimized structure had a max force component {:.2f} kcal/mol/A. Threshold is {}".format(
                    best_force, force_tolerance
                )
            )

        minimized_coords = best_result.x.reshape((natoms, 3)).copy()

        if restrained_dihedrals:
            for fi in forceidx[::-1]:
                self.system.removeForce(fi)

        return minimized_coords