def pi_metal(mol1, mol2, cutoff = 5, tolerance = 30): """Returns pairs of ring-metal atoms, which meet pi-metal criteria Parameters ---------- mol1, mol2 : oddt.toolkit.Molecule object Molecules to compute ring-metal pairs cutoff : float, (default=5) Distance cutoff for Pi-metal pairs tolerance : int, (default=30) Range (+/- tolerance) from perfect direction (perpendicular) in which pi-metal are considered as strict. Returns ------- r1 : ring_dict-type numpy array Aligned rings forming pi-metal m : atom_dict-type numpy array Aligned metals forming pi-metal strict_parallel : numpy array, dtype=bool Boolean array align with ring-metal pairs, informing whether they form 'strict' pi-metal. If false, only distance cutoff is met, therefore the interaction is 'crude'. """ r1, m = close_contacts(mol1.ring_dict, mol2.atom_dict[mol2.atom_dict['ismetal']], cutoff, x_column='centroid') if len(r1) > 0 and len(m) > 0: angle1 = angle_2v(r1['vector'], m['coords'] - r1['centroid']) strict = (angle1 > 180 - tolerance) | (angle1 < tolerance) return r1, m, strict else: return r1, m, np.array([], dtype=bool)
def pi_stacking(mol1, mol2, cutoff = 5, tolerance = 30): """Returns pairs of rings, which meet pi stacking criteria Parameters ---------- mol1, mol2 : oddt.toolkit.Molecule object Molecules to compute ring pairs cutoff : float, (default=5) Distance cutoff for Pi-stacking pairs tolerance : int, (default=30) Range (+/- tolerance) from perfect direction (parallel or perpendicular) in which pi-stackings are considered as strict. Returns ------- r1, r2 : ring_dict-type numpy array Aligned arrays of rings forming pi-stacking strict_parallel : numpy array, dtype=bool Boolean array align with ring pairs, informing whether rings form 'strict' parallel pi-stacking. If false, only distance cutoff is met, therefore the stacking is 'crude'. strict_perpendicular : numpy array, dtype=bool Boolean array align with ring pairs, informing whether rings form 'strict' perpendicular pi-stacking (T-shaped, T-face, etc.). If false, only distance cutoff is met, therefore the stacking is 'crude'. """ r1, r2 = close_contacts(mol1.ring_dict, mol2.ring_dict, cutoff, x_column = 'centroid', y_column = 'centroid') if len(r1) > 0 and len(r2) > 0: angle1 = angle_2v(r1['vector'],r2['vector']) angle2 = angle(r1['vector'] + r1['centroid'],r1['centroid'], r2['centroid']) strict_parallel = ((angle1 > 180 - tolerance) | (angle1 < tolerance)) & ((angle2 > 180 - tolerance) | (angle2 < tolerance)) strict_perpendicular = ((angle1 > 90 - tolerance) & (angle1 < 90 + tolerance)) & ((angle2 > 180 - tolerance) | (angle2 < tolerance)) return r1, r2, strict_parallel, strict_perpendicular else: return r1, r2, np.array([], dtype=bool), np.array([], dtype=bool)
def pi_cation(mol1, mol2, cutoff=5, tolerance=30, cation_exact=False): """Returns pairs of ring-cation atoms, which meet pi-cation criteria Parameters ---------- mol1, mol2 : oddt.toolkit.Molecule object Molecules to compute ring-cation pairs cutoff : float, (default=5) Distance cutoff for Pi-cation pairs tolerance : int, (default=30) Range (+/- tolerance) from perfect direction (perpendicular) in which pi-cation are considered as strict. cation_exact : bool Requires interacting atoms to have non-zero formal charge. Returns ------- r1 : ring_dict-type numpy array Aligned rings forming pi-stacking plus2 : atom_dict-type numpy array Aligned cations forming pi-cation strict_parallel : numpy array, dtype=bool Boolean array align with ring-cation pairs, informing whether they form 'strict' pi-cation. If false, only distance cutoff is met, therefore the interaction is 'crude'. """ cation_map = mol2.atom_dict['isplus'] if cation_exact: cation_map = cation_map & (mol2.atom_dict['formalcharge'] > 0) r1, plus2 = close_contacts(mol1.ring_dict, mol2.atom_dict[cation_map], cutoff, x_column='centroid') if len(r1) > 0 and len(plus2) > 0: angle1 = angle_2v(r1['vector'], plus2['coords'] - r1['centroid']) ideal_angle = 30 # angle to normal vector strict = (((angle1 > ideal_angle - tolerance) & (angle1 < ideal_angle + tolerance)) | ((angle1 > 180 - ideal_angle - tolerance) & (angle1 < 180 - ideal_angle + tolerance))) return r1, plus2, strict else: return r1, plus2, np.array([], dtype=bool)