Example #1
0
 def test_dihedral_ethene(self):
     mol = XYZFile("input/ethene.xyz").get_molecule()
     c = mol.coordinates.copy()
     self.assertAlmostEqual(ic.dihed_cos(c[2], c[0], c[3], c[5])[0], 1.0)
     self.assertAlmostEqual(ic.dihed_angle(c[2], c[0], c[3], c[5])[0], 0.0)
     for i in xrange(1000):
         angle = numpy.random.uniform(-numpy.pi, numpy.pi)
         radius = numpy.random.uniform(0, 5*angstrom)
         offset = numpy.random.uniform(0, 5*angstrom)
         c[5] = [
             offset,
             -radius*numpy.cos(angle),
             radius*numpy.sin(angle),
         ]
         self.assertAlmostEqual(ic.dihed_cos(c[2], c[0], c[3], c[5])[0], numpy.cos(angle))
         self.assertAlmostEqual(ic.dihed_angle(c[2], c[0], c[3], c[5])[0], angle)
Example #2
0
 def cart_to_zmat(self, coordinates):
     N = len(self.graph.numbers)
     result = numpy.zeros(N, dtype=self.dtype)
     for i in xrange(N):
         ref0 = self.old_index[i]
         rel1 = -1
         rel2 = -1
         rel3 = -1
         distance = 0
         angle = 0
         dihed = 0
         if i > 0:
             ref1 = self.get_new_ref([ref0])
             distance = numpy.linalg.norm(coordinates[ref0]-coordinates[ref1])
             rel1 = i - self.new_index[ref1]
         if i > 1:
             ref2 = self.get_new_ref([ref0, ref1])
             angle, = ic.bend_angle(coordinates[ref0], coordinates[ref1], coordinates[ref2])
             rel2 = i - self.new_index[ref2]
         if i > 2:
             ref3 = self.get_new_ref([ref0, ref1, ref2])
             dihed, = ic.dihed_angle(coordinates[ref0], coordinates[ref1], coordinates[ref2], coordinates[ref3])
             rel3 = i - self.new_index[ref3]
         result[i] = (self.graph.numbers[i], distance, rel1, angle, rel2, dihed, rel3)
     return result
Example #3
0
    def cart_to_zmat(self, coordinates):
        """Convert cartesian coordinates to ZMatrix format

           Argument:
             coordinates  --  Cartesian coordinates (numpy array Nx3)

           The coordinates must match with the graph that was used to initialize
           the ZMatrixGenerator object.
        """
        N = len(self.graph.numbers)
        if coordinates.shape != (N, 3):
            raise ValueError("The shape of the coordinates must be (%i, 3)" % N)
        result = numpy.zeros(N, dtype=self.dtype)
        for i in xrange(N):
            ref0 = self.old_index[i]
            rel1 = -1
            rel2 = -1
            rel3 = -1
            distance = 0
            angle = 0
            dihed = 0
            if i > 0:
                ref1 = self._get_new_ref([ref0])
                distance = numpy.linalg.norm(coordinates[ref0]-coordinates[ref1])
                rel1 = i - self.new_index[ref1]
            if i > 1:
                ref2 = self._get_new_ref([ref0, ref1])
                angle, = ic.bend_angle(coordinates[[ref0, ref1, ref2]])
                rel2 = i - self.new_index[ref2]
            if i > 2:
                ref3 = self._get_new_ref([ref0, ref1, ref2])
                dihed, = ic.dihed_angle(coordinates[[ref0, ref1, ref2, ref3]])
                rel3 = i - self.new_index[ref3]
            result[i] = (self.graph.numbers[i], distance, rel1, angle, rel2, dihed, rel3)
        return result
