def exercise_rejoin(): from mmtbx.building.alternate_conformations.tst_build_simple import pdb_raw pdb_in = iotbx.pdb.hierarchy.input(pdb_string=pdb_raw) hierarchy = pdb_in.hierarchy params = alternate_conformations.rejoin_phil.extract() n_modified = alternate_conformations.rejoin_split_single_conformers( pdb_hierarchy=hierarchy, params=params, model_error_ml=0.5, log=null_out()) assert (n_modified == 3), n_modified # Gln5 # split residue 6 without changing coordinates, set occupancy very low chain = hierarchy.only_model().chains()[0] rg6 = chain.residue_groups()[5] ag = rg6.only_atom_group().detached_copy() for atom in ag.atoms(): atom.occ = 0.05 for atom in rg6.atoms(): atom.occ = 0.95 rg6.only_atom_group().altloc = 'A' ag.altloc = 'B' rg6.append_atom_group(ag) n_modified = alternate_conformations.rejoin_split_single_conformers( pdb_hierarchy=hierarchy.deep_copy(), params=params, model_error_ml=0.5, log=null_out()) assert (n_modified == 1), n_modified # now with higher B-factors for all atoms for atom in hierarchy.atoms(): atom.b = atom.b * 10 n_modified = alternate_conformations.rejoin_split_single_conformers( pdb_hierarchy=hierarchy, params=params, log=null_out()) assert (n_modified == 1), n_modified
def exercise_rejoin () : from mmtbx.building.alternate_conformations.tst_build_simple import pdb_raw pdb_in = iotbx.pdb.hierarchy.input(pdb_string=pdb_raw) hierarchy = pdb_in.hierarchy params = alternate_conformations.rejoin_phil.extract() n_modified = alternate_conformations.rejoin_split_single_conformers( pdb_hierarchy=hierarchy, params=params, model_error_ml=0.5, log=null_out()) assert (n_modified == 3), n_modified # Gln5 # split residue 6 without changing coordinates, set occupancy very low chain = hierarchy.only_model().chains()[0] rg6 = chain.residue_groups()[5] ag = rg6.only_atom_group().detached_copy() for atom in ag.atoms() : atom.occ = 0.05 for atom in rg6.atoms() : atom.occ = 0.95 rg6.only_atom_group().altloc = 'A' ag.altloc = 'B' rg6.append_atom_group(ag) n_modified = alternate_conformations.rejoin_split_single_conformers( pdb_hierarchy=hierarchy.deep_copy(), params=params, model_error_ml=0.5, log=null_out()) assert (n_modified == 1), n_modified # now with higher B-factors for all atoms for atom in hierarchy.atoms() : atom.b = atom.b * 10 n_modified = alternate_conformations.rejoin_split_single_conformers( pdb_hierarchy=hierarchy, params=params, log=null_out()) assert (n_modified == 1), n_modified
def __init__( self, hierarchy=None, # XXX warning, ncs_phil_groups can be changed inside... ncs_phil_groups=None, params=None, log=None, ): """ TODO: 1. Transfer get_ncs_info_as_spec() to ncs/ncs.py:ncs Select method to build ncs_group_object order of implementation: 1) ncs_phil_groups - user-supplied definitions are filtered 2) hierarchy only - Performing NCS search Args: ----- ncs_phil_groups: iotbx.phil.parse(ncs_group_phil_str).extract().ncs_group chain_max_rmsd (float): limit of rms difference between chains to be considered as copies min_percent (float): Threshold for similarity between chains similarity define as: (number of matching res) / (number of res in longer chain) chain_similarity_threshold (float): min similarity between matching chains residue_match_radius (float): max allow distance difference between pairs of matching atoms of two residues """ self.number_of_ncs_groups = 0 # consider removing/replacing with function self.ncs_restraints_group_list = class_ncs_restraints_group_list() # keep hierarchy for writing (To have a source of atoms labels) self.hierarchy = hierarchy # residues common to NCS copies. Used for .spec representation self.common_res_dict = {} # Collect messages, recommendation and errors self.messages = '' # Not used outside... self.old_i_seqs = None self.original_hierarchy = None self.truncated_hierarchy = None self.truncated_h_asc = None self.chains_info = None extension = '' # set search parameters self.params = params if self.params is None: self.params = input.get_default_params().ncs_search # if log is None: self.log = sys.stdout else: self.log = log if hierarchy: # for a in hierarchy.atoms(): # print "oo", a.i_seq, a.id_str() # print "=====" hierarchy.atoms().reset_i_seq() self.original_hierarchy = hierarchy.deep_copy() self.original_hierarchy.reset_atom_i_seqs() if self.params.exclude_selection is not None: # pdb_hierarchy_inp.hierarchy.write_pdb_file("in_ncs_pre_before.pdb") cache = hierarchy.atom_selection_cache() sel = cache.selection("not (%s)" % self.params.exclude_selection) self.truncated_hierarchy = hierarchy.select(sel) else: # this could be to save iseqs but I'm not sure self.truncated_hierarchy = hierarchy.select( flex.size_t_range(hierarchy.atoms_size())) self.old_i_seqs = self.truncated_hierarchy.atoms().extract_i_seq() # print "self.old_i_seqs", list(self.old_i_seqs) # self.truncated_hierarchy.atoms().reset_i_seq() self.truncated_hierarchy.reset_atom_i_seqs() self.truncated_h_asc = self.truncated_hierarchy.atom_selection_cache( ) # self.truncated_hierarchy.write_pdb_file("in_ncs_pre_after.pdb") self.chains_info = ncs_search.get_chains_info( self.truncated_hierarchy) if self.truncated_hierarchy.atoms_size() == 0: return # # print "ncs_groups before validation", ncs_phil_groups validated_ncs_phil_groups = None validated_ncs_phil_groups = self.validate_ncs_phil_groups( pdb_h=self.truncated_hierarchy, ncs_phil_groups=ncs_phil_groups, asc=self.truncated_h_asc) if validated_ncs_phil_groups is None: # print "Last chance, building from hierarchy" self.build_ncs_obj_from_pdb_asu(pdb_h=self.truncated_hierarchy, asc=self.truncated_h_asc) # error handling if self.ncs_restraints_group_list.get_n_groups() == 0: print >> self.log, '========== WARNING! ============\n' print >> self.log, ' No NCS relation were found !!!\n' print >> self.log, '================================\n' if self.messages != '': print >> self.log, self.messages
def combine_ensembles(self, pdb_hierarchy): """ Iterate over all residues covered by the group, and pick the alternate conformers out for each residue to combine into a continous fragment. If additional conformers are needed, the previously existing atom group will be duplicated as necessary. """ from mmtbx import building from scitbx.array_family import flex hierarchy = pdb_hierarchy.deep_copy() pdb_atoms = hierarchy.atoms() pdb_atoms.reset_i_seq() n_atoms = len(pdb_atoms) covered_selection = flex.bool(pdb_atoms.size(), False) sites_cart = pdb_atoms.extract_xyz().deep_copy() residue_groups = [] n_max = self.n_confs_max() selection = self.get_entire_selection() central_selection = self.get_central_residues_selection() sub_hierarchy = hierarchy.deep_copy().select(selection) sub_hierarchy.atoms().reset_i_seq() sub_iselection = pdb_atoms.extract_i_seq().select(selection) sub_central_selection = flex.bool(pdb_atoms.size(), False).set_selected(central_selection, True).select(sub_iselection) fragment_atom_groups = [] fragment_i_seqs = [] for residue_group in mmtbx.building.iter_residue_groups(sub_hierarchy): new_atom_groups = [] n_confs = 0 atom_group = residue_group.only_atom_group() ag_new_isel = atom_group.atoms().extract_i_seq() ag_old_isel = sub_iselection.select(ag_new_isel) fragment_i_seqs.append(ag_old_isel) original_sel = flex.bool(n_atoms, False).set_selected(ag_old_isel, True) def new_atom_group(trial, selection): sites_new = sites_cart.deep_copy() sites_new.set_selected(selection, trial.sites_cart) new_ag = atom_group.detached_copy() new_ag.atoms().set_xyz(sites_new.select(original_sel)) #for k, atom in enumerate(new_ag.atoms()): # atom.i_seq = ag_old_isel[k] return new_ag if (sub_central_selection.select(ag_new_isel).all_eq(True)): # residue is the center of the window for a single ensemble, so use # the coordinates from that enemble found_residue = False for ens in self.ensembles : if (original_sel.select(ens.residue_selection).all_eq(True)): assert (not found_residue) for trial in self.sites_trials : new_atom_groups.append(new_atom_group(trial, ens.selection)) n_confs += 1 found_residue = True assert (found_residue) else : # adjacent residue only, so we take the best n_max out of all # conformations (padding with the first conf if necessary) all_trials = [] ens_selection = None for ens in self.ensembles : ens_selection_ = flex.bool(n_atoms, False).set_selected( ens.selection, True) if (ens_selection_.select(ag_old_isel).all_eq(True)): all_trials.extend(ens.sites_trials) ens_selection = ens.selection break if (len(all_trials) == 0): raise RuntimeError("No matching atoms found for %s" % atom_group.id_str()) # XXX sort by maximum deviation, or rmsd? all_trials.sort(key=operator.attrgetter("max_dev"), reverse=True) k = 0 while (n_confs < n_max) and (k < len(all_trials)): trial = all_trials[k] new_atom_groups.append(new_atom_group(trial, ens_selection)) n_confs += 1 k += 1 # fill in the remaining conformations with copies of the first while (n_confs < n_max): new_ag = atom_group.detached_copy() new_atom_groups.append(new_ag) n_confs += 1 fragment_atom_groups.append(new_atom_groups) return fragment_atom_groups, fragment_i_seqs
def combine_ensembles (self, pdb_hierarchy) : """ Iterate over all residues covered by the group, and pick the alternate conformers out for each residue to combine into a continous fragment. If additional conformers are needed, the previously existing atom group will be duplicated as necessary. """ from mmtbx import building from scitbx.array_family import flex hierarchy = pdb_hierarchy.deep_copy() pdb_atoms = hierarchy.atoms() pdb_atoms.reset_i_seq() n_atoms = len(pdb_atoms) covered_selection = flex.bool(pdb_atoms.size(), False) sites_cart = pdb_atoms.extract_xyz().deep_copy() residue_groups = [] n_max = self.n_confs_max() selection = self.get_entire_selection() central_selection = self.get_central_residues_selection() sub_hierarchy = hierarchy.deep_copy().select(selection) sub_hierarchy.atoms().reset_i_seq() sub_iselection = pdb_atoms.extract_i_seq().select(selection) sub_central_selection = flex.bool(pdb_atoms.size(), False).set_selected(central_selection, True).select(sub_iselection) fragment_atom_groups = [] fragment_i_seqs = [] for residue_group in mmtbx.building.iter_residue_groups(sub_hierarchy) : new_atom_groups = [] n_confs = 0 atom_group = residue_group.only_atom_group() ag_new_isel = atom_group.atoms().extract_i_seq() ag_old_isel = sub_iselection.select(ag_new_isel) fragment_i_seqs.append(ag_old_isel) original_sel = flex.bool(n_atoms, False).set_selected(ag_old_isel, True) def new_atom_group (trial, selection) : sites_new = sites_cart.deep_copy() sites_new.set_selected(selection, trial.sites_cart) new_ag = atom_group.detached_copy() new_ag.atoms().set_xyz(sites_new.select(original_sel)) #for k, atom in enumerate(new_ag.atoms()) : # atom.i_seq = ag_old_isel[k] return new_ag if (sub_central_selection.select(ag_new_isel).all_eq(True)) : # residue is the center of the window for a single ensemble, so use # the coordinates from that enemble found_residue = False for ens in self.ensembles : if (original_sel.select(ens.residue_selection).all_eq(True)): assert (not found_residue) for trial in self.sites_trials : new_atom_groups.append(new_atom_group(trial, ens.selection)) n_confs += 1 found_residue = True assert (found_residue) else : # adjacent residue only, so we take the best n_max out of all # conformations (padding with the first conf if necessary) all_trials = [] ens_selection = None for ens in self.ensembles : ens_selection_ = flex.bool(n_atoms, False).set_selected( ens.selection, True) if (ens_selection_.select(ag_old_isel).all_eq(True)) : all_trials.extend(ens.sites_trials) ens_selection = ens.selection break if (len(all_trials) == 0) : raise RuntimeError("No matching atoms found for %s" % atom_group.id_str()) # XXX sort by maximum deviation, or rmsd? all_trials.sort(lambda a,b: cmp(b.max_dev, a.max_dev)) k = 0 while (n_confs < n_max) and (k < len(all_trials)) : trial = all_trials[k] new_atom_groups.append(new_atom_group(trial, ens_selection)) n_confs += 1 k += 1 # fill in the remaining conformations with copies of the first while (n_confs < n_max) : new_ag = atom_group.detached_copy() new_atom_groups.append(new_ag) n_confs += 1 fragment_atom_groups.append(new_atom_groups) return fragment_atom_groups, fragment_i_seqs