Esempio n. 1
0
class MolecularGraphics:
    def __init__(self, coordinates, interaction_manager):
        self.viewer = QtViewer()
        self.selected_atom = 0
        self.active = True
        self.coordinates = None
        self.atoms = None
        self.bonds = None
        self.interaction_manager = interaction_manager

        self.viewer.widget.on_mouse.append(self.select)

        try:
            self.update(coordinates, interaction_manager)
            if len(coordinates) != len(self.atoms):
                raise Exception(
                    "Atom List does not correspond to coordinate array")

        except Exception as e:
            self.disable(e)

    def select(self, mouse_vector):
        closest_index = None
        closest_dist = 100
        for index, atom in enumerate(self.coordinates):
            dist = np.linalg.norm(mouse_vector[:2] - atom[:2])
            if dist < closest_dist:
                closest_index = index
                closest_dist = dist

        mouse_vector[2] = 0
        self.selected_atom = closest_index
        self.coordinates[0] = mouse_vector
        print(mouse_vector)
        self.update(self.coordinates, self.interaction_manager)

    """
    def scroll_atom(self):
        self.selected_atom += 1
        self.selected_atom %= len(self.interaction_manager.atoms)
        #print(self.selected_atom)
        self.update(self.coordinates, self.interaction_manager)
    """

    def update_coordinates(self, coordinates):
        self.coordinates = coordinates
        if self.active:
            try:

                self.renderer.update_positions(scale * coordinates)
                self.viewer.widget.update()
            except Exception as e:
                self.disable(e)

    def disable(self, e):
        raise e
        input(
            "Exception occured in graphics handler. Graphics will henceforth be disabled:"
        )
        self.active = False

    def run(self, iterfunction):
        if self.active:
            try:
                self.viewer.schedule(iterfunction)
                self.viewer.run()
            except Exception as e:
                self.disable(e)
        if not self.active:
            while True:
                iterfunction()

    def update(self, coordinates, interaction_manager):
        self.coordinates = coordinates
        self.interaction_manager = interaction_manager
        self.atoms = interaction_manager.atoms
        self.bonds = interaction_manager.bonds
        if self.active:
            try:
                bond_colors = np.array([
                    bond_colors_dict[bond.inferred_by] for bond in self.bonds
                ])
                interactions = []
                interaction_colors = []

                for x in [1, 3, 6]:
                    new_interaction_list = interaction_manager.get_all_interaction_atoms(
                        x)
                    new_interaction_indices = [[
                        y[0].index_value, y[1].index_value
                    ] for y in new_interaction_list]

                    interactions += new_interaction_indices
                    interaction_colors += [interaction_colors_dict[x]
                                           ] * len(new_interaction_indices)

                self.viewer.clear()

                type_array = [
                    atom.atom_type for atom in interaction_manager.atoms
                ]
                atom_colors = []
                for index, atom in enumerate(interaction_manager.atoms):
                    if atom.get_free_valency(
                    ) != 0 and atom.atom_type in atom_colors_dict and self.selected_atom != index:
                        atom_colors.append(atom_colors_dict[atom.atom_type])
                    elif index == self.selected_atom:
                        atom_colors.append([57, 255, 20, 255])
                    else:
                        atom_colors.append(default_atom_map[atom.atom_type])

                self.renderer = self.viewer.add_renderer(
                    MyBallAndStickRenderer, scale * coordinates,
                    np.array(type_array), np.array(atom_colors),
                    np.array([bond.get_indices() for bond in self.bonds]),
                    bond_colors, np.array(interactions),
                    np.array(interaction_colors))
            except Exception as e:
                self.disable(e)
