Beispiel #1
0
def test_points_on_sphere():

    points = geom.get_points_on_sphere(n_points=4)

    # 4 points on a sphere equally spaced should be roughly √2 apart
    assert len(points) == 4
    assert np.abs(np.linalg.norm(points[0] - points[1]) - np.sqrt(2)) < 1E-6

    points = geom.get_points_on_sphere(n_points=2)
    # The algorithm isn't great at generated small numbers of points so 2 -> 3

    # 3 points on a sphere equally spaced should be roughly the diameter
    assert len(points) == 3
    assert np.abs(np.linalg.norm(points[0] - points[1]) - np.sqrt(3)) < 1E-6
Beispiel #2
0
    def _generate_conformers(self):
        """
        Generate rigid body conformers of a complex by (1) Fixing the first m
        olecule, (2) initialising the second molecule's COM evenly on the points
        of a sphere around the first with a random rotation and (3) iterating
        until all molecules in the complex have been added
        """
        if len(self.molecules) < 2:
            # Single (or zero) molecule complex only has a single *rigid body*
            # conformer
            self.conformers = [get_conformer(name=self.name, species=self)]

            return None

        n_molecules = len(self.molecules)  # Number of molecules in the complex
        self.conformers = []
        n = 0  # Current conformer number

        points_on_sphere = get_points_on_sphere(
            n_points=Config.num_complex_sphere_points)

        for _ in iterprod(range(Config.num_complex_random_rotations),
                          repeat=n_molecules - 1):
            # Generate the rotation thetas and axes
            rotations = [
                np.random.uniform(-np.pi, np.pi, size=4)
                for _ in range(n_molecules - 1)
            ]

            for points in iterprod(points_on_sphere, repeat=n_molecules - 1):

                conformer = get_conformer(species=self,
                                          name=f'{self.name}_conf{n}')
                atoms = get_complex_conformer_atoms(self.molecules, rotations,
                                                    points)
                conformer.set_atoms(atoms)

                self.conformers.append(conformer)
                n += 1

                if n == Config.max_num_complex_conformers:
                    logger.warning(
                        f'Generated the maximum number of complex conformers ({n})'
                    )
                    return None

        logger.info(f'Generated {n} conformers')
        return None
Beispiel #3
0
    def get_active_atom_neighbour_lists(self, mol, depth):
        """
        Get neighbour lists of all the active atoms in the molecule
        (reactant complex)

        Arguments:
            mol (autode.species.Species):
            depth (int): Depth of the neighbour list to consider

        Returns:
            (list(list(int))):
        """
        connected_molecules = connected_components(mol.graph)
        n_molecules = len(connected_molecules)

        def shift_molecules(vectors):
            for i, molecule_nodes in enumerate(connected_molecules):
                for j in molecule_nodes:
                    mol.atoms[j].translate(vec=vectors[i])

        # For every molecule in the complex shift so they are far away, thus
        # the neighbour lists only include atoms in the same molecule
        vecs = get_points_on_sphere(n_points=n_molecules + 1)
        shift_vectors = [100 * vec for vec in vecs]

        shift_molecules(vectors=shift_vectors)

        # Calculate the neighbour lists while the molecules are all far away
        def nl(atom):
            return get_neighbour_list(species=mol, atom_i=atom)[:depth]

        if self.active_atom_nl is None:
            self.active_atom_nl = [nl(atom) for atom in self.active_atoms]

        # Shift the molecules back to where they were
        shift_molecules(vectors=[-vector for vector in shift_vectors])

        return self.active_atom_nl