Example #4
0
 def cart_to_zmat(self, coordinates):
     N = len(self.graph.numbers)
     result = numpy.zeros(N, dtype=self.dtype)
     for i in xrange(N):
         ref0 = self.old_index[i]
         rel1 = -1
         rel2 = -1
         rel3 = -1
         distance = 0
         angle = 0
         dihed = 0
         if i > 0:
             ref1 = self.get_new_ref([ref0])
             distance = numpy.linalg.norm(coordinates[ref0] -
                                          coordinates[ref1])
             rel1 = i - self.new_index[ref1]
         if i > 1:
             ref2 = self.get_new_ref([ref0, ref1])
             angle, = ic.bend_angle(coordinates[ref0], coordinates[ref1],
                                    coordinates[ref2])
             rel2 = i - self.new_index[ref2]
         if i > 2:
             ref3 = self.get_new_ref([ref0, ref1, ref2])
             dihed, = ic.dihed_angle(coordinates[ref0], coordinates[ref1],
                                     coordinates[ref2], coordinates[ref3])
             rel3 = i - self.new_index[ref3]
         result[i] = (self.graph.numbers[i], distance, rel1, angle, rel2,
                      dihed, rel3)
     return result
Example #5
0
def test_dihedral_ethene():
    mol = Molecule.from_file("input/ethene.xyz")
    c = mol.coordinates.copy()
    assert abs(ic.dihed_cos([c[2], c[0], c[3], c[5]])[0] - 1.0) < 1e-5
    assert abs(ic.dihed_angle([c[2], c[0], c[3], c[5]])[0]) < 1e-5
    for i in xrange(1000):
        angle = np.random.uniform(-np.pi, np.pi)
        radius = np.random.uniform(0, 5*angstrom)
        offset = np.random.uniform(0, 5*angstrom)
        c[5] = [
            offset,
            -radius*np.cos(angle),
            -radius*np.sin(angle),
        ]
        assert abs(ic.dihed_cos([c[2], c[0], c[3], c[5]])[0] - np.cos(angle)) < 1e-5
        assert abs(ic.dihed_angle([c[2], c[0], c[3], c[5]])[0] - angle) < 1e-5
Example #6
0
def test_dihedral_ethene():
    mol = Molecule.from_file(context.get_fn("test/ethene.xyz"))
    c = mol.coordinates.copy()
    assert abs(ic.dihed_cos([c[2], c[0], c[3], c[5]])[0] - 1.0) < 1e-5
    assert abs(ic.dihed_angle([c[2], c[0], c[3], c[5]])[0]) < 1e-5
    for i in xrange(1000):
        angle = np.random.uniform(-np.pi, np.pi)
        radius = np.random.uniform(0, 5 * angstrom)
        offset = np.random.uniform(0, 5 * angstrom)
        c[5] = [
            offset,
            -radius * np.cos(angle),
            -radius * np.sin(angle),
        ]
        assert abs(ic.dihed_cos([c[2], c[0], c[3], c[5]])[0] -
                   np.cos(angle)) < 1e-5
        assert abs(ic.dihed_angle([c[2], c[0], c[3], c[5]])[0] - angle) < 1e-5
Example #7
0
def test_dihedral_ethene():
    mol = Molecule.from_file(
        pkg_resources.resource_filename(__name__, "../data/test/ethene.xyz"))
    c = mol.coordinates.copy()
    assert abs(ic.dihed_cos([c[2], c[0], c[3], c[5]])[0] - 1.0) < 1e-5
    assert abs(ic.dihed_angle([c[2], c[0], c[3], c[5]])[0]) < 1e-5
    for i in range(1000):
        angle = np.random.uniform(-np.pi, np.pi)
        radius = np.random.uniform(0, 5 * angstrom)
        offset = np.random.uniform(0, 5 * angstrom)
        c[5] = [
            offset,
            -radius * np.cos(angle),
            -radius * np.sin(angle),
        ]
        assert abs(ic.dihed_cos([c[2], c[0], c[3], c[5]])[0] -
                   np.cos(angle)) < 1e-5
        assert abs(ic.dihed_angle([c[2], c[0], c[3], c[5]])[0] - angle) < 1e-5
