def to_cml(self): ''' Creates a cml molecule element Uses the original (i.e. non-aromatised) ''' original_bonds = self.bonds for each_tuple in self.aromatised_bonds: i, j, k = each_tuple original_bonds[i][j] = k original_bonds[j][i] = k root = ET.Element(lbl_molecule) atom_array = ET.Element(lbl_atom_array) for each in self.atoms: atom_array.append(each.to_cml()) root.append(atom_array) bond_array = ET.Element(lbl_bond_array) for i_idx, i in enumerate(original_bonds): for j_idx, j in enumerate(i): if j and (i_idx > j_idx): bond = ET.Element(lbl_bond) bond.set(lbl_order, str(j)) bond.set(lbl_atom_refs, ' '.join([py_to_id(l) for l in [i_idx, j_idx]])) bond_array.append(bond) root.append(bond_array) return ET.tostring(root)
def set_torsion(self, id1, id2, id3, id4, torsion): ''' Rotates atom 1 and all its children aound that atom2-atom3 bond so that the 1-2-3-4 torsion is the supplied value (in radians) ''' # Start by finding the children of atom 2(all closer to it than atom 3) children = [] for idx, i in enumerate(self.distances): if i[id2] < i[id3]: children.append(idx) at2 = self.atoms[id2] axis = at2.get_vector(self.atoms[id3]) angle = self.get_torsion(id1, id2, id3, id4) - torsion matrix = linalg.rotation_axis_angle(axis, angle) back_again = at2.coords there = [-1 * i for i in back_again] for at_idx in children: at = self.atoms[at_idx] at.translate(there) c = at.coords.transpose() new_c = matrix.dot(c) at.coords = new_c.transpose() at.translate(back_again) d = self.get_torsion(id1, id2, id3, id4) try: assert abs(sin(d) - sin(torsion)) < 1e-3 assert abs(cos(d) - cos(torsion)) < 1e-3 except AssertionError: msg = 'Failed to set torsion %s' %'->'.join([py_to_id(i) for i in (id1, id2, id3, id4)]) msg += '\n Should be %f, is %f' %(degrees(torsion), degrees(d)) raise RuntimeError(msg)