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)
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
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
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
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
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
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
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]
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]
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
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
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
def dihedral(self, *atoms): ''' IUPAC sign convention''' return ic.dihed_angle([self.coordinates[i] for i in atoms])[0] / units.deg
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")
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)
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