Example #8
0
def get_dihedral_angle(term, system):
    dihed = term.get_atoms()
    if system.cell.nvec > 0:
        d10 = system.pos[dihed[0]] - system.pos[dihed[1]]
        d12 = system.pos[dihed[2]] - system.pos[dihed[1]]
        d23 = system.pos[dihed[3]] - system.pos[dihed[2]]
        system.cell.mic(d10)
        system.cell.mic(d12)
        system.cell.mic(d23)
        return _dihed_angle_low(d10, d12, d23, 0)[0]
    else:
        rs = np.array([system.pos[j] for j in dihed])
        return dihed_angle(rs)[0]
Example #9
0
def get_dihedral_angle(term, system):
    dihed = term.get_atoms()
    if system.cell.nvec>0:
        d10 = system.pos[dihed[0]] - system.pos[dihed[1]]
        d12 = system.pos[dihed[2]] - system.pos[dihed[1]]
        d23 = system.pos[dihed[3]] - system.pos[dihed[2]]
        system.cell.mic(d10)
        system.cell.mic(d12)
        system.cell.mic(d23)
        return _dihed_angle_low(d10, d12, d23, 0)[0]
    else:
        rs = np.array([system.pos[j] for j in dihed])
        return dihed_angle(rs)[0]
Example #10
0
    def init_part_fun(self, nma, partf):
        """See :meth:`tamkin.partf.StatFys.init_part_fun`"""
        if nma.periodic:
            raise NotImplementedError("Rotors in periodic systems are not supported yet")

        self.center = nma.coordinates[self.rot_scan.dihedral[1]]
        self.axis = nma.coordinates[self.rot_scan.dihedral[2]] - self.center
        self.axis /= numpy.linalg.norm(self.axis)
        self.moment, self.reduced_moment = compute_moments(
            nma.coordinates, nma.masses3, self.center, self.axis, self.rot_scan.top_indexes
        )
        if self.large_fixed:
            moment = self.moment
        else:
            moment = self.reduced_moment
        from molmod.ic import dihed_angle
        self.nma_angle = dihed_angle(nma.coordinates[self.rot_scan.dihedral])[0]
        # the energy levels
        if self.rot_scan.potential is None:
            # free rotor
            self.energy_levels = numpy.zeros(self.num_levels, float)
            for i in xrange(self.num_levels-1):
                index = i/2+1
                self.energy_levels[i+1] = index**2/(2*moment)
            self.hb = None
            self.v_coeffs = None
            self.v_ref = 0.0
        else:
            # hindered rotor
            self.hb = HarmonicBasis(self.num_levels, 2*numpy.pi)
            angles, energies = self.potential

            self.v_coeffs = self.hb.fit_fn(angles, energies, self.dofmax,
                self.rotsym, self.even, self.v_threshold)
            self.energy_levels = self.hb.solve(moment, self.v_coeffs)
            self.energy_levels = self.energy_levels[:self.num_levels]

        # the cancelation frequency based on the scan
        if self.cancel_freq == 'scan':
            force_constant = self.hb.eval_deriv2(numpy.array([self.nma_angle]), self.v_coeffs)[0]
            self.cancel_freq = numpy.sqrt(force_constant/moment)/(2*numpy.pi)

        # scaling factors
        self.freq_scaling = partf.vibrational.freq_scaling
        self.zp_scaling = partf.vibrational.zp_scaling
        self.classical = partf.vibrational.classical
Example #11
0
    def cart_to_zmat(self, coordinates):
        """Convert cartesian coordinates to ZMatrix format

           Argument:
             coordinates  --  Cartesian coordinates (numpy array Nx3)

           The coordinates must match with the graph that was used to initialize
           the ZMatrixGenerator object.
        """
        N = len(self.graph.numbers)
        if coordinates.shape != (N, 3):
            raise ValueError("The shape of the coordinates must be (%i, 3)" %
                             N)
        result = np.zeros(N, dtype=self.dtype)
        for i in range(N):
            ref0 = self.old_index[i]
            rel1 = -1
            rel2 = -1
            rel3 = -1
            distance = 0
            angle = 0
            dihed = 0
            if i > 0:
                ref1 = self._get_new_ref([ref0])
                distance = np.linalg.norm(coordinates[ref0] -
                                          coordinates[ref1])
                rel1 = i - self.new_index[ref1]
            if i > 1:
                ref2 = self._get_new_ref([ref0, ref1])
                angle, = ic.bend_angle(coordinates[[ref0, ref1, ref2]])
                rel2 = i - self.new_index[ref2]
            if i > 2:
                ref3 = self._get_new_ref([ref0, ref1, ref2])
                dihed, = ic.dihed_angle(coordinates[[ref0, ref1, ref2, ref3]])
                rel3 = i - self.new_index[ref3]
            result[i] = (self.graph.numbers[i], distance, rel1, angle, rel2,
                         dihed, rel3)
        return result
