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)
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 ]