def get_pose_with_ligand(filepath, LIGAND_PARAMS=[]): pose = Pose() ligand_params = Vector1(LIGAND_PARAMS) res_set = pose.conformation().modifiable_residue_type_set_for_conf() res_set.read_files_for_base_residue_types(ligand_params) pose.conformation().reset_residue_type_set_for_conf(res_set) return pose_from_file(filepath)
def GeneratePopulation(eaObj, initcfg): eaObj.population = [] # Truncation starting point delStart = min(eaObj.seqLen, eaObj.knownNativeLen) delEnd = max(eaObj.seqLen, eaObj.knownNativeLen) # Truncation ending point if (((delEnd - delStart) >= 1) and (eaObj.knownNativeLen == delEnd)): delete_region(eaObj.knownNative, delStart + 1, delEnd) # Create the initial population specified in the ini file size = 0 maxPopulation = int(initcfg['population']) while (size < maxPopulation): # new protein to be added to population that is subject to a randomized conformation newPose = Pose() newPose.assign(eaObj.initialPose) # Will convert the protein into a centroid. eaObj.fa2cen.apply(newPose) eaObj.varMover.apply(newPose) # Molecular fragment replacement if (((delEnd - delStart) >= 1) and (eaObj.seqLen == delEnd)): delete_region(newPose, delStart + 1, delEnd) # Add the newly modified protein to the total population eaObj.population.append( ProteinData(newPose, eaObj.impScoreFxn(newPose))) eaObj.evalnum += 1 size += 1
def has_interface(self, pose: pyrosetta.Pose, interface: str) -> bool: if pose is None: pose = self.pose pose2pdb = pose.pdb_info().pose2pdb have_chains = {pose2pdb(r).split()[1] for r in range(1, pose.total_residue() + 1)} want_chains = set(interface.replace('_', '')) return have_chains == want_chains
def get_NGL_selection_from_AtomID(pose: pyrosetta.Pose, atom_id: pyrosetta.AtomID): pose_resi = atom_id.rsd() residue = pose.residue(pose_resi) atom_name = residue.atom_name(atom_id.atomno()).strip() pdb_resi, chain = pose.pdb_info().pose2pdb(pose_resi).strip().split() return f'[{residue.name3().strip()}]{pdb_resi}:{chain}.{atom_name}'
def make_mutant(self, pose: pyrosetta.Pose, mutation: str, chain='A') -> pyrosetta.Pose: """ Make a point mutant (``A23D``). :param pose: pose :param mutation: :param chain: :return: """ mutant = pose.clone() pose2pdb = pose.pdb_info().pdb2pose rex = re.match('(\w)(\d+)(\w)', mutation) r = pose2pdb(res=int(rex.group(2)), chain=chain) rn = pose.residue(r).name1() assert rn == rex.group( 1 ), f'residue {r}(pose)/{rex.group(2)}(pdb) is a {rn}, not a {rex.group()}' MutateResidue = pyrosetta.rosetta.protocols.simple_moves.MutateResidue MutateResidue(target=r, new_res=self._name3[rex.group(3)]).apply(mutant) self.relax_around_mover(mutant, int(rex.group(2)), chain, distance=12, cycles=15) return mutant
def __init__(self, temp_path,results_path,pdb_path,input_path,\ close_cycles = 20, refine_cycles = 1,relax_cycles=3, DEBUG=True,watch = True,ligand=False,ligand_params=[],partners='A_X'): self.DEBUG = DEBUG super(InDelMut, self).__init__() if temp_path.strip()[-1]=='/': temp_path = temp_path.strip()[:-1] if results_path.strip()[-1]=='/': results_path = results_path.strip()[:-1] self.temp_path = temp_path self.results_path = results_path if DEBUG: print('temp_path:',self.temp_path) if DEBUG: print('results_path:',self.results_path) self.pdb_path = pdb_path self.input_path = input_path self.refine_cycles = refine_cycles self.close_cycles = close_cycles self.relax_cycles = relax_cycles self.ligand = ligand self.partners = partners self._load_files() # constant pose - initial pose if ligand: self.POSE = get_pose_with_ligand(self.pdb_path,ligand_params) else: self.POSE = get_pose(self.pdb_path) pose = Pose() # keeps current pose self.pose = pose.assign(self.POSE) movemap = MoveMap() movemap.set_bb(True) movemap.set_chi(True) minmover = pyrosetta.rosetta.protocols.minimization_packing.MinMover() minmover.movemap(movemap) minmover.score_function(get_fa_scorefxn()) minmover.apply(self.pose) self._load_movers() self.scores[0] = pose.scores['total_score'] self._load_numbering() # pymol = PyMOLMover() # pymol.keep_history(True) # self.pymol = pymol # if watch: self._apply_pymol() self.mover_index = 0
def add_cst(self, pose: pyrosetta.Pose, res_i: int, atm_i: str, res_j: int, atm_j: str, distance: float = 2.4, sigma: float = 0.1) \ -> pyrosetta.rosetta.core.scoring.constraints.AtomPairConstraint: AtomID = pyrosetta.rosetta.core.id.AtomID id_i = AtomID(pose.residue(res_i).atom_index(atm_i), res_i) id_j = AtomID(pose.residue(res_j).atom_index(atm_j), res_j) ijfunc = pyrosetta.rosetta.core.scoring.constraints.BoundFunc( 0.0, distance, sigma, 'cst1') cst_ij = pyrosetta.rosetta.core.scoring.constraints.AtomPairConstraint( id_i, id_j, ijfunc) pose.add_constraint(cst_ij) return cst_ij
def movement(self, original: pyrosetta.Pose, resi: int, chain: str, distance: int, trials: int = 50, temperature: int = 1.0, replicate_number: int = 10): """ This method adapted from a notebook of mine, but not from an official source, is not well written. It should be a filter and score combo. It returns the largest bb_rmsd of the pdb residue resi following backrub. """ # this code is experimental n = self.get_neighbour_vector(pose=original, resi=resi, chain=chain, distance=distance, own_chain_only=False) # resi if chain is None: # pose numbering. target_res = resi else: target_res = original.pdb_info().pdb2pose(chain=chain, res=resi) # prep rv = pyrosetta.rosetta.core.select.residue_selector.ResidueVector(n) backrub = pyrosetta.rosetta.protocols.backrub.BackrubMover() backrub.set_pivot_residues(rv) # https://www.rosettacommons.org/docs/latest/scripting_documentation/RosettaScripts/Movers/movers_pages/GenericMonteCarloMover monégasque = pyrosetta.rosetta.protocols.monte_carlo.GenericMonteCarloMover(maxtrials=trials, max_accepted_trials=trials, # gen.max_accepted_trials() = 0 task_scaling=5, # gen.task_scaling() mover=backrub, temperature=temperature, sample_type='low', drift=True) monégasque.set_scorefxn(self.scorefxn) # monégasque.add_filter(filters , False , 0.005 , 'low' , True ) # define the first 4 atoms (N C CA O) am = pyrosetta.rosetta.utility.vector1_unsigned_long(4) for i in range(1, 5): am[i] = i # find most deviant best_r = 0 for i in range(replicate_number): variant = original.clone() monégasque.apply(variant) if monégasque.accept_counter() > 0: variant = monégasque.last_accepted_pose() # pretty sure redundant # bb_rmsd is all residues: pyrosetta.rosetta.core.scoring.bb_rmsd(pose, ori) r = pyrosetta.rosetta.core.scoring.residue_rmsd_nosuper(variant.residue(target_res), original.residue(target_res), am) if r > best_r: best_r = r return best_r
def __init__(self, PDB, EPITOPES=[], ANTIBODY='HK', ANTIGEN='A', pymol=True): pose = Pose() self.pose = pose_from_file(PDB) self.native_pose = self.pose.clone() self.scorefxn = create_score_function('ref2015') self.partners = '{0}_{1}'.format(ANTIGEN, ANTIBODY) self.antibody = ANTIBODY self.antigen = ANTIGEN self.epitopes_pdb = EPITOPES # store corresponding pose residue numbers self.epitopes_pose = [] info = self.pose.pdb_info() for ep in EPITOPES: chain, res = ep self.epitopes_pose.append(info.pdb2pose(chain, res)) if pymol: pymover = PyMOLMover() self.pymol_mover = pymover pymover.update_interval(1) pymover.keep_history(True) self.send_to_pymol()
def iterate(self): # Possible expansion of MOEA. Hence, why this operation is more complicated than it needs to be. prevPop = selection.select(self) nextPop = [] # Focus on the poses for i in range(len(prevPop)): # Setup variables for creating the new protein configuration to be added to the population. childData = ProteinData(Pose(), prevPop[i].score) # copy pose from previous generation. childData.pose.assign(prevPop[i].pose) # Begin protein manipulation crossover.typeofcrossover(self, childData) # Perform a crossover variation.perturb(self, childData) # Apply fragment replacement # Local search for possible improvement improvement.localSearch(self, childData) nextPop.append(childData) # Elitest-based Truncation Selection self.population = selection.truncate(self, prevPop, nextPop) # Evaluate the newest generation for i in range(len(self.population)): # align the poses for a better score. # Don't think this is working. Tested it and didn't show any signficant changes. # calpha_superimpose_pose(self.population[i].pose, self.knownNative) # Evaluate and store the rmsd score between the 2 poses along with the score. self.population[i].rmsd = CA_rmsd(self.population[i].pose, self.knownNative) self.population[i].age += 1 self.proteinDB.append([ self.population[i].rmsd, self.population[i].score, self.population[i].age ])
def get_neighbour_vector( self, pose: pyrosetta.Pose, resi: int, chain: str, distance: int, include_focus_in_subset: bool = True, own_chain_only: bool = False ) -> pyrosetta.rosetta.utility.vector1_bool: resi_sele = pyrosetta.rosetta.core.select.residue_selector.ResidueIndexSelector( ) if chain is None: # pose numbering. resi_sele.set_index(resi) else: resi_sele.set_index(pose.pdb_info().pdb2pose(chain=chain, res=resi)) NeighborhoodResidueSelector = pyrosetta.rosetta.core.select.residue_selector.NeighborhoodResidueSelector neigh_sele = NeighborhoodResidueSelector( resi_sele, distance=distance, include_focus_in_subset=include_focus_in_subset) if own_chain_only and chain is not None: chain_sele = pyrosetta.rosetta.core.select.residue_selector.ChainSelector( chain) and_sele = pyrosetta.rosetta.core.select.residue_selector.AndResidueSelector( neigh_sele, chain_sele) return and_sele.apply(pose) else: return neigh_sele.apply(pose)
def make_mutant(self, pose: pyrosetta.Pose, mutation: Union[str, Mutation], chain='A', distance: int = 10, cycles: int = 5) -> pyrosetta.Pose: """ Make a point mutant (``A23D``). :param pose: pose :param mutation: :param chain: :return: """ if pose is None: mutant = self.pose.clone() else: mutant = pose.clone() if isinstance(mutation, str): mutation = Mutation(mutation, chain, mutant) MutateResidue = pyrosetta.rosetta.protocols.simple_moves.MutateResidue MutateResidue(target=mutation.pose_resi, new_res=mutation.to_resn3).apply(mutant) self.relax_around_mover(mutant, mutation=mutation, distance=distance, cycles=cycles, own_chain_only=False) return mutant
def setup_class(cls): mmap = MoveMap() cls.pose = Pose() make_pose_from_sequence(cls.pose, 'PYTEST', "fa_standard", True) cls.shear_mv = ShearMover(mmap, 1., 1)
def pose2pandas(pose: pyrosetta.Pose, scorefxn: pyrosetta.ScoreFunction) -> pd.DataFrame: """ Return a pandas dataframe from the scores of the pose :param pose: :return: """ pose.energies().clear_energies() scorefxn(pose) scores = pd.DataFrame(pose.energies().residue_total_energies_array()) pi = pose.pdb_info() scores['residue'] = scores.index.to_series() \ .apply(lambda r: pose.residue( r +1) \ .name1() + pi.pose2pdb( r +1) ) return scores
def pose_fx(pose: pyrosetta.Pose): """ Histidine in delta. """ pdb2pose = pose.pdb_info().pdb2pose r = pdb2pose(res=41, chain='A') MutateResidue = pyrosetta.rosetta.protocols.simple_moves.MutateResidue MutateResidue(target=r, new_res='HIS').apply(pose)
def setup_class(cls): mmap = MoveMap() mmap.set_bb(True) cls.pose = Pose() make_pose_from_sequence(cls.pose, 'PYTEST', "fa_standard", True) cls.small_mv = SmallMover(mmap, 1., 1) cls.rep_mv = RepeatMover(cls.small_mv, 3)
def poised_pose_fx(pose: pyrosetta.Pose): """ Histidine in delta and cysteine in thiolate. """ pdb2pose = pose.pdb_info().pdb2pose r = pdb2pose(res=41, chain='A') MutateResidue = pyrosetta.rosetta.protocols.simple_moves.MutateResidue MutateResidue(target=r, new_res='HIS_D').apply(pose) r = pdb2pose(res=145, chain='A') MutateResidue(target=r, new_res='CYZ').apply(pose)
def __init__(self, mutation_name: str, chain: str, pose: pyrosetta.Pose): self.mutation = self.parse_mutation(mutation_name) rex = re.match('(\w)(\d+)(\w)', self.mutation) self.pdb_resi = int(rex.group(2)) self.chain = chain self.from_resn1 = rex.group(1) self.from_resn3 = self._name3[rex.group(1)] self.to_resn1 = rex.group(3) self.to_resn3 = self._name3[rex.group(3)] pose2pdb = pose.pdb_info().pdb2pose self.pose_resi = pose2pdb(res=self.pdb_resi, chain=self.chain) if self.pose_resi != 0: self.pose_residue = pose.residue(self.pose_resi) self.pose_resn1 = self.pose_residue.name1() self.pose_resn3 = self.pose_residue.name3() else: self.pose_residue = None self.pose_resn1 = None self.pose_resn3 = None
def input_silent_score_seq(filename): hbond_list = {} torsion_list = {} score_list = {} seq_list = {} # sfd=SilentFileData() sfd = SilentFileData(SilentFileOptions()) sfd.read_file(filename) p = Pose() sf_tags = sfd.tags() for tag in sf_tags: silent_struct = sfd.get_structure(tag) silent_struct.fill_pose(p) en = silent_struct.energies()[1] score_list[tag] = en.value() seq_list[tag] = [p.residue(i).name() for i in range(1, p.size() + 1)] torsion_list[tag] = get_torsions(p) hbond_list[tag] = find_hbonds(p) return torsion_list, hbond_list, score_list, seq_list
def copy_pdb_info(self, original_pose: pyrosetta.Pose, final_pose: pyrosetta.Pose): # get original residue info ResInfo.pdb_info = original_pose.pdb_info() original = [] previous = None for row in self: if row[0] == 0: # insertion code is a letter previous.icode raise NotImplementedError ri = ResInfo.get(row[0]) original.append(ri) previous = ri # set info pdb_info = final_pose.pdb_info() for i, row in enumerate(original): row.set(i + 1, pdb_info) pdb_info().obsolete(False)
def add_residuetype( self, pose: pyrosetta.Pose ) -> pyrosetta.rosetta.core.chemical.ResidueTypeSet: rts = pose.conformation().modifiable_residue_type_set_for_conf( pyrosetta.rosetta.core.chemical.FULL_ATOM_t) buffer = pyrosetta.rosetta.std.stringbuf(self.dumps()) stream = pyrosetta.rosetta.std.istream(buffer) new = pyrosetta.rosetta.core.chemical.read_topology_file( stream, self.NAME, rts) # no idea what the second argument does rts.add_base_residue_type(new) return rts
def Fc_glycan_rmsd( working, working_Fc_glycan_chains, native, native_Fc_glycan_chains, decoy_num, dump_dir ): """ :param working: decoy Pose() :param working_Fc_glycan_chains: list( the chain id's for the working Fc glycan ). Ex = [ 'H', 'I' ] :param native: native Pose() :param native_Fc_glycan_chains: list( the chain id's for the native Fc glycan ). Ex = [ 'D', 'E' ] :param decoy_num: int( the number of the decoy for use when dumping its Fc glycan ) :param dump_dir: str( /path/to/dump_dir for the temp pdb files made. Files will be deleted ) return: float( Fc glycan rmsd ) """ # imports import os from pyrosetta import Pose from rosetta.core.scoring import non_peptide_heavy_atom_RMSD from antibody_functions import load_pose from util import dump_pdb_by_chain, id_generator # get temporary files to work with id = id_generator() if dump_dir.endswith( '/' ): working_filename = "%s%s_temp_working_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) native_filename = "%s%s_temp_native_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) else: working_filename = "%s/%s_temp_working_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) native_filename = "%s/%s_temp_native_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) # dump out the Fc glycans by their chain id's dump_pdb_by_chain( working_filename, working, working_Fc_glycan_chains, decoy_num, dump_dir = dump_dir ) dump_pdb_by_chain( native_filename, native, native_Fc_glycan_chains, decoy_num, dump_dir = dump_dir ) # load in the Fc glycans just_Fc_glycan = Pose() try: just_Fc_glycan.assign( load_pose( working_filename ) ) except: pass native_just_Fc_glycan = Pose() try: native_just_Fc_glycan.assign( load_pose( native_filename ) ) except: pass # calculate the glycan rmsd try: glycan_rmsd = non_peptide_heavy_atom_RMSD( just_Fc_glycan, native_just_Fc_glycan ) except: glycan_rmsd = "nan" pass # delete the files try: os.popen( "rm %s" %working_filename ) os.popen( "rm %s" %native_filename ) except: pass return glycan_rmsd
def do_chainwise_relax(pose: pyrosetta.Pose, scorefxn: Optional[pyrosetta.ScoreFunction] = None, cycles: int = 5) -> None: if scorefxn is None: scorefxn = pyrosetta.get_fa_scorefxn() for chain_i in range(1, pose.num_chains() + 1): chain_sele = pyrosetta.rosetta.core.select.residue_selector.ChainSelector(chain_i) chain_vector = chain_sele.apply(pose) movemap = pyrosetta.MoveMap() movemap.set_bb(allow_bb=chain_vector) movemap.set_chi(allow_chi=chain_vector) relax = pyrosetta.rosetta.protocols.relax.FastRelax(scorefxn, cycles) relax.set_movemap(movemap) relax.apply(pose)
def input_silent(filename): hbond_list = {} torsion_list = {} # sfd=SilentFileData() sfd = SilentFileData(SilentFileOptions()) sfd.read_file(filename) p = Pose() sf_tags = sfd.tags() for tag in sf_tags: silent_struct = sfd.get_structure(tag) silent_struct.fill_pose(p) torsion_list[tag] = get_torsions(p) hbond_list[tag] = find_hbonds(p) return torsion_list, hbond_list
def pose_from_params(filename, params_list): pose = Pose() rts = pose.conformation().modifiable_residue_type_set_for_conf( core.chemical.FULL_ATOM_t) rts.read_files_for_base_residue_types(Vector1(params_list)) pose.conformation().reset_residue_type_set_for_conf(rts) pose_from_file(pose, pose.residue_type_set_for_pose(), filename) return pose
def clarify_selector(selector: pyrosetta.rosetta.core.select.residue_selector. ResidueSelector, pose: pyrosetta.Pose) -> List['str']: """ Given a selector and pose return a list of residues in NGL selection format Example, [CMP]787:H :param selector: :param pose: :return: list of residues in NGL selection format """ pose2pdb = pose.pdb_info().pose2pdb vector = selector.apply(pose) rv = pyrosetta.rosetta.core.select.residue_selector.ResidueVector(vector) return [ f'[{pose.residue(r).name3()}]{pose2pdb(r).strip().replace(" " ,":")}' for r in rv ]
def relax_around_mover(self, pose: pyrosetta.Pose, resi: int, chain: str, scorefxn=None, cycles=5, distance=5, cartesian=False) -> None: """ Relaxes pose ``distance`` around resi:chain. :param resi: PDB residue number. :param chain: :param pose: :param scorefxn: :param cycles: of relax (3 quick, 15 thorough) :param distance: :param cartesian: :return: """ if scorefxn is None: scorefxn = pyrosetta.get_fa_scorefxn() #self._cst_score(scorefxn) movemap = pyrosetta.MoveMap() #### resi_sele = pyrosetta.rosetta.core.select.residue_selector.ResidueIndexSelector( ) resi_sele.set_index(pose.pdb_info().pdb2pose(chain=chain, res=resi)) NeighborhoodResidueSelector = pyrosetta.rosetta.core.select.residue_selector.NeighborhoodResidueSelector neigh_sele = NeighborhoodResidueSelector(resi_sele, distance=distance, include_focus_in_subset=True) n = neigh_sele.apply(pose) movemap.set_bb(allow_bb=n) movemap.set_chi(allow_chi=n) relax = pyrosetta.rosetta.protocols.relax.FastRelax(scorefxn, cycles) relax.set_movemap_disables_packing_of_fixed_chi_positions(True) relax.set_movemap(movemap) relax.cartesian(cartesian) relax.apply(pose)
def add_bfactor_from_score(pose: pyrosetta.Pose): """ Adds the bfactors from total_score. Snippet for testing in Jupyter >>> import nglview as nv >>> view = nv.show_rosetta(pose) >>> # view = nv.show_file('test.cif') >>> view.clear_representations() >>> view.add_tube(radiusType="bfactor", color="bfactor", radiusScale=0.10, colorScale="RdYlBu") >>> view ``replace_res_remap_bfactors`` may have been a cleaner strategy. This was quicker to write. If this fails, it may be because the pose was not scored first. """ if pose.pdb_info().obsolete(): raise ValueError( 'Pose pdb_info is flagged as obsolete (change `pose.pdb_info().obsolete(False)`)' ) # scores energies = pose.energies() def get_res_score(res): total_score = pyrosetta.rosetta.core.scoring.ScoreType.total_score # if pose.residue(res).is_polymer() try: return energies.residue_total_energies(res)[total_score] except: return float('nan') # the array goes from zero (nan) to n_residues total_scores = np.array( [float('nan')] + [get_res_score(res) for res in range(1, pose.total_residue() + 1)]) mask = np.isnan(total_scores) total_scores -= np.nanmin(total_scores) total_scores *= 100 / np.nanmax(total_scores) total_scores = np.nan_to_num(total_scores, nan=100) total_scores[mask] = 0. # add to pose pdb_info = pose.pdb_info() for res in range(pose.total_residue()): for i in range(pose.residue(res + 1).natoms()): pdb_info.bfactor(res + 1, i + 1, total_scores[res + 1])
def correct( self, pose: pyrosetta.Pose ) -> pyrosetta.rosetta.core.select.residue_selector.ResidueSelector: """ This is not a great thing to do. So it is best to relax the neighbours of the vector afterwards. If there are valines instead of the intended sequence that is bad. Altering the blueprint is required. :param pose: :return: """ MutateResidue = pyrosetta.rosetta.protocols.simple_moves.MutateResidue one2three = pyrosetta.rosetta.protocols.motifs.name3_from_oneletter ex_seq = self.expected_seq() altered = pyrosetta.rosetta.core.select.residue_selector.ResidueIndexSelector( ) for i, (expected, current) in enumerate(zip(ex_seq, pose.chain_sequence(1))): if expected != current: altered.append_index(i + 1) MutateResidue(target=i + 1, new_res=one2three(expected)).apply(pose) return altered
def pose_from_pubchem(cid, name, temporary=True): pose = Pose() if temporary: # the temporary solution, create an ephemeral ResidueSet params_from_pubchem(cid, name) # Add the new ResidueType to the pose rts = pose.conformation().modifiable_residue_type_set_for_conf( core.chemical.FULL_ATOM_t) rts.add_base_residue_type(name) pose.conformation().reset_residue_type_set_for_conf(rts) # fill the pose pose_from_file(pose, pose.residue_type_set_for_pose(), name + "_0001.pdb") else: # permanent solution, add to .params list add_cid_to_database(cid, name) # fill the pose pose_from_file(pose, name + "_0001.pdb") return pose
CONECT 4 2 5 6 CONECT 5 4 CONECT 6 4 CONECT 7 8 CONECT 8 7 9 12 CONECT 9 8 10 11 CONECT 10 9 13 14 CONECT 11 9 15 16 CONECT 12 8 CONECT 13 10 CONECT 14 10 CONECT 15 11 CONECT 16 11 """ pose = Pose() pose_from_pdbstring(pose, contents) sc_donor = { 1: [ pick_ray(pose.residue(1), "1HD2", "ND2"), pick_ray(pose.residue(1), "2HD2", "ND2") ], 2: [ pick_ray(pose.residue(2), "HE", "NE"), pick_ray(pose.residue(2), "1HH1", "NH1"), pick_ray(pose.residue(2), "2HH1", "NH1"), pick_ray(pose.residue(2), "1HH2", "NH2"), pick_ray(pose.residue(2), "2HH2", "NH2") ] }
def pseudo_interface_energy_3ay4( pose, in_sf, native = False, pmm = None ): """ Attempts to get pseudo-interface energy of a glycosylated 3ay4 decoy Lots of hard coding here - works on a decoy pose as Rosetta renumbers the Pose a bit Makes the two ASN connections to the Fc A and B glycans JUMPs instead of chemical EDGEs :param pose: Pose :param in_sf: ScoreFunction :param native: bool( is this the native 3ay4 or a decoy? Answer determines how FoldTree gets coded ) :param pmm: PyMOL_Mover( pass a PyMOL_Mover object if you want to watch the protocol ). Default = None :return: float( pseudo interface energy ) """ from pyrosetta import FoldTree, Pose from rosetta.numeric import xyzVector_double_t from rosetta.core.scoring import score_type_from_name # if this isn't the Fc-FcR structure of 3ay4, just return 0 if pose.size() != 618: return 0 # set atom_pair_constraint weight to 0 sf = in_sf.clone() sf.set_weight( score_type_from_name( "atom_pair_constraint" ), 0.0 ) # get the score of the whole complex start_score = sf( pose ) # hard code the new FoldTree specific to a glycosylated decoy of 3ay4 if not native: ft = FoldTree() ft.add_edge( 1, 215, -1 ) ft.add_edge( 1, 216, 1 ) # beginning of chain A to beginning of chain B ft.add_edge( 216, 431, -1 ) ft.add_edge( 1, 432, 2 ) # beginning of chain A to beginning of chain C ft.add_edge( 432, 591, -1 ) ft.add_edge( 579, 592, "ND2", "C1" ) ft.add_edge( 592, 596, -1 ) ft.add_edge( 594, 597, "O6", "C1" ) ft.add_edge( 597, 598, -1 ) ft.add_edge( 592, 599, "O6", "C1" ) ft.add_edge( 462, 600, "ND2", "C1" ) ft.add_edge( 600, 602, -1 ) ft.add_edge( 69, 603, 3 ) # ASN 297 A to core GlcNAc H ft.add_edge( 603, 607, -1 ) ft.add_edge( 605, 608, "O6", "C1" ) ft.add_edge( 608, 610, -1 ) ft.add_edge( 284, 611, 4 ) # ASN 297 B to core GlcNAc J ft.add_edge( 611, 615, -1 ) ft.add_edge( 613, 616, "O6", "C1" ) ft.add_edge( 616, 618, -1 ) # hard code the new FoldTree specific to the native 3ay4 else: ft = FoldTree() ft.add_edge( 1, 215, -1 ) ft.add_edge( 69, 216, 1 ) # ASN 297 A to core GlcNAc D ft.add_edge( 216, 220, -1 ) ft.add_edge( 218, 221, "O6", "C1" ) ft.add_edge( 221, 223, -1 ) ft.add_edge( 1, 224, 2 ) # beginning of chain A to beginning of chain B ft.add_edge( 224, 439, -1 ) ft.add_edge( 292, 440, 3 ) # ASN 297 B to core GlcNAc E ft.add_edge( 440, 444, -1 ) ft.add_edge( 442, 445, "O6", "C1" ) ft.add_edge( 445, 447, -1 ) ft.add_edge( 1, 448, 4 ) # beginning of chain A to beginning of chain C ft.add_edge( 448, 607, -1 ) ft.add_edge( 595, 608, "ND2", "C1" ) ft.add_edge( 608, 612, -1 ) ft.add_edge( 610, 613, "O6", "C1" ) ft.add_edge( 613, 614, -1 ) ft.add_edge( 608, 615, "O6", "C1" ) ft.add_edge( 478, 616, "ND2", "C1" ) ft.add_edge( 616, 618, -1 ) # make a temporary Pose and give the new FoldTree to it try: pmm.keep_history( True ) except: pass temp_pose = Pose() temp_pose.assign( pose ) temp_pose.fold_tree( ft ) try: pmm.apply( temp_pose ) except: pass # split apart the two Fc sugars one-by-one # if decoy structure -- the two glycans are now the last two new jumps if not native: jump = temp_pose.jump( 3 ) # sugar A vec = xyzVector_double_t( 1000, 1000, 1000 ) jump.set_translation( vec ) temp_pose.set_jump( 3, jump ) try: pmm.apply( temp_pose ) except: pass jump = temp_pose.jump( 4 ) # sugar B vec = xyzVector_double_t( 1000, 1000, 1000 ) jump.set_translation( vec ) temp_pose.set_jump( 4, jump ) try: pmm.apply( temp_pose ) except: pass # else native structure -- the two glycans are the first and third new jumps else: jump = temp_pose.jump( 1 ) # sugar A vec = xyzVector_double_t( 1000, 1000, 1000 ) jump.set_translation( vec ) temp_pose.set_jump( 1, jump ) try: pmm.apply( temp_pose ) except: pass jump = temp_pose.jump( 3 ) # sugar B vec = xyzVector_double_t( 1000, 1000, 1000 ) jump.set_translation( vec ) temp_pose.set_jump( 3, jump ) try: pmm.apply( temp_pose ) except: pass # score the split-apart Pose split_score = sf( temp_pose ) # get the pseudo-interface score # total - split = interface ( ie. interface + split = total ) pseudo_interface_energy = start_score - split_score return pseudo_interface_energy
def Fc_glycan_metrics( working, native, working_Fc_glycan_chains, native_Fc_glycan_chains, sf, decoy_num, dump_dir ): """ Return the glycan RMSD contribution of the two Fc glycans in 3ay4 (may work for other PDBs, but I don't know yet) Fc_glycan_buried_sasa = complex with Fc glycan - ( complex without Fc glycan + just Fc glycan ) hbonds contributed by Fc glycans = total hbonds in Pose - total hbonds in Pose without Fc glycans - just Fc glycan hbonds :param working: decoy Pose() :param native: native Pose() :param working_Fc_glycan_chains: list( the chain id's for the working Fc glycan ). Ex = [ 'H', 'I' ] :param native_Fc_glycan_chains: list( the chain id's for the native Fc glycan ). Ex = [ 'D', 'E' ] :param sf: ScoreFunction :param decoy_num: int( the number of the decoy for use when dumping its Fc glycan ) :param dump_dir: str( /path/to/dump_dir for the temp pdb files made. Files will be deleted ) :return: obj( DataHolder that contains Fc_glycan_rmsd, Fc_glycan_tot_score, Fc_glycan_buried_sasa, and Fc_glycan_internal_hbonds, Fc_glycan_hbonds_contributed ) """ ################# #### IMPORTS #### ################# # Rosetta functions from pyrosetta import Pose from rosetta.core.scoring import non_peptide_heavy_atom_RMSD, \ calc_total_sasa # Rosetta functions I wrote out from antibody_functions import load_pose, DataHolder # utility functions import os from util import dump_pdb_by_chain, id_generator from pyrosetta.toolbox import get_hbonds # for use in SASA calculations probe_size = 1.4 # get glycan rmsd (not using above function because I want to use the glycan poses for something else # get temporary files to work with id = id_generator() if dump_dir.endswith( '/' ): working_filename = "%s%s_temp_working_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) native_filename = "%s%s_temp_native_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) else: working_filename = "%s/%s_temp_working_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) native_filename = "%s/%s_temp_native_just_glyc%s.pdb" %( dump_dir, id, str( decoy_num ) ) # dump out the Fc glycans by their chain id's dump_pdb_by_chain( working_filename, working, working_Fc_glycan_chains, decoy_num, dump_dir = dump_dir ) dump_pdb_by_chain( native_filename, native, native_Fc_glycan_chains, decoy_num, dump_dir = dump_dir ) # load in the Fc glycans working_just_Fc_glycan = Pose() try: working_just_Fc_glycan.assign( load_pose( working_filename ) ) except: pass native_just_Fc_glycan = Pose() try: native_just_Fc_glycan.assign( load_pose( native_filename ) ) except: pass # calculate the glycan rmsd try: glycan_rmsd = non_peptide_heavy_atom_RMSD( working_just_Fc_glycan, native_just_Fc_glycan ) except: glycan_rmsd = "nan" pass # get the metrics associated with just the Fc glycan # score first as to gain access to the hbonds data working_Fc_glycan_tot_score = sf( working_just_Fc_glycan ) native_Fc_glycan_tot_score = sf( native_just_Fc_glycan ) # SASA of just the glycan working_Fc_glycan_sasa = calc_total_sasa( working_just_Fc_glycan, probe_size ) native_Fc_glycan_sasa = calc_total_sasa( native_just_Fc_glycan, probe_size ) # num hbonds in Fc glycan working_Fc_glycan_internal_hbonds = get_hbonds( working_just_Fc_glycan ).nhbonds() native_Fc_glycan_internal_hbonds = get_hbonds( native_just_Fc_glycan ).nhbonds() # delete the files try: os.popen( "rm %s" %working_filename ) os.popen( "rm %s" %native_filename ) except: pass # now move to metrics requiring the removal of the glycan from the complex # get temporary files to work with id = id_generator() if dump_dir.endswith( '/' ): working_filename = "%s%s_working_no_glyc_%s.pdb" %( dump_dir, id, str( decoy_num ) ) native_filename = "%s%s_native_no_glyc_%s.pdb" %( dump_dir, id, str( decoy_num ) ) else: working_filename = "%s/%s_working_no_glyc_%s.pdb" %( dump_dir, id, str( decoy_num ) ) native_filename = "%s/%s_native_no_glyc_%s.pdb" %( dump_dir, id, str( decoy_num ) ) # get the chain id's of everything discluding the passed Fc glycan chain id's working_pose_chains = [] for res in working: chain_id = working.pdb_info().chain( res.seqpos() ) if ( chain_id not in working_pose_chains ) and ( chain_id not in working_Fc_glycan_chains ): working_pose_chains.append( chain_id ) native_pose_chains = [] for res in native: chain_id = native.pdb_info().chain( res.seqpos() ) if ( chain_id not in native_pose_chains ) and ( chain_id not in native_Fc_glycan_chains ): native_pose_chains.append( chain_id ) # dump out the pose without its Fc glycans by the chain id's dump_pdb_by_chain( working_filename, working, working_pose_chains, decoy_num, dump_dir = dump_dir ) dump_pdb_by_chain( native_filename, native, native_pose_chains, decoy_num, dump_dir = dump_dir ) # load in the working Pose without the Fc glycans working_complex_no_Fc_glycan = Pose() native_complex_no_Fc_glycan = Pose() try: working_complex_no_Fc_glycan.assign( load_pose( working_filename ) ) native_complex_no_Fc_glycan.assign( load_pose( working_filename ) ) except: pass # score the Poses so their hbond energies get updated sf( working ) sf( working_complex_no_Fc_glycan ) sf( native ) sf( native_complex_no_Fc_glycan ) # get the number of hbonds in the Pose without the Fc glycans # working working_with_Fc_glycan_hbonds = get_hbonds( working ) working_no_Fc_glycan_hbonds = get_hbonds( working_complex_no_Fc_glycan ) working_Fc_glycan_hbonds_contributed = working_with_Fc_glycan_hbonds.nhbonds() - working_no_Fc_glycan_hbonds.nhbonds() - working_Fc_glycan_internal_hbonds # native native_with_Fc_glycan_hbonds = get_hbonds( native ) native_no_Fc_glycan_hbonds = get_hbonds( native_complex_no_Fc_glycan ) native_Fc_glycan_hbonds_contributed = native_with_Fc_glycan_hbonds.nhbonds() - native_no_Fc_glycan_hbonds.nhbonds() - native_Fc_glycan_internal_hbonds # get the SASA contributed by the presence of the Fc glycan # working working_with_Fc_glycan_sasa = calc_total_sasa( working, probe_size ) working_no_Fc_glycan_sasa = calc_total_sasa( working_complex_no_Fc_glycan, probe_size ) working_Fc_glycan_sasa_contributed = working_with_Fc_glycan_sasa - ( working_no_Fc_glycan_sasa + working_Fc_glycan_sasa ) # native native_with_Fc_glycan_sasa = calc_total_sasa( native, probe_size ) native_no_Fc_glycan_sasa = calc_total_sasa( native_complex_no_Fc_glycan, probe_size ) native_Fc_glycan_sasa_contributed = native_with_Fc_glycan_sasa - ( native_no_Fc_glycan_sasa + native_Fc_glycan_sasa ) # delete the files try: os.popen( "rm %s" %working_filename ) os.popen( "rm %s" %native_filename ) except: pass # store data in the DataHolder and return it data = DataHolder() data.Fc_glycan_rmsd = glycan_rmsd data.Fc_glycan_tot_score = working_Fc_glycan_tot_score data.native_Fc_glycan_tot_score = native_Fc_glycan_tot_score data.Fc_glycan_internal_hbonds = working_Fc_glycan_internal_hbonds data.native_Fc_glycan_internal_hbonds = native_Fc_glycan_internal_hbonds data.Fc_glycan_hbonds_contributed = working_Fc_glycan_hbonds_contributed data.native_Fc_glycan_hbonds_contributed = native_Fc_glycan_hbonds_contributed data.Fc_glycan_sasa_contributed = working_Fc_glycan_sasa_contributed data.native_Fc_glycan_sasa_contributed = native_Fc_glycan_sasa_contributed data.probe_size = probe_size return data