Example #12
0
    def init_part_fun(self, nma, partf):
        """See :meth:`tamkin.partf.StatFys.init_part_fun`"""
        if nma.periodic:
            raise NotImplementedError(
                "Rotors in periodic systems are not supported yet")

        self.center = nma.coordinates[self.rot_scan.dihedral[1]]
        self.axis = nma.coordinates[self.rot_scan.dihedral[2]] - self.center
        self.axis /= np.linalg.norm(self.axis)
        self.moment, self.reduced_moment = compute_moments(
            nma.coordinates, nma.masses3, self.center, self.axis,
            self.rot_scan.top_indexes)
        if self.large_fixed:
            moment = self.moment
        else:
            moment = self.reduced_moment
        from molmod.ic import dihed_angle
        self.nma_angle = dihed_angle(
            nma.coordinates[self.rot_scan.dihedral])[0]
        # the energy levels
        if self.rot_scan.potential is None:
            # free rotor
            self.energy_levels = np.zeros(self.num_levels, float)
            for i in xrange(self.num_levels - 1):
                index = i / 2 + 1
                self.energy_levels[i + 1] = index**2 / (2 * moment)
            self.hb = None
            self.v_coeffs = None
            self.v_ref = 0.0
        else:
            # hindered rotor
            self.hb = HarmonicBasis(self.num_levels, 2 * np.pi)
            angles, energies = self.potential

            self.v_coeffs = self.hb.fit_fn(angles, energies, self.dofmax,
                                           self.rotsym, self.even,
                                           self.v_threshold)
            self.energy_levels = self.hb.solve(moment, self.v_coeffs)
            self.energy_levels = self.energy_levels[:self.num_levels]

        # the cancelation frequency based on the scan
        if self.hb is None:
            if not isinstance(self.cancel_freq, float):
                raise ValueError(
                    'No cancelation frequency was computed for rotor "%s"' %
                    self.name)
        else:
            force_constant = self.hb.eval_deriv2(np.array([self.nma_angle]),
                                                 self.v_coeffs)[0]
            scan_cancel_freq = np.sqrt(force_constant / moment) / (2 * np.pi)
            if self.cancel_freq == 'scan':
                self.cancel_freq = scan_cancel_freq
            elif abs(self.cancel_freq -
                     scan_cancel_freq) > 0.3 * abs(self.cancel_freq):
                print 'WARNING: The cancelation frequency of rotor "%s" obtained with MBH (%.1f cm^-1) deviates a lot from the one derived from the scan (%.1f cm^-1).' % (
                    self.name, self.cancel_freq /
                    (lightspeed / centimeter), scan_cancel_freq /
                    (lightspeed / centimeter))

        # print a warning is the cancelation frequency is rather high.
        if self.cancel_freq > 500 * (lightspeed / centimeter):
            print 'WARNING: the cancelation frequency of rotor "%s" is rather high: %.1f cm^-1.' % (
                self.name, self.cancel_freq / (lightspeed / centimeter))
        elif self.cancel_freq <= 0:
            print 'WARNING: the cancelation frequency of rotor "%s" is negative: %.1f cm^-1.' % (
                self.name, self.cancel_freq / (lightspeed / centimeter))

        # scaling factors
        self.freq_scaling = partf.vibrational.freq_scaling
        self.zp_scaling = partf.vibrational.zp_scaling
        self.classical = partf.vibrational.classical