Esempio n. 2
0
class ChemLabMinimiser:
    def __init__(self):
        self.interaction_manager = get_interaction_manager(
            *get_twod_signal_manager().get_interaction_data())
        im = self.interaction_manager.interaction_matrix
        im[19][6] = 0
        im[19][7] = 0
        """
        for x in [9,10,11,12,13,17,18,19,20,21]:
            for y in range(self.interaction_manager.number_atoms):
                if im[x][y] == 3:
                    im[x][y] = 0
                    im[y][x] = 0

        """

        self.interaction_matrix = self.interaction_manager.interaction_matrix
        self.type_array = self.interaction_manager.type_array
        self.shift_data = self.interaction_manager.shift_data
        self.number_atoms = self.interaction_manager.number_atoms
        self.global_bond_indices = self.interaction_manager.bonds
        self.bond_orders = self.interaction_manager.bond_orders
        self.viewer = QtViewer()
        self.best_response_value = 1000000.0
        ac = np.random.rand(self.number_atoms, 3) * 0.001
        #ac = FileManager().read_numpy_from_xyz('manual2.xyz') * 0.1
        self.iteration_number = 0
        self.coordinate_manager = CoordinateManager(self, ac,
                                                    self.interaction_manager)
        self.fragments = self.generate_fragments_list()
        print(self.coordinate_manager.calculate_response_value(True))
        self.interaction_manager.print_matrix()
        input("")

        self.delay = 0
        """
        for x in [0,1,2,3,4,5]:
            self.interaction_manager.interaction_matrix[self.interaction_manager.interaction_matrix==x] = 9
        """
        self.nullfrag = Fragment([], [], [], [], self.viewer,
                                 self.coordinate_manager,
                                 self.interaction_manager, [])

    def generate_fragments_list(self):
        """
        Creates a list of fragment objects
        """

        self.calculate_valencies()

        fragments = []
        fragment_data = self.generate_fragment_groups()
        for fragment_piece in fragment_data:
            global_indices = fragment_piece['global indices']
            global_bond_indices = fragment_piece['global bond indices']
            local_bond_indices = np.array(
                [[global_indices.index(x[0]),
                  global_indices.index(x[1])] for x in global_bond_indices])
            bond_orders = fragment_piece['bond orders']
            fragment = Fragment(global_indices, global_bond_indices,
                                local_bond_indices, bond_orders, self.viewer,
                                self.coordinate_manager,
                                self.interaction_manager, self.free_valencies)
            fragments.append(fragment)
        return fragments

    def calculate_valencies(self):
        valencies = {"H": 1, "C": 4, "N": 4}
        self.free_valencies = [
            valencies[x] for x in self.interaction_manager.type_array
        ]
        for bond in self.global_bond_indices:
            self.free_valencies[bond[0]] -= 1
            self.free_valencies[bond[1]] -= 1
        for i, shift in enumerate(self.shift_data):
            if 100 < shift < 160:
                self.free_valencies[i] -= 1
        self.fix_types()

    def fix_types(self):
        for index, type in enumerate(self.type_array):
            if self.free_valencies[index] == 0 and self.type_array[
                    index] == "C":
                self.type_array[index] = "N"

    def fix_renderers(self):
        self.viewer.clear()
        for fragment in self.fragments:
            fragment.set_renderer()

    def generate_fragment_groups(self):
        fragment_groups = []
        unselected = [x for x in range(self.number_atoms)]
        while len(unselected) > 0:
            new_atoms = set()
            new_atoms.add(unselected[0])
            atoms = []
            new_bonds = []
            new_bond_orders = []
            while len(new_atoms) > 0:
                a = list(new_atoms)[0]
                atoms.append(a)
                new_atoms.remove(a)
                for bond_index, bond in enumerate(self.global_bond_indices):
                    if atoms[-1] == bond[0] and bond[1] not in atoms:
                        new_atoms.add(bond[1])
                    if atoms[-1] == bond[1] and bond[0] not in atoms:
                        new_atoms.add(bond[0])
                    if a in bond and list(bond) not in new_bonds:
                        new_bonds.append(list(bond))
                        new_bond_orders.append(self.bond_orders[bond_index])
            atoms.sort()
            fragment_piece = dict()
            fragment_piece["global indices"] = atoms
            fragment_piece["global bond indices"] = new_bonds
            fragment_piece["bond orders"] = new_bond_orders
            fragment_groups.append(fragment_piece)
            unselected = [
                x for x in range(self.number_atoms)
                if x not in sum([y["global indices"]
                                 for y in fragment_groups], [])
            ]
        return fragment_groups

    def main(self):
        #self.interaction_manager.interaction_matrix[self.interaction_manager.interaction_matrix==1] = 0
        #self.interaction_manager.interaction_matrix[self.interaction_manager.interaction_matrix==2] = 0

        print(self.coordinate_manager.calculate_response_value(True))
        self.viewer.schedule(self.iteration2)
        self.viewer.run()

    def iteration2(self):
        atom_coordinates = self.coordinate_manager.get_coordinates()
        hmbcs = []
        for x1 in range(len(atom_coordinates)):
            for x2 in range(len(atom_coordinates)):
                if self.interaction_matrix[x1][x2] == 3:
                    hmbcs.append([x1, x2])
        for frag1 in self.fragments:
            for frag2 in self.fragments:
                for hmbc in hmbcs:
                    a = hmbc[0] in frag1.global_indices and hmbc[
                        1] in frag2.global_bond_indices
                    b = hmbc[1] in frag1.global_indices and hmbc[
                        0] in frag2.global_bond_indices
                    if not (a and b):
                        continue
                    hmbc.sort()
                    if self.type_array[hmbc[0]] == "H":
                        bond = [
                            x for x in self.global_bond_indices if hmbc[0] in x
                        ][0]
                        carbon_index = max(bond)
                        if self.free_valencies[carbon_index] != 0:
                            continue
                        else:
                            adjacent_carbons = [[
                                y for y in x if y != carbon_index
                                and self.free_valencies[y] != 0
                            ][0] for x in self.global_bond_indices
                                                if carbon_index in x]
                            if len(adjacent_carbons) == 1:
                                self.merge(
                                    frag1,
                                    frag2,
                                )

                                self.global_bond_indices.append(
                                    adjacent_carbons[0], hmbc[1])

    def iteration(self):
        self.iteration_number += 1
        if self.iteration_number < 2500:
            self.optimise_substructures()
        else:
            self.form_new_bonds()

    def optimise_substructures(self):
        for fragment in self.fragments:
            fragment.start_iter()
            fragment.rotate_bonds(sequence=1)
            fragment.rotate_bonds(sequence=1)
            fragment.verify()
            fragment.start_iter()
            fragment.translate()
            fragment.verify()

            fragment.update_graphics()

    def form_new_bonds(self):

        fragment1 = random.choice(self.fragments)

        shortest_bond = None
        closest_fragment = None
        shortest_distance = 1000

        atom_coordinates = self.coordinate_manager.get_coordinates()

        for fragment2 in self.fragments:
            if fragment1 != fragment2 or len(self.fragments) == 1:
                for i1 in fragment1.global_indices:
                    for i2 in fragment2.global_indices:
                        frag1_atom = atom_coordinates[i1]
                        frag2_atom = atom_coordinates[i2]
                        if np.linalg.norm(frag2_atom -
                                          frag1_atom) < shortest_distance:
                            if self.free_valencies[
                                    i1] > 0 and self.free_valencies[
                                        i2] > 0 and self.checkHMBC(
                                            i1, i2, fragment1, fragment2):
                                if not (fragment1.has_hydrogens[i1]
                                        and fragment1.has_hydrogens[i2]):
                                    shortest_bond = [i1, i2]
                                    shortest_distance = np.linalg.norm(
                                        frag2_atom - frag1_atom)
                                    closest_fragment = fragment2

        if closest_fragment == None:
            return
        else:
            self.iteration_number = 0
            self.coordinate_manager.reset()

        self.interaction_manager.interaction_matrix[i1][i2] = 4
        self.interaction_manager.interaction_matrix[i2][i1] = 4
        if len(self.fragments) > 1:
            self.merge(fragment1, closest_fragment, shortest_bond)
        else:

            self.merge(fragment1, self.nullfrag, shortest_bond)

        self.coordinate_manager.reset()
        for fragment in self.fragments:
            fragment.project_bond_lengths()

    def merge(self, fragment1, fragment2, shortest_bond):
        """
        Creates a list of fragment objects
        """

        global_indices = fragment1.global_indices + fragment2.global_indices
        self.global_bond_indices.append(shortest_bond)
        self.calculate_valencies()
        global_bond_indices = fragment1.global_bond_indices + fragment2.global_bond_indices + [
            shortest_bond
        ]
        local_bond_indices = np.array(
            [[global_indices.index(x[0]),
              global_indices.index(x[1])] for x in global_bond_indices])
        bond_orders = fragment1.bond_orders + fragment2.bond_orders

        self.fix_types()
        self.fix_renderers()

        fragment = Fragment(global_indices, global_bond_indices,
                            local_bond_indices, bond_orders, self.viewer,
                            self.coordinate_manager, self.interaction_manager,
                            self.free_valencies)
        self.viewer.clear()
        if fragment1 in self.fragments:
            self.fragments.remove(fragment1)
        if fragment2 in self.fragments:
            self.fragments.remove(fragment2)
        self.fragments.append(fragment)
        self.calculate_valencies()
        for fragment in self.fragments:
            fragment.set_renderer()

        return fragment

    def checkHMBC(self, i1, i2, frag1, frag2):
        return True

        all_bonds = frag1.global_bond_indices + frag2.global_bond_indices + [[
            i1, i2
        ]]

        all_indices = list(set(sum(all_bonds, [])))

        i1_hmbcs = [
            x for x in range(0, self.number_atoms)
            if self.interaction_matrix[i1][x] == 3 and x in all_indices
        ]

        one_bond_gap = []
        for bond in all_bonds:
            if i1 in bond:
                if i1 == bond[0]:
                    one_bond_gap.append(bond[1])
                else:
                    one_bond_gap.append(bond[0])

        two_bond_gap = []
        for index in one_bond_gap:
            for bond in all_bonds:
                if index in bond and index not in one_bond_gap and index != i1:
                    if index == bond[0]:
                        two_bond_gap.append(bond[1])
                    else:
                        two_bond_gap.append(bond[0])

        three_bond_gap = []
        for index in two_bond_gap:
            for bond in all_bonds:
                if index in bond and index not in one_bond_gap and index not in two_bond_gap and index != i1:
                    if index == bond[0]:
                        three_bond_gap.append(bond[1])
                    else:
                        three_bond_gap.append(bond[0])

        delta_indices = [
            x for x in i1_hmbcs if x not in two_bond_gap + three_bond_gap
        ]
        if len(delta_indices) > 0:
            print(delta_indices)
            return False
        else:
            return True

        i2_hmbcs = [
            x for x in range(0, self.number_atoms)
            if self.interaction_matrix[i2][x] == 3 and x in all_indices
        ]