def test_generates_correct_connected_shells_level1(self): from e3fp.fingerprint import fprinter from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) conf = mol.GetConformers()[0] atoms = list(range(3)) bonds_dict = {0: {1, 2}, 1: {0}, 2: {0}} for atom in atoms: conf.SetAtomPosition(atom, [0, 0, .45 * atom]) expected_shells_dict = { 0: Shell(0, {1}), 1: Shell(1, {0}), 2: Shell(2, {}) } with mock.patch('e3fp.fingerprint.fprinter.bound_atoms_from_mol', return_value=bonds_dict): shells_gen = fprinter.ShellsGenerator(conf, atoms, radius_multiplier=0.5, include_disconnected=False) for i in range(2): shells_dict = next(shells_gen) self.assertDictEqual(shells_dict, expected_shells_dict)
def test_stereo_indicators_for_frame(self): from e3fp.fingerprint.fprinter import stereo_indicators_from_shell from e3fp.fingerprint.array_ops import project_to_plane,\ make_transform_matrix,\ transform_array from e3fp.fingerprint.structs import Shell shell = Shell(0, {1, 2, 3}) atom_coords = np.asarray([[0, 0, 0.], [1, -0.5, 0.], [0, 2., 0.], # -> y [0, 0, 3.]], # -> z dtype=np.float) atom_tuples = [(1, 1, Shell(2)), # -> y (2, 1, Shell(1)), (5, 5, Shell(3))] # -> z for i in range(20): rand_trans = np.random.uniform(size=3)*100 rand_y = np.random.uniform(size=3)*10 rand_v = np.random.uniform(size=3)*20 rand_z = project_to_plane(rand_v, rand_y)*30 rand_transform_mat = make_transform_matrix(np.zeros(3), rand_y, rand_z) new_coords = transform_array(rand_transform_mat, atom_coords) np.testing.assert_almost_equal( atom_coords, transform_array( np.linalg.inv(rand_transform_mat), new_coords)) new_coords += rand_trans atom_coords_dict = dict(list(zip(list(range(4)), new_coords))) stereo_ind = stereo_indicators_from_shell(shell, atom_tuples, atom_coords_dict) # 2 is chosen for y, 3 for z expect_stereo_ind = [1, -5, 2] self.assertEqual(stereo_ind, expect_stereo_ind)
def test_stereo_sets_correct_transform_matrix(self): from e3fp.fingerprint.fprinter import stereo_indicators_from_shell from e3fp.fingerprint.array_ops import project_to_plane, \ make_transform_matrix, \ transform_array from e3fp.fingerprint.structs import Shell shell = Shell(0, {1, 2}) atom_coords = np.asarray([[0, 0, 0.], [0, 2., 0.], # -> y [0, 0, 3.]], # -> z dtype=np.float) atom_tuples = [(1, 1, Shell(1)), # -> y (5, 5, Shell(2))] # -> z for i in range(20): rand_trans = np.random.uniform(size=3)*100 rand_y = np.random.uniform(size=3)*10 rand_v = np.random.uniform(size=3)*20 rand_z = project_to_plane(rand_v, rand_y)*30 rand_transform_mat = make_transform_matrix(np.zeros(3), rand_y, rand_z) trans_mat = np.identity(4, dtype=np.float) trans_mat[:3, 3] = rand_trans rand_transform_mat = np.dot(trans_mat, rand_transform_mat) new_coords = transform_array(rand_transform_mat, atom_coords) reverse_trans_mat = np.linalg.inv(rand_transform_mat) np.testing.assert_almost_equal( atom_coords, transform_array(reverse_trans_mat, new_coords)) atom_coords_dict = dict(list(zip(list(range(3)), new_coords))) stereo_indicators_from_shell(shell, atom_tuples, atom_coords_dict) np.testing.assert_almost_equal(shell.transform_matrix, reverse_trans_mat)
def test_shells_diff_center_same_atoms_nonequal(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) shell1 = Shell(atoms[0], atoms[2:]) shell2 = Shell(atoms[1], atoms[2:]) self.assertNotEqual(shell1, shell2)
def test_creation_with_atoms_or_ids_equivalent(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) atom_ids = [x.GetIdx() for x in atoms] self.assertEqual(Shell(atoms[0], atoms[1:]), Shell(atom_ids[0], atom_ids[1:]))
def test_shell_creation_from_substruct_without_center_fails(self): from e3fp.fingerprint.structs import Shell, Substruct, FormatError from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) substruct = Substruct(None, atoms[:2]) with self.assertRaises(FormatError): Shell.from_substruct(substruct)
def test_equal_shells_hash_to_same_value(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) center_atom = atoms[0] shell1 = Shell(center_atom, atoms[1:]) shell2 = Shell(center_atom, atoms[1:]) self.assertEqual(hash(shell1), hash(shell2))
def test_creation_with_atoms_or_shells_equal(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) shells = list(map(Shell, atoms)) center_atom = atoms[0] shell1 = Shell(center_atom, atoms[1:]) shell2 = Shell(center_atom, shells[1:]) self.assertEqual(shell1, shell2)
def test_generates_correct_disconnected_shells_level0(self): from e3fp.fingerprint.fprinter import ShellsGenerator from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) conf = mol.GetConformers()[0] atoms = list(range(3)) expected_shells_dict = {0: Shell(0), 1: Shell(1), 2: Shell(2)} shells_gen = ShellsGenerator(conf, atoms) shells_dict = next(shells_gen) self.assertDictEqual(shells_dict, expected_shells_dict)
def test_recursive_atom_shells_correct(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) shell1 = Shell(atoms[5], atoms[6:8]) shell2 = Shell(atoms[2], atoms[3:5]) shell = Shell(atoms[0], (shell1, shell2)) self.assertEqual(shell.atoms, {x.GetIdx() for x in (atoms[0], atoms[2], atoms[5])})
def test_no_unique_y_two_evenly_spaced_correct(self): from e3fp.fingerprint.fprinter import stereo_indicators_from_shell from e3fp.fingerprint.structs import Shell shell = Shell(0, {1, 2}) atom_coords_dict = {0: [0, 0, 0], 1: [0, 1, 0], 2: [0, 0, 1]} atom_tuples = [(1, 1, Shell(1)), (1, 1, Shell(2))] stereo_ind = stereo_indicators_from_shell(shell, atom_tuples, atom_coords_dict) # mean should be between 1 and 2, so z cannot be picked, so all 0. expect_stereo_ind = [1, 2] self.assertEqual(stereo_ind, expect_stereo_ind)
def test_recursive_shell_substruct_correct2(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) shell1 = Shell(atoms[1], atoms[2:5]) shell2 = Shell(atoms[5], {shell1}) shell3 = Shell(atoms[6], atoms[7:10]) shell4 = Shell(atoms[10], {shell3}) shell = Shell(atoms[0], (shell2, shell4)) self.assertEqual(shell.substruct.atoms, {x.GetIdx() for x in atoms[:11]})
def test_no_unique_y_along_poles_correct(self): from e3fp.fingerprint.fprinter import stereo_indicators_from_shell from e3fp.fingerprint.structs import Shell shell = Shell(0, {1, 2, 3}) atom_coords_dict = {0: [0, 0, 0], 1: [0, 1, 0], 2: [0, -5, 0], 3: [0, -10, 0]} atom_tuples = [(1, 1, Shell(1)), (1, 1, Shell(2)), (1, 1, Shell(3))] stereo_ind = stereo_indicators_from_shell(shell, atom_tuples, atom_coords_dict) # mean should be along atom 2/3, so z not be picked, but all at poles. expect_stereo_ind = [-1, 1, 1] self.assertEqual(stereo_ind, expect_stereo_ind)
def test_create_shell_no_shell(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) center_atom = atoms[0] Shell(center_atom)
def test_generates_correct_disconnected_shells_level1(self): from e3fp.fingerprint.fprinter import ShellsGenerator from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) conf = mol.GetConformers()[0] atoms = list(range(3)) for atom in atoms: conf.SetAtomPosition(atom, [0, 0, .45*atom]) expected_shells_dict = {0: Shell(0, {1}), 1: Shell(1, {0, 2}), 2: Shell(2, {1})} shells_gen = ShellsGenerator(conf, atoms, radius_multiplier=0.5, include_disconnected=True) for i in range(2): shells_dict = next(shells_gen) self.assertDictEqual(shells_dict, expected_shells_dict)
def test_error_when_shells_has_non_shell(self): from e3fp.fingerprint.structs import Shell atom = 0 shells = [None] with self.assertRaises(TypeError): Shell(atom, shells)
def test_substruct_creation_from_shell(self): from e3fp.fingerprint.structs import Shell, Substruct from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) shell = Shell(atoms[0], atoms[1:]) substruct = Substruct.from_shell(shell) self.assertEqual(shell.substruct, substruct)
def test_create_shell_with_same_center_fails(self): from e3fp.fingerprint.structs import Shell, FormatError from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) center_atom = atoms[0] with self.assertRaises(FormatError): Shell(center_atom, atoms)
def test_no_neighbors_transform_matrix_is_translate(self): from e3fp.fingerprint.fprinter import stereo_indicators_from_shell from e3fp.fingerprint.structs import Shell shell = Shell(0) center_coord = np.random.uniform(3) stereo_indicators_from_shell(shell, [], {0: center_coord}) np.testing.assert_almost_equal(shell.transform_matrix[:3, 3], -center_coord)
def test_atoms_converted_to_shells(self): from e3fp.fingerprint.structs import Shell from e3fp.conformer.util import mol_from_sdf mol = mol_from_sdf(PLANAR_SDF_FILE) atoms = list(mol.GetAtoms()) center_atom = atoms[0] shell = Shell(center_atom, atoms[1:]) for s in shell.shells: self.assertIsInstance(s, Shell)
def test_empty_tuples_returns_empty(self): from e3fp.fingerprint.fprinter import stereo_indicators_from_shell from e3fp.fingerprint.structs import Shell shell = Shell(0, {}) atom_coords_dict = {0: np.random.uniform(size=3)} atom_tuples = [] stereo_ind = stereo_indicators_from_shell(shell, atom_tuples, atom_coords_dict) self.assertEqual(len(stereo_ind), 0)
def test_error_when_center_not_atom(self): from e3fp.fingerprint.structs import Shell with self.assertRaises(TypeError): Shell(None)