Example #13
0
 def dihedral(self, *atoms):
     ''' IUPAC sign convention'''
     return ic.dihed_angle([self.coordinates[i]
                            for i in atoms])[0] / units.deg
Example #14
0
 def dihedral(self, *atoms):
     ''' IUPAC sign convention'''
     return ic.dihed_angle([self.coordinates[i]
                            for i in atoms])[0] / units.deg
Example #15
0
    mol = Molecule.from_file(filename)

    # setup stuff
    mol.set_default_graph()
    mol.set_default_symbols()

    return mol


if __name__ == "__main__":
    # initialize molecule
    mol = setup("1IRA_R_B_clean.pdb")

    # all bonds of degree 3
    for bond in kth_bonds(mol, 3):
        # find the coordinates of the bonds
        bond_coor = list(map(lambda x: mol.coordinates[x], bond))

        # print symbols of bond and bond angle in degrees
        to_print = [bond]+symbolify(mol, bond)+[bend_angle(bond_coor)[0]/deg]
        pretty(to_print, "\t")

    # all bonds of degree 4
    for bond in kth_bonds(mol, 4):
        # find the coordinates of the bonds
        bond_coor = list(map(lambda x: mol.coordinates[x], bond))

        # print symbols of bond and dihed angle in degrees
        to_print = [bond]+symbolify(mol, bond)+[dihed_angle(bond_coor)[0]/deg]
        pretty(to_print, "\t")
Example #16
0
    def init_dihedral_terms(self, thresshold=20 * deg):
        '''
            Initialize the dihedral potentials from the local topology. The
            dihedral potential will be one of the two following possibilities:

                The multiplicity m is determined from the local topology, i.e.
                the number of neighbors of the central two atoms in the dihedral

                If the equilibrium value of all instances of the torsion are
                within `thresshold` of 0 deg or per/2 with per = 180deg/m,
                the following potential will be chosen:

                    0.5*K*(1-cos(m*psi-m*psi0)) with psi0 = 0 or 360/(2*m)
        '''
        with log.section('VAL', 3, 'Initializing'):
            #get all dihedrals
            from molmod.ic import dihed_angle, _dihed_angle_low
            ffatypes = [
                self.system.ffatypes[fid] for fid in self.system.ffatype_ids
            ]
            dihedrals = {}
            for dihedral in self.system.iter_dihedrals():
                dihedral, types = term_sort_atypes(ffatypes, dihedral,
                                                   'dihedral')
                if types in dihedrals.keys():
                    dihedrals[types].append(dihedral)
                else:
                    dihedrals[types] = [dihedral]
            #loop over all distinct dihedral types
            ncos = 0
            for types, diheds in dihedrals.iteritems():
                psi0s = np.zeros(len(diheds), float)
                ms = np.zeros(len(diheds), float)
                for i, dihed in enumerate(diheds):
                    if self.system.cell.nvec > 0:
                        d10 = self.system.pos[dihed[0]] - self.system.pos[
                            dihed[1]]
                        d12 = self.system.pos[dihed[2]] - self.system.pos[
                            dihed[1]]
                        d23 = self.system.pos[dihed[3]] - self.system.pos[
                            dihed[2]]
                        self.system.cell.mic(d10)
                        self.system.cell.mic(d12)
                        self.system.cell.mic(d23)
                        psi0s[i] = _dihed_angle_low(d10, d12, d23, 0)[0]
                    else:
                        rs = np.array([self.system.pos[j] for j in dihed])
                        psi0s[i] = dihed_angle(rs)[0]
                    n1 = len(self.system.neighs1[dihed[1]])
                    n2 = len(self.system.neighs1[dihed[2]])
                    ms[i] = get_multiplicity(n1, n2)
                nan = False
                for m in ms:
                    if np.isnan(m): nan = True
                if nan or None in ms or ms.std() > 1e-3:
                    ms_string = str(ms)
                    if nan: ms_string = 'nan'
                    log.warning('missing dihedral for %s (m is %s)' %
                                ('.'.join(types), ms_string))
                    continue
                m = int(np.round(ms.mean()))
                rv = get_restvalue(psi0s, m, thresshold=thresshold, mode=1)
                if rv is not None:
                    #a regular Cosine term is used for the dihedral potential
                    for dihed in diheds:
                        term = self.add_term(Cosine, [DihedAngle(*dihed)],
                                             types, ['HC_FC_DIAG'],
                                             ['au', 'kjmol', 'deg'])
                        self.set_params(term.index, rv0=rv, m=m)
                        ncos += 1
                else:
                    #no dihedral potential could be determine, hence it is ignored
                    log.warning(
                        'missing dihedral for %s (could not determine rest value from %s)'
                        % ('.'.join(types), str(psi0s / deg)))
                    continue
        log.dump('Added %i Cosine dihedral terms' % ncos)
