def do_dirty(self): """ TODO: Find a better way to detect movement of pseudoatom: Do_position? / Save last positon and only call do move if it actually moved TODO STRUC: Move this out to a provider function. The GUI handling program should not deal with special cases for certain selction types. Returns ------- """ print('dirty', mv=0) self.redraw() # only for debugging if isinstance(self.logic_handler.my_selection, SphericalSelection): if not self.check_objects_exists('SphericalSelection'): self.provide_services_to_spherical_selection() # Find the coordinates of the Spherical selection coords = [None] self.cmd.iterate_state(-1, selection='SphericalSelection', expression='coords[0]=(x,y,z)', space=locals()) x, y, z = coords[0] self.trigger_event(program_states.EventType.MOVE, new_x=x, new_y=y, new_z=z)
def _atom_list_to_pymol_selection(atom_list: t.List[u.Atom]) -> str: """ atom_list_to_pymol_selection converts a List of Atoms to a string that pymool can understand. @warning Pymol can only handle a string with a length of ca 1000. (ca 200 atoms.) Consider using help_pymol_with_big_atoms_List Parameters ---------- atom_list : t.List[u.Atom] A List of Atoms Returns ------- str A interface_Pymol selection expression, containing all those Atoms """ selection_expression: str = "ID " if len(atom_list) > 0 else 'none' for a in atom_list: selection_expression += str(a.id) + "," if (len(selection_expression)) > 1000: print( 'WARNING in _atom_list_to_pymol_selection. Pymol can not handle selection expression with more than ca 200 Atoms. Consider using help_pymol_with_big_atom_list', mv=3) return selection_expression
def _update_select(self, new_atoms: t.List[u.Atom]): """ _update_select should be overridden by every subclass of _Selection that wants to be notified when new atoms have been selected/marked in the GUI LimitedSelection.update () only accepts one molecule in new_atoms at a time. :param new_atoms: List of atom selection that has been added since last updated :type new_atoms: t.List :param display_function: :type display_function: :return: - :rtype: - """ if self.has_finished: return if (len(new_atoms) > 1): print( 'WARNING: LimitedSelection.update(...) has been called with more than one atom in its new_atoms List.', mv=4) print(" Only the fist Atom of the List is added: ", new_atoms[0], mv=4) new_atom = new_atoms[0] if new_atom in self.atoms: self.atoms.remove(new_atom) else: self.atoms.append(new_atom) self.has_finished = len(self.atoms) >= self.max_size
def _set_restraint_type(self, new_restraint_type: t.Type[Restraints._Restraint]): ''' _set_restraint_type changes the current type of Restraint. :warning: Should only be called via set_action_type which handles type checking :param new_restraint_type: A type of restraint :type new_restraint_type: type[Restraint._Restraint} :return: None :rtype: None :raises: TypeError if new_restraint_type is not in available_restraint_types ''' if new_restraint_type == None: self.current_restraint_type = None self.my_restraint = None return if not new_restraint_type in self.available_restraint_types + [None]: raise TypeError(str(new_restraint_type) + ' is not an available type of Restraint') print("SET TYPE: " + str(new_restraint_type)) self.current_restraint_type = new_restraint_type # self.current_restraint_type.accepted_selection_types_atoms if(self.atom_or_restraint_mode) else # Set the Selection type to the preferred selection of this restraint type. set_mode will deactivate the selection, button, so it cant be changed # TODO: In theory a restraint could accept several selection types. Would be nice to give the user the possibilitz to choose between all of them # TODO: If the first selection in the list is e.g a Limited selection the user will be asked for input. At a moment I just check for all lists that that is not the case. # Would be nicer if there was a way to pass an input function that does not require user input in this context self.set_action_states() self.available_selection_types = self.current_restraint_type.accepted_selection_types_atoms if(self.atom_or_restraint_mode) else self.current_restraint_type.accepted_selection_types_res self._set_selection_type(self.available_selection_types[0]) self.available_optimizer_types = self.current_restraint_type.accepted_optimizer_types self.available_exporter_types = self.current_restraint_type.accepted_exporter_types self.available_importer_types = self.current_restraint_type.accepted_importer_types
def _inner_colorize_4(): time_step = const_time_max / 100 cols = [] cmd.iterate_state(state=-1, selection=_atom_list_to_pymol_selection(atoms), expression='cols.append(ID)', space=locals) print(cols, mv=1)
def _inner_colorize_2(): time_step = const_time_max / 100 for i in range(1, 100): __a = str(100 - i) __b = 'gray' + __a.zfill(2) print(__b) cmd.color(color=__b, selection=_atom_list_to_pymol_selection(atoms)) time.sleep(time_step / 1000)
def import_restraints(self, verbose: bool = False) -> t.List[dict]: """ This function reads in a gromos distance restraint file. TODO: Read in additional Settings (r0, w0, etc...) TODO: WE could try to read thefile in get_args to get the Error there already. IDEA: READ THE WHOLE TEXT IN GET ARGS AND ONLY CONVERT IT HERE. OS ALLERRORS HAPPEN IN GET ARGS Parameters ---------- verbose Returns ------- t.List[dict] returns a dict containing the atom ids for each disres. (has to be translated in interface_Pymol """ restraint_objects = [ ] # Define before try_block, so we can return the empty list in case of errors try: tmp_file_content = json.load(open(self.in_path, "r")) # Analogous new version for i, restraint in tmp_file_content.items(): if verbose: print(restraint) atom1 = u.find_atom_by_property(self.all_atoms, restraint['a1']['id']) atomRef = u.find_atom_by_property(self.all_atoms, restraint['aR']['id']) new_restraint = Restraints.PositionRestraint( atomA=atom1, reference_atom=atomRef) restraint_objects.append(new_restraint) # PRINT RESULTS for i_r, r in enumerate(restraint_objects): print('PositionRestraint', str(i_r), ': Atom1_ID:', str(r.atoms[0].id), 'AtomR_ID:', str(r.reference_atom.id)) except FileNotFoundError: print("Error: Could not find the file: \'" + self.in_path + "\'", mv=4) except KeyError: print("Error: Could not read the file: " + self.in_path, mv=4) except ImportError: print( "BAD ERROR: FAILED TO IMPORT THE MODULES NECESSARY FOR IMPORTING AND EXPORTING JSON FILES!", mv=4) if (len(restraint_objects) == 0): warnings.warn("Could not find any Restraint in file: " + str(self.in_path)) return restraint_objects
def _ok_button_pressed(): '''iterate over all input fields and add their value to answers''' for field in dial.children(): # field = lay.itemAt(i) if isinstance(field, QtWidgets.QLineEdit): answers.append(field.text()) elif isinstance(field, QtWidgets.QComboBox): answers.append(field.currentText()) # else: QLabel etc => Do nothing dial.close() print(answers, mv=1)
def write(self, path): """ Args: path: """ file = open(path, "w") file.write(self.__str__()) file.flush() file.close() print("New file generated: " + path) return path
def do_special(self, k, x, y, mod): """ control special actions of the keyboard Parameters ---------- k : int pressed key x : int coordinate x y : float coordinate y mod : int pressed shift? Returns ------- None """ print('special') if self.logic_handler.my_selection == None or self.logic_handler.my_selection.has_finished: return if k == 102: # right - arrow key self.trigger_event(program_states.EventType.SIZE, increase=True) # increase = True if hasattr(self.logic_handler.my_selection, 'radius' ): # if it is Spherical Selection increase sphere size self.cmd.set('sphere_scale', self.logic_handler.my_selection.radius, selection='SphericalSelection') elif k == 100: # left - arrow key self.trigger_event(program_states.EventType.SIZE, increase=False) # increase = False if hasattr(self.logic_handler.my_selection, 'radius' ): # if it is Spherical Selection reduce sphere size self.cmd.set('sphere_scale', self.logic_handler.my_selection.radius, selection='SphericalSelection') elif k == 101: # + -key self.cmd.controlling.button('Left', 'None', 'MovA') elif k == 103: # down - key self.cmd.controlling.button('Left', 'None', 'Rota') if k == 101 and mod == 1: # up + Shift - keys self.trigger_event(program_states.EventType.CONFIRM) self.cmd.controlling.button('Left', 'None', 'Rota') self.cmd.controlling.unmask('all') self.cmd.delete('SphericalSelection') self.logic_handler._set_selection_type(None)
def add_block(self, blocktitle: str, content: dict, verbose: bool = False): """ Args: blocktitle (str): content (dict): verbose (bool): """ if blocktitle in self.block_names: if blocktitle == "TITLE": self.title_block = blocks.title_block(content) self.blocksset.append(blocktitle) else: try: content = {k.split("(")[0]: v for k, v in content.items()} content = {k.split(":")[0]: v for k, v in content.items()} content = {k.split(" ")[0]: v for k, v in content.items()} self.__setattr__(self.block_names.get(blocktitle), blocks.__getattribute__(self.block_names.get(blocktitle))(**content)) self.blocksset.append(blocktitle) except: print("Error while adding new value - can not resolve value names in \'" + blocktitle + "\' block!") print("Content is " + str(content)) print("Block knows " + str( (blocks.__getattribute__(self.block_names.get(blocktitle)).__init__.__code__.co_varnames)[1:])) exit(1) else: print(" Warning while adding new block \'" + blocktitle + "\' - can not resolve \'" + blocktitle + "\'\n" + " -> Block will be skipped!") return 0
def read_disres_file(self, path: str): # parse file into dicts """ Args: path (str): """ data = self.parse_disres_file(path) # convert distance_res lines to objects data["DISTANCERESSPEC"]["RESTRAINTS"] = list( map(lambda x: blocks.atom_pair_distanceRes(**x), data["DISTANCERESSPEC"]["RESTRAINTS"])) # add blocks as attribute to objects for key, sub_content in data.items(): print(sub_content) self.add_block(blocktitle=key, content=sub_content)
def update(self): """ general update function Returns ------- NoReturn """ print( "EXECUTING MCS Selection: please Wait - this can take a bit longer.", mv=5) mcs_ids = Rdkit_Functions.mcs_selection(self.molecules_rdk) self.atoms = list(filter(lambda a: a.id in mcs_ids, self.all_atoms)) self.has_finished = True print("EXECUTING MCS Selection: DONE", mv=5)
def _check_optimzer_results_pairwise_5(self, exit_test_mode=False): '''Creates groups for all pairs which are connected. And show them all in grid mode :warning: only designed for pairwise restraints ''' self.check_results_mode = 5 # 1) Check which molecule pairs have connections pair_exists = {} for i_m1 in range(len(self.pymol_molecule_objects)): for i_m2 in range(len(self.pymol_molecule_objects)): pair_exists.update({str(i_m1 + 1) + str(i_m2 + 1): False}) for r in self.logic_handler.selected_restraints: pair_exists.update({str(r.atoms[0].resi) + str(r.atoms[1].resi): True}) mol_pairs = [(str(i_m1 + 1), str(i_m2 + 1)) for i_m1 in range(len(self.pymol_molecule_objects) - 1) for i_m2 in range(i_m1, len(self.pymol_molecule_objects)) if pair_exists[str(i_m1 + 1) + str(i_m2 + 1)] or pair_exists[str(i_m2 + 1) + str(i_m1 + 1)]] print(mol_pairs, mv=1) cmd.disable('all') for p in mol_pairs: m1, m2 = p[0], p[1] m1_name = m1 + '-' + m2 + 'mol_' + m1 m2_name = m1 + '-' + m2 + 'mol_' + m2 cmd.copy(m1 + '-' + m2 + 'mol_' + m1, 'mol_' + m1) cmd.copy(m1 + '-' + m2 + 'mol_' + m2, 'mol_' + m2) group_expression = m1_name + ' ' + m2_name cmd.group('pair_' + m1 + '_' + m2, group_expression) cmd.enable(group_expression) cmd.set('grid_mode', 1) cmd.reset() if (exit_test_mode): self.check_results_mode = 0 for p in mol_pairs: m1_name = m1 + '-' + m2 + 'mol_' + m1 m2_name = m1 + '-' + m2 + 'mol_' + m2 group_expression = m1_name + ' ' + m2_name cmd.delete(m1_name) cmd.delete(m2_name) cmd.ungroup('group_expression') cmd.set('grid_mode', 0) cmd.enable('all')
def _read_disres_subblock(blocks): result_data = {} for block in blocks: if (block == "TITLE"): result_data.update({block: blocks[block]}) elif (block == "DISTANCERESSPEC"): subcontent = {} restrains = [] current_block = blocks[block] # readout KDISH or KDISC keys = current_block[0].replace("#", "").strip().split() values = current_block[1].split() subcontent.update({key: values[keys.index(key)] for key in keys}) # read list header: line_header = current_block[2].replace("#", "").split() ##unify keys: key_dict = {"i": 1, "j": 1, "k": 1, "l": 1, "type": 1} renamed_header = [] for x in line_header: if (x in key_dict): renamed_header.append(x + str(key_dict[x])) key_dict[x] += 1 else: renamed_header.append(x) line_header = renamed_header # read restraints for line in current_block[3:]: if (not line.startswith("#") and len(line.split()) == len(line_header)): values = line.split() restrains.append({key: values[line_header.index(key)] for key in line_header}) # print(restrains) elif (line.startswith("#")): continue else: print("WARNING! could not Read in :" + line) continue subcontent.update({"RESTRAINTHEADER": line_header}) subcontent.update({"RESTRAINTS": restrains}) result_data.update({block: subcontent}) else: raise IOError("DISRES parser does not know block: " + str(block) + "\n with content: " + "\n".join( blocks[block])) return result_data
def _get_mol_offset(selected_mol: Chem.Mol, mols: t.List[Chem.Mol]) -> int: """ determines the molecule offset """ # deal with offsets of ligands: mol_offset = 1 for mol in sorted(mols, key=lambda x: x.resi): if (selected_mol.name == mol.name): print("FOUND_MOLNAME: ", mol.name) break else: mol_offset += len(mol.GetAtoms()) else: raise ValueError( 'The molecule is not a member of the list of moleucles.') return mol_offset
def __init__(self, in_path: (str or dict) = None): """ Args: in_path: """ self.blocksset = [] self.block_names = {"TITLE": "title_block"} if type(in_path) is str: self.path = in_path elif (type(in_path) == dict): self.content = in_path self.path = None elif (in_path == None): print("WARNING!: generated empty gromosFileobj!") else: raise IOError("Gromos File Input path is not str, dict or None!")
def _optimzer_show_next_molecule_pair_3(self): ''' Only for debugging and testing. :return: :rtype: ''' molecules = (self.cmd.get_object_list()) color = ['orange', 'green', 'magenta', 'brown'] self.redraw() # TODO: There also seems to be a self.cmd.redraw attribute. => Change name of my function to avoid confusion self.cmd.hide('spheres', 'all') self.cmd.disable('all') m1 = self._to3_i_m + 1 # convert ot counting from 1 to n, instead of 0 to n-1 m2 = m1 + 1 if int(m1) != len(molecules) / 3 else '1' self.cmd.enable(str(m1) + '_prim') self.cmd.enable(str(m1) + '_shortest') self.cmd.enable(str(m1) + '_avg') self.cmd.enable(str(m2) + '_prim') self.cmd.enable(str(m2) + '_shortest') self.cmd.enable(str(m2) + '_avg') my_slice = slice(self._to3_n_restraints * self._to3_i_m, self._to3_n_restraints * (self._to3_i_m + 1)) for r_prim, r_shortest, r_avg in zip(self._prim_restraints[my_slice], self._shortest_restraints[my_slice], self._avg_restraints[my_slice]): col = color[self._prim_restraints.index(r_prim) % self._to3_n_restraints] self.cmd.color(col, pu._atom_list_to_pymol_selection(r_prim.atoms) + ' & ' + str( m1) + '_prim') # After using the create command the corresponding atoms have the same id => need to specify molecule self.cmd.color(col, pu._atom_list_to_pymol_selection(r_prim.atoms) + ' & ' + str(m2) + '_prim') self.cmd.color(col, pu._atom_list_to_pymol_selection(r_shortest.atoms) + ' & ' + str(m1) + '_shortest') self.cmd.color(col, pu._atom_list_to_pymol_selection(r_shortest.atoms) + ' & ' + str(m2) + '_shortest') self.cmd.color(col, pu._atom_list_to_pymol_selection(r_avg.atoms) + ' & ' + str(m1) + '_avg') self.cmd.color(col, pu._atom_list_to_pymol_selection(r_avg.atoms) + ' & ' + str(m2) + '_avg') self.cmd.show('spheres', pu._atom_list_to_pymol_selection(r_prim.atoms + r_shortest.atoms + r_avg.atoms)) print(pu._atom_list_to_pymol_selection(r_avg.atoms) + ' & m1_avg') self.cmd.reset() self.cmd.refresh()
def PolyArea(corners, title=""): # Shoelace formula#from plotly - print("small", corners) corners = PolygonSort(corners[:, :2]) print("Corners", corners) n = len(corners) # of corners area = 0.0 for i in range(n): j = (i + 1) % n area += corners[i][0] * corners[j][1] area -= corners[j][0] * corners[i][1] print("area", area) area = abs(area) / 2.0 return area
def timer(self, runs: int, func: t.Callable): '''Timer: Can be used''' t_start = time.time() for i in range(runs): func() t_end = time.time() # Correct for time of loop execution etc t_corr_start = time.time() for i in range(runs): pass t_corr_end = time.time() # TODO: Round to sign digits. No direct built in function in python upper = (t_end - t_start) / runs lower = ((t_end - t_start) - (t_corr_end - t_corr_start)) / runs print('Timer estimates:', min_verbosity=0) print(' Lower: ' + '%10.3e' % lower + ' s', min_verbosity=0) print(' Upper: ' + '%10.3e' % upper + ' s', min_verbosity=0)
def try_to_get_args(my_x, input_function) -> bool: """ wrapper function for get_args. Takes care of the error handling Parameters ---------- my_x : _Importer,_Restraint,_Selection,_Filter,_Optimzer or _Exporter An Object that should call get args input_function : t.Callable[str] The input_function argument of get_args Returns ------- bool Could get_args be executed without errors? """ failed = False try: my_x.get_args(input_function) except u.BadArgumentException as err: print('Failed to create a ' + my_x.__class__.__name__ + ' with the given arguments: \n' + str(err), mv=4) failed = True except IndexError: print('Did not receive enough arguments to create a ' + my_x.__class__.__name__, mv=4) failed = True except NotImplementedError: print(my_x.__class__.__name__ + 'has not been implemented', mv=4) failed = True # Do not expect Argumetn error that will ocurr if my_x does not have a get_args function. That is a fault that really should stop the program . => Leave it to standard error handling return not failed
def mcs_selection(mols: t.List[Chem.Mol], min_MCS_size: int = 6) -> t.List: """ The selection is getting only the MCS of pairwise molecules Warnings: results do not seem reasonable YET. TODO: Check what exactly is not going as expected Parameters ---------- mols: t.List[Chem.Mol] molecules min_MCS_size : what is the minimal MCS size verbose : bool loud and noisy Returns ------- List """ def _get_mol_offset(selected_mol: Chem.Mol, mols: t.List[Chem.Mol]) -> int: # deal with offsets of ligands: mol_offset = 1 for mol in sorted(mols, key=lambda x: x.resi): if (selected_mol.name == mol.name): # print("FOUND_MOLNAME: ", mol.name) break else: mol_offset += len(mol.GetAtoms()) return mol_offset # generate MCS out of tools_Rdkit mols: ## most common substructres print("Calculate MCS", mv=0) mcs = [[] for mol in mols] for ind1, mol1 in enumerate(mols): print(ind1) for ind2, mol2 in enumerate(mols): print("\t", ind2) if (mol1 == mol2): continue else: tmp_mcs = rdFMCS.FindMCS([mol1, mol2], ringMatchesRingOnly=True) mcs[ind1].append(tmp_mcs) mcs[ind2].append(tmp_mcs) print("MCS: got ", len(mcs), "\t aim ", len(mols) * len(mols), mv=1) ## convert result to smart strings and make these to new tools_Rdkit mols: smart_mols = [ Chem.MolFromSmarts(mcs_s.smartsString) for molecule_smarts in mcs for mcs_s in molecule_smarts ] print("SMARTS: got ", len(smart_mols), "\t aim ", len(mols) * len(mols), mv=1) # get atom nums of mcs_smart match for each row and col - Carefull there could be multiple matches! matching_atoms = [] mol_matrix = [mol2 for mol2 in mols for mol1 in mols if (mol1 != mol2)] # flattened mol matrix for mol, smart in zip(mol_matrix, smart_mols): substructre = mol.GetSubstructMatches(smart) print(substructre) matching_atoms.append(substructre) print("Matching Atoms: got ", len(matching_atoms), "\t aim ", len(mols) * len(mols), mv=1) print("MATRIX LENGHT: ", len(matching_atoms), mv=1) ##add offset to atom indices offset_added_mol_matches = [] for ind, mol_matches in enumerate(matching_atoms): offset_added_matches = [] print("MOL: ", ind // (len(mols) - 1), mv=1) for match in mol_matches: if (len(match) >= min_MCS_size): print("\t", match) offset = _get_mol_offset(mols[ind // (len(mols) - 1)], mols) offset_added_matches.extend( tuple(map(lambda x: x + offset, match))) else: continue offset_added_mol_matches.extend(offset_added_matches) print("MCS: got ", len(offset_added_matches), "\t aim ", len(mols) * len(mols), mv=1) print('len:', str(len(offset_added_mol_matches)), ' -', offset_added_mol_matches, mv=1) return offset_added_mol_matches
def ring_atom_filter(selected: list, mols: t.List[Chem.Mol], selected_mols: dict) -> t.List[int]: """ Filter molecules for rings and remove non-ring atoms from the selection Parameters ---------- mols: t.List[Chem.Mol] molecules to select from Returns ------- t.List[int] list of stil selected atom indices, inside a ring """ def _get_mol_offset(selected_mol: Chem.Mol, mols: t.List[Chem.Mol]) -> int: """ determines the molecule offset """ # deal with offsets of ligands: mol_offset = 1 for mol in sorted(mols, key=lambda x: x.resi): if (selected_mol.name == mol.name): print("FOUND_MOLNAME: ", mol.name) break else: mol_offset += len(mol.GetAtoms()) else: raise ValueError( 'The molecule is not a member of the list of moleucles.') return mol_offset already_selected_atomIdx = [] collect = [] for ind, mol in enumerate(mols): # deal with offsets: mol_offset = _get_mol_offset(selected_mol=mol, mols=mols) # print("Mol " + str(mol_ind) +" "+str(mol.name)+" has offset: " + str(mol_offset)) all_atoms = mol.GetAtoms() # print("All atoms:"+str([atom.GetIdx() for atom in all_atoms])) # get all ring atoms all_atoms_in_rings = list(filter(lambda x: x.IsInRing(), all_atoms)) print("all_atoms in rings: " + str([atom.GetIdx() for atom in all_atoms_in_rings])) # print out all ring atoms test = "" for atom in all_atoms_in_rings: test += str(mol_offset + atom.GetIdx()) + " " print("all ring Atoms +offset: " + str(test)) # reduce ring atoms by already selected atoms if len(already_selected_atomIdx) > 0: atoms_selected_in_rings = list( filter( lambda x: (x.GetIdx() + int(mol_offset)) in already_selected_atomIdx, all_atoms_in_rings)) else: atoms_selected_in_rings = all_atoms_in_rings # collect filtered atoms # print("only preselected atoms in rings+off"+str([mol_offset + atom.GetIdx() for atom in atoms_selected_in_rings])) collect += [ mol_offset + atom.GetIdx() for atom in atoms_selected_in_rings ] print("Finally Selected atoms: ", collect) return collect
def import_restraints(self, verbose: bool = False) -> t.List[dict]: """ ..function: import_restraints This function reads in a gromos distance restraint file. TODO: Read in additional Settings (r0, w0, etc...) Args: in_path (str): path to the disres file verbose (bool): shall I be loud and noisy? Returns: returns a dict containing the atom ids for each disres. (has to be translated in interface_Pymol t.List[dict]: :raises: TODO """ restraint_objects = [ ] # Define before try_block, so we can return the empty list in case of errors try: # TODO CLEAN IMPORT: WE should do this import in the beginning. It is extremley annoying, if you go through the whole program an the get an error because this import fails. Sam e with exporter import Files # readFiles disres_file = Files.Gromos_files.disres(self.in_path) if verbose: print(disres_file) if verbose: print("READ: " + "".join(disres_file["TITLE"])) # Analogous new version for restraint in disres_file.distance_res_spec_block.RESTRAINTS: if verbose: print(restraint) atom1 = self.find_atom_by_id(restraint.atom1i) atom2 = self.find_atom_by_id(restraint.atom2i) new_restraint = Restraint.Pair_Restraint(atoms=[atom1, atom2]) restraint_objects.append(new_restraint) # PRINT RESULTS for i_r, r in enumerate(restraint_objects): print('PairRestraint', str(i_r), ': Atom1_ID:', str(r.atoms[0].id), 'Atom2_ID:', str(r.atoms[1].id)) except FileNotFoundError: print("Error: Could not find the file: \'" + self.in_path + "\'", mv=4) except KeyError: print( "Error: Could not read the file: " + self.in_path, mv=4 ) # TODO: WE could try to read thefile in get_args to get the Error there already. IDEA: READ THE WHOLE TEXT IN GET ARGS AND ONLY CONVERT IT HERE. OS ALLERRORS HAPPEN IN GET ARGS except ImportError: print( "BAD ERROR: FAILED TO IMPORT THE MODULES NECESSARY FOR IMPORTING AND EXPORTING GROMOS FILES!", mv=4) return restraint_objects
def import_restraints(self, verbose: bool = True) -> t.List[dict]: """ This function reads in a gromos distance restraint file. TODO: Read in additional Settings (r0, w0, etc...) TODO: WE could try to read thefile in get_args to get the Error there already. IDEA: READ THE WHOLE TEXT IN GET ARGS AND ONLY CONVERT IT HERE. OS ALLERRORS HAPPEN IN GET ARGS Parameters ---------- verbose Returns ------- t.List[dict] returns a dict containing the atom ids for each disres. (has to be translated in interface_Pymol """ restraint_objects = [ ] # Define before try_block, so we can return the empty list in case of errors try: # readFiles from pygromos.files.coord.posres import Position_Restraints posres_file = Position_Restraints(self.in_path) if verbose: print(posres_file, mv=5) # Analogous new version for restraint in posres_file.POSRESSPEC: if verbose: print(restraint) atom1 = u.find_atom_by_property(self.all_atoms, restraint.atomID) new_restraint = Restraints.PositionRestraint(atomA=atom1) restraint_objects.append(new_restraint) # PRINT RESULTS for i_r, r in enumerate(restraint_objects): print('PairRestraint', str(i_r), ': Atom1_ID:', str(r.atomA.id)) except FileNotFoundError: print("Error: Could not find the file: \'" + self.in_path + "\'", mv=4) except KeyError: print("Error: Could not read the file: " + self.in_path, mv=4) except ImportError: print( "BAD ERROR: FAILED TO IMPORT THE MODULES NECESSARY FOR IMPORTING AND EXPORTING GROMOS FILES!", mv=4) if (len(restraint_objects) == 0): warnings.warn("Could not find any Restraint in file: " + str(self.in_path)) return restraint_objects
def export_restraints(self, verbose: bool = False) -> str: # TODO: Go through all the functions it calls to see where we would get a file error ''' export_restraints must be overridden by every subclass of Exporter. Writes the restraints into a file. For Gromos Exporter it will be in a gromos compatible format. :param verbose: print progress (True) or not (False) :type verbose: bool :return: - :rtype: None :raises FileNotFoundError ''' ##disres_file settings #todo: realise these parameters as settings dict, which the user can provide as input KDISH = 0.1 KDISC = 0.153 fullharm = 1 deviationdist = None general_dist = None # build_up clean disres file; # clean_restrains = data def build_pair_distance_restraints(self, restrain_atoms: t.List[dict], fullharm: int = 1, deviationdist=None, general_dist=None) -> list: # Can do it in two steps: 1)type = fullharm, deviationdist, generaldist, 2) value # check input if (fullharm == 0): if (deviationdist != None or general_dist != None): raise IOError( "Please use one option, fullharm, ddist or generaldist." ) elif (deviationdist != None): if (fullharm == 0 or general_dist != None): raise IOError( "Please use one option, fullharm, ddist or generaldist." ) elif (general_dist != None): if (deviationdist != None or fullharm == 0): raise IOError( "Please use one option, fullharm, ddist or generaldist." ) if (deviationdist == None): deviationdist = 0.0 restraint_dict = [] # TODO use zipto iterate over a1 and a2 directly for r in self.restraints: a1 = r.atoms[0] a2 = r.atoms[1] # TODO:Make distance an attribute of RestraintPair and set it once at creation. BUT THEN WE HAVE TO MAKE SUERE ATOMS ARE NOT CHANGE DAFTER THAT distance_A = sqrt((float(a1.x) - float(a2.x))**2 + (float(a1.y) - float(a2.y))**2 + (float(a1.z) - float(a2.z))**2) distance_nm = round(distance_A, 2) / 10 comment = "##\t" + a1.resn + "/" + a1.name + " " + str( a1.id) + " - " + a2.resn + "/" + a2.name + " " + str( a2.id) + "\n" distance = r.atoms new_entry = Files.Gromos_blocks.atom_pair_distanceRes( i1=a1.id, j1=0, k1=0, l1=0, type1=0, i2=a2.id, j2=0, k2=0, l2=0, type2=0, r0=distance_nm, w0=1.0, rah=fullharm, comment=comment) # print(new_entry) restraint_dict.append(new_entry) return restraint_dict disres_out = build_pair_distance_restraints( self, restrain_atoms=self.restraints, fullharm=fullharm, deviationdist=deviationdist) ##WRITE out disres.dat if verbose: print("generate out_dict") disres_out_dict = { "KDISH": KDISH, "KDISC": KDISC, "RESTRAINTHEADER": "i j k l type i j k l type r0 w0 rah".split(), # header "RESTRAINTS": disres_out } if verbose: print("generate top_disres obj") disres_file = Files.Gromos_files.disres() if verbose: print("top_disres obj add:") disres_file.add_block( blocktitle="TITLE", content="generated disres file for BRD4 with PYMOL wizard\n", verbose=True) # disres.write('/home/rhinerc/Desktop/testingRestraints_afterTitelBlock.disres') disres_file.add_block(blocktitle="DISTANCERESSPEC", content=disres_out_dict, verbose=verbose) # disres_file.write('/home/rhinerc/Desktop/testingRestraints_afterDISRESBLOCK.disres') # print(disres_out_dict,mv=1) disres_file.write(self.out_path) if verbose: print("wrote to: " + self.out_path) return str(disres_file)
def _calc_pca(coords, dims, verbose: bool = True): if (verbose): print("PCA: ") # center data: (scale) geometric_mean = np.mean(coords, axis=0) centered_coords = coords - geometric_mean # get covariance_matrix covaricance_matrix = np.cov(centered_coords.T) if (verbose): print("\tcovariance: \n\t", "\n\t ".join(map(str, list(covaricance_matrix)))) # eigenvalue decomp. => principle components eigen_values, eigen_vectors = np.linalg.eig(covaricance_matrix) if (verbose): print("\tPC: \n\t", "\n\t ".join(map(str, list(eigen_vectors)))) if (verbose): print("\teigenvalues: ", eigen_values) # SORT for size sorted_eigen = list( reversed(sorted(zip(eigen_values, eigen_vectors), key=lambda x: x[0]))) reduced_eigenvalues = [eigen[0] for eigen in sorted_eigen][:dims] if (verbose): print(sorted_eigen) # transform coordinates onto new coords. if (verbose): print("\tPC: \n\t", "\n\t ".join(map(str, list(eigen_vectors)))) transformed_coords = eigen_vectors.T.dot(centered_coords.T) reduced_transformed_coords = np.array([ transf_dim for transf_dim, eigen_val in zip(transformed_coords, eigen_values) if (eigen_val in reduced_eigenvalues) ]) if (verbose): print(reduced_transformed_coords) return reduced_transformed_coords, eigen_vectors, eigen_values, covaricance_matrix
def colorize(atoms): """ sets the pymol colors - FOOLING AROUND :) colorize_atoms: Some tests for different ways of colouring atoms. When using the predefinied names (e.g. "gray") PyMol raises a Quiet Error. With this method I can test, that Pymol does accept the different colour numbering schemes (s for spectrum, c for complementary etc.) Parameters ---------- atoms : Atoms Returns ------- """ try: const_time_max = 10000 print('inner1') def _inner_colorize_1(): time_max = const_time_max time_step = time_max / (3 * len(atoms)) while (time_max > 0): time_max -= time_step __a = atoms[random.randint(0, len(atoms) - 1)] __b = random.random() < 0.5 __c = random.randint(1, 999) __d = ('s' if __c else 'c') + str(__c) cmd.color(color=__d, selection=_atom_list_to_pymol_selection([__a])) time.sleep(time_step / 1000) print('inner2') def _inner_colorize_2(): time_step = const_time_max / 100 for i in range(1, 100): __a = str(100 - i) __b = 'gray' + __a.zfill(2) print(__b) cmd.color(color=__b, selection=_atom_list_to_pymol_selection(atoms)) time.sleep(time_step / 1000) print('inner3') def _inner_colorize_3(): time_max = const_time_max time_step = (time_max / len(atoms) * 3) cmd.color(color='white', selection=_atom_list_to_pymol_selection(atoms)) while (time_max > 0): time_max -= time_step __a = random.randint(0, len(atoms) - 1) cmd.color(color='red', selection=_atom_list_to_pymol_selection([atoms[__a] ])) time.sleep(time_step / 1000) def _inner_colorize_4(): time_step = const_time_max / 100 cols = [] cmd.iterate_state(state=-1, selection=_atom_list_to_pymol_selection(atoms), expression='cols.append(ID)', space=locals) print(cols, mv=1) inner_funcs = [ _inner_colorize_1, _inner_colorize_2, _inner_colorize_3, _inner_colorize_4 ] rand_i = random.randint(0, len(inner_funcs) - 1) my_thread = threading.Thread(target=inner_funcs[rand_i]) my_thread.start() except: pass
def export_restraints(self, verbose: bool = True) -> str: """ export_restraints must be overridden by every subclass of Exporter. Writes the restraints into a file. For Gromos Exporter it will be in a gromos compatible format. todo: realise these parameters as settings dict, which the user can provide as input Parameters ---------- verbose : bool print progress (True) or not (False) Returns ------- """ ##disres_file settings KDISH = 0.1 KDISC = 0.153 fullharm = 1 deviationdist = None general_dist = None # build_up clean disres file; def build_pair_distance_restraints(self, restrain_atoms: t.List, fullharm: int = 1, deviationdist=None, general_dist=None) -> list: # Can do it in two steps: 1)type = fullharm, deviationdist, generaldist, 2) value # check input if (fullharm == 0): if (deviationdist != None or general_dist != None): raise IOError( "Please use one option, fullharm, ddist or generaldist." ) elif (deviationdist != None): if (fullharm == 0 or general_dist != None): raise IOError( "Please use one option, fullharm, ddist or generaldist." ) elif (general_dist != None): if (deviationdist != None or fullharm == 0): raise IOError( "Please use one option, fullharm, ddist or generaldist." ) if (deviationdist == None): deviationdist = 0.0 restraint_dict = [] # TODO use zipto iterate over a1 and a2 directly for r in self.restraints: a1 = r.atoms[0] a2 = r.atoms[1] # TODO:Make distance an attribute of RestraintPair and set it once at creation. BUT THEN WE HAVE TO MAKE SUERE ATOMS ARE NOT CHANGE DAFTER THAT distance_A = sqrt((float(a1.x) - float(a2.x))**2 + (float(a1.y) - float(a2.y))**2 + (float(a1.z) - float(a2.z))**2) distance_nm = round(distance_A, 2) / 10 comment = "##\t" + a1.resn + "/" + a1.name + " " + str( a1.id) + " - " + a2.resn + "/" + a2.name + " " + str( a2.id) + "\n" distance = r.atoms new_entry = Files.Gromos_blocks.atom_pair_distanceRes( i1=a1.id, j1=0, k1=0, l1=0, type1=0, i2=a2.id, j2=0, k2=0, l2=0, type2=0, r0=np.floor(distance_nm * 100) / 100, w0=1.0, rah=fullharm, comment=comment) # print(new_entry) restraint_dict.append(new_entry) return restraint_dict disres_out = build_pair_distance_restraints( self, restrain_atoms=self.restraints, fullharm=fullharm, deviationdist=deviationdist) ##WRITE out disres.dat print("generate out_dict", mv=0) disres_out_dict = { "KDISH": KDISH, "KDISC": KDISC, "RESTRAINTHEADER": "i j k l type i j k l type r0 w0 rah".split(), # header "RESTRAINTS": disres_out } print("generate top_disres obj", mv=0) disres_file = Files.Gromos_files.disres() print("top_disres obj add:", mv=0) disres_file.add_block( blocktitle="TITLE", content="generated disres file with restraintmaker\n", verbose=True) disres_file.add_block(blocktitle="DISTANCERESSPEC", content=disres_out_dict, verbose=verbose) disres_file.write(self.out_path + ".disres") print("wrote to: " + self.out_path + ".disres", mv=4) return str(disres_file)
def _set_optimizer_type(self, new_optimizer_type: type): """ changes the current type of Optimizer and creates and applies a Optimizer of that type. @Warnings Should only be called via set_action_type which handles type checking. Parameters ---------- new_optimizer_type : t.Type[Filter] type of the new Filter Returns ------- NoReturn """ if new_optimizer_type == None: self.current_optimizer_type = None self.my_optimizer = None return if not new_optimizer_type in self.available_optimizer_types + [None]: raise TypeError(str(new_optimizer_type) + ' is not an available type of Optimizer') self.my_optimizer = new_optimizer_type(self.selected_atoms) # SWITCHTABLE FOR input function input_functions = u.do_nothing() if isinstance(self.my_optimizer, Optimizer.GreedyGraphOptimizer): input_function = qt_dialogs.create_multi_dialog( title='Parameters for GreedyGraphOptimizer', \ inputs=['number of restraints', 'maximal distance of restraints', 'tree-algorithm', 'optimize molecules pairs by'], \ options={'tree-algorithm': ['minmax', 'cog', 'prim', "biased_avg"], 'optimize molecules pairs by': ['None', 'convex_hull', 'pca_2d']}, \ default={'number of restraints': '4', 'maximal distance of restraints': '1.0', 'algorithm': 'minmax', 'optimize molecules pairs by': 'convex_hull'}) elif isinstance(self.my_optimizer, Optimizer.BruteForceRingOptimzer): input_function = qt_dialogs.create_multi_dialog( title='Parameters for BruteForceOptimizer', \ inputs=['number of restraints', 'maximal distance of restraints', 'algorithm', 'optimize molecules pairs by'], \ options={'algorithm': ['convex_hull', 'pca'], 'optimize molecules pairs by': ['None', 'convex_hull', 'pca_2d']}, \ default={'number of restraints': '4', 'maximal distance of restraints': '1.2', 'algorithm': 'pca', 'optimize molecules pairs by': 'pca_2d'}) elif isinstance(self.my_optimizer, Optimizer.MetaMoleculeRingOptimizer): input_function = qt_dialogs.create_multi_dialog( title='Parameters for BestMoleculeRingOptimizer', \ inputs=['number of restraints', 'maximal distance of restraints', 'algorithm', 'optimize molecules pairs by'], \ options={'algorithm': ['convex_hull', 'pca'], 'optimize molecules pairs by': ['convex_hull', 'pca_2d']}, \ default={'number of restraints': '4', 'maximal distance of restraints': '1.2', 'algorithm': 'pca', 'optimize molecules pairs by': 'pca_2d'}) if try_to_get_args(self.my_optimizer, input_function): time_start = time.time() try: self.selected_restraints = self.my_optimizer.make_restraints() time_stop = time.time() print('Optimized in ' + '{:0.1f}'.format(time_stop - time_start) + ' s', mv=3) except u.NoOptimalSolutionException as ex: print('Failed to find a optimal solution under the given conditions:', ex, mv=4) else: self.my_optimizer = None self.current_optimizer_type = None