Example #17
0
    def init_part_fun(self, nma, partf):
        """See :meth:`tamkin.partf.StatFys.init_part_fun`"""
        if nma.periodic:
            raise NotImplementedError("Rotors in periodic systems are not supported yet")

        self.center = nma.coordinates[self.rot_scan.dihedral[1]]
        self.axis = nma.coordinates[self.rot_scan.dihedral[2]] - self.center
        self.axis /= np.linalg.norm(self.axis)
        self.moment, self.reduced_moment = compute_moments(
            nma.coordinates, nma.masses3, self.center, self.axis, self.rot_scan.top_indexes
        )
        if self.large_fixed:
            moment = self.moment
        else:
            moment = self.reduced_moment
        from molmod.ic import dihed_angle
        self.nma_angle = dihed_angle(nma.coordinates[self.rot_scan.dihedral])[0]
        # the energy levels
        if self.rot_scan.potential is None:
            # free rotor
            self.energy_levels = np.zeros(self.num_levels, float)
            for i in xrange(self.num_levels-1):
                index = i/2+1
                self.energy_levels[i+1] = index**2/(2*moment)
            self.hb = None
            self.v_coeffs = None
            self.v_ref = 0.0
        else:
            # hindered rotor
            self.hb = HarmonicBasis(self.num_levels, 2*np.pi)
            angles, energies = self.potential

            self.v_coeffs = self.hb.fit_fn(angles, energies, self.dofmax,
                self.rotsym, self.even, self.v_threshold)
            self.energy_levels = self.hb.solve(moment, self.v_coeffs)
            self.energy_levels = self.energy_levels[:self.num_levels]

        # the cancelation frequency based on the scan
        if self.hb is None:
            if not isinstance(self.cancel_freq, float):
                raise ValueError('No cancelation frequency was computed for rotor "%s"' % self.name)
        else:
            force_constant = self.hb.eval_deriv2(np.array([self.nma_angle]), self.v_coeffs)[0]
            scan_cancel_freq = np.sqrt(force_constant/moment)/(2*np.pi)
            if self.cancel_freq == 'scan':
                self.cancel_freq = scan_cancel_freq
            elif abs(self.cancel_freq - scan_cancel_freq) > 0.3*abs(self.cancel_freq):
                print 'WARNING: The cancelation frequency of rotor "%s" obtained with MBH (%.1f cm^-1) deviates a lot from the one derived from the scan (%.1f cm^-1).' % (
                    self.name, self.cancel_freq/(lightspeed/centimeter), scan_cancel_freq/(lightspeed/centimeter)
                )

        # print a warning is the cancelation frequency is rather high.
        if self.cancel_freq > 500*(lightspeed/centimeter):
            print 'WARNING: the cancelation frequency of rotor "%s" is rather high: %.1f cm^-1.' % (
                self.name, self.cancel_freq/(lightspeed/centimeter)
            )
        elif self.cancel_freq <= 0:
            print 'WARNING: the cancelation frequency of rotor "%s" is negative: %.1f cm^-1.' % (
                self.name, self.cancel_freq/(lightspeed/centimeter)
            )


        # scaling factors
        self.freq_scaling = partf.vibrational.freq_scaling
        self.zp_scaling = partf.vibrational.zp_scaling
        self.classical = partf.vibrational.classical