def __init__( self, spacegroup, pept_axis, pept_orig, ligands, sym_of_ligand, max_dun_score, **kw, ): super(XtalSearchSpec, self).__init__() kw = rp.Bunch(kw) self.spacegroup = spacegroup self.pept_axis = pept_axis self.pept_orig = pept_orig self.ligands = ligands self.sym_of_ligand = sym_of_ligand self.max_dun_score = max_dun_score self.xtal_spec = mof.xtal_spec.get_xtal_spec(self.spacegroup) self.chm = rt.core.chemical.ChemicalManager.get_instance() self.rts = self.chm.residue_type_set('fa_standard') self.sfxn_rotamer = get_sfxn('rotamer') # self.sfxn_rotamer.set_weight(rt.core.scoring.ScoreType.fa_dun, 1.0) self.sfxn_sterics = get_sfxn('sterics') # self.sfxn_sterics.set_weight(rt.core.scoring.ScoreType.fa_atr, 1.00) # self.sfxn_sterics.set_weight(rt.core.scoring.ScoreType.fa_rep, 0.55) self.sfxn_minimize = get_sfxn('minimize')
def get_cli_args(argv=None, parent=None, **kw): parser = default_cli_parser(parent, **kw) argv = sys.argv[1:] if argv is None else argv argv = rp.app.options.make_argv_with_atfiles(argv, **kw) options = parser.parse_args(argv) # options = process_cli_args(options, **kw) return rp.Bunch(options)
def get_rotclouds(**kw): kw = rp.Bunch(kw) chiresl_asp1 = kw.chiresl_asp1 / kw.scale_number_of_rotamers chiresl_asp2 = kw.chiresl_asp2 / kw.scale_number_of_rotamers chiresl_cys1 = kw.chiresl_cys1 / kw.scale_number_of_rotamers chiresl_cys2 = kw.chiresl_cys2 / kw.scale_number_of_rotamers chiresl_his1 = kw.chiresl_his1 / kw.scale_number_of_rotamers chiresl_his2 = kw.chiresl_his2 / kw.scale_number_of_rotamers chiresl_glu1 = kw.chiresl_glu1 / kw.scale_number_of_rotamers chiresl_glu2 = kw.chiresl_glu2 / kw.scale_number_of_rotamers chiresl_glu3 = kw.chiresl_glu3 / kw.scale_number_of_rotamers os.makedirs(kw.rotcloud_cache, exist_ok=True) params = (kw.chiresl_his1, kw.chiresl_his2, kw.chiresl_cys1, kw.chiresl_cys2, kw.chiresl_asp1, kw.chiresl_asp2, kw.chiresl_glu1, kw.chiresl_glu2, kw.chiresl_glu3, kw.maxdun_cys, kw.maxdun_asp, kw.maxdun_glu, kw.maxdun_his) ident = mof.util.hash_str_to_int(str(params)) cache_file = kw.rotcloud_cache + '/%i.pickle' % ident if os.path.exists(cache_file): lC, lD, lE, lH, lJ, dC, dD, dE, dH, dJ = rp.util.load(cache_file) else: print('building rotamer clouds') chi_range = lambda resl: np.arange(-180, 180, resl) chi_asp = [chi_range(x) for x in (chiresl_asp1, chiresl_asp2)] chi_cys = [chi_range(x) for x in (chiresl_cys1, chiresl_cys2)] chi_his = [chi_range(x) for x in (chiresl_his1, chiresl_his2)] chi_glu = [ chi_range(x) for x in (chiresl_glu1, chiresl_glu2, chiresl_glu3) ] lC = mof.rotamer_cloud.RotCloudCysZN(grid=chi_cys, max_dun_score=4.0) lD = mof.rotamer_cloud.RotCloudAspZN(grid=chi_asp, max_dun_score=5.0) lE = mof.rotamer_cloud.RotCloudGluZN(grid=chi_glu, max_dun_score=5.0) lH = mof.rotamer_cloud.RotCloudHisZN(grid=chi_his, max_dun_score=5.0) lJ = mof.rotamer_cloud.RotCloudHisdZN(grid=chi_his, max_dun_score=5.0) dC = mof.rotamer_cloud.RotCloudDCysZN(grid=chi_cys, max_dun_score=4.0) dD = mof.rotamer_cloud.RotCloudDAspZN(grid=chi_asp, max_dun_score=5.0) dE = mof.rotamer_cloud.RotCloudDGluZN(grid=chi_glu, max_dun_score=5.0) dH = mof.rotamer_cloud.RotCloudDHisZN(grid=chi_his, max_dun_score=5.0) dJ = mof.rotamer_cloud.RotCloudDHisdZN(grid=chi_his, max_dun_score=5.0) rp.util.dump([lC, lD, lE, lH, lJ, dC, dD, dE, dH, dJ], cache_file) return dict(lC=lC, lD=lD, lE=lE, lH=lH, lJ=lJ, dC=dC, dD=dD, dE=dE, dH=dH, dJ=dJ)
def test_xtal_build_p213(): arg = rp.Bunch() arg.min_cell_size = 0 arg.max_cell_size = 999 arg.clash_dis = 3.0, arg.contact_dis = 7.0, arg.min_contacts = 0, arg.max_sym_score = 9e9, pose = pose_from_file(path_to_test_data('test_xtal_build_p213.pdb')) xtal_posess = xtal_build( pdb_name='testpdb', xspec=xtal_spec.get_xtal_spec('p213'), pose=pose, peptide_sym='C3', peptide_orig=np.array([0, 0, 0, 1]), peptide_axis=np.array([0, 0, 1, 0]), metal_sym='C3', metal_origin=np.array([6.21626192, -9.70902624, 5.32956683, 1.]), metal_sym_axis=np.array([-0.55345815, -0.76326468, -0.33333333, 0.]), rpxbody=rp.Body(pose), tag='test_xtal_build_p213', **arg, ) xalign, xpose, bodypdb = xtal_posess[0] print('verify bb coords') assert np.allclose( util.coord_find(xpose, 1, 'CA'), [-2.33104726, -4.58076386, -11.17135244], ) assert np.allclose( util.coord_find(xpose, 2, 'CA'), [-5.24447638, -2.71997589, -12.75316055], ) assert np.allclose( util.coord_find(xpose, 3, 'CA'), [-5.3331455, -4.53568805, -16.09169707], ) print('verify space group and unit cell') assert xpose.pdb_info().crystinfo().spacegroup() == 'P 21 3' assert np.allclose(xpose.pdb_info().crystinfo().A(), 30.354578479691444) # print('test_xtal_build_p213') print('verify xtal alignment') xalign_should_be = np.array([ [-0.47930882, -0.6610066, 0.57735027, -7.73090447], [0.81210292, -0.08459031, 0.57735027, -7.73090447], [-0.3327941, 0.74559691, 0.57735027, -7.73090447], [0., 0., 0., 1.], ]) assert np.allclose(xalign, xalign_should_be, atol=1e-5)
def get_sfxn(tag='cli', **kw): kw = rp.Bunch(kw) tag = tag.lower() if tag is 'cli': return scoring.get_score_function() elif tag is 'rotamer': get_sfxn_weights(kw.sfxn_rotamer_weights) return get_sfxn_weights(kw.sfxn_rotamer_weights) elif tag is 'sterics': return get_sfxn_weights(kw.sfxn_sterics_weights) elif tag is 'minimize': return get_sfxn_weights(kw.sfxn_minimize_weights) else: return get_sfxn_weights(tag) raise ValueError(f'unknown rosetta scorefunction tag: {tag}')
def test_xtal_search_2res_i213(c3_peptide, rotcloud_asp, rotcloud_his): arg = rp.Bunch() arg.max_bb_redundancy = 1.0 arg.err_tolerance = 1.5 arg.dist_err_tolerance = 1.0 arg.angle_err_tolerance = 15 arg.min_dist_to_z_axis = 6.0 arg.sym_axes_angle_tolerance = 5.0 arg.angle_to_cart_err_ratio = 20.0 arg.max_dun_score arg.min_cell_size = 0 arg.max_cell_size = 999 arg.clash_dis = 3.0 arg.contact_dis = 7.0 arg.min_contacts = 0 arg.max_sym_score = 9e9 arg.max_2res_score = 10 search_spec = mof.xtal_search.XtalSearchSpec( spacegroup='i213', pept_orig=np.array([0, 0, 0, 1]), pept_axis=np.array([0, 0, 1, 0]), max_dun_score=arg.max_dun_score, sym_of_ligand=dict(HZ3='C3'), ligands=['HZ3'], ) r = mof.xtal_search.xtal_search_two_residues( search_spec, c3_peptide, rotcloud_his, rotcloud_asp, **arg, ) assert len(r) is 1 assert np.allclose(r[0].xalign, [ [-0.77574427, -0.25473024, 0.57735027, 6.70142185], [0.608475, -0.54444912, 0.57735027, 6.70142185], [0.16726927, 0.79917937, 0.57735027, 6.70142185], [0., 0., 0., 1.], ], atol=0.0001)
log = logging.getLogger(__name__) data_dir = os.path.dirname(__file__) motifs_dir = str(os.path.join(data_dir, "motifs")) params_dir = str(os.path.join(data_dir, "rosetta_params")) weights_dir = str(os.path.join(data_dir, "rosetta_weights")) frank_space_groups = os.path.join(data_dir, "crystals_from_point.csv") peptides_dir = os.path.join(data_dir, "peptides") a_c3_peptide = os.path.join(peptides_dir, "c3_21res_c.101.12_0001.pdb") params = rp.Bunch( HZ3=str(os.path.join(motifs_dir, "HZ3.params")), HZD=str(os.path.join(motifs_dir, "HZD.params")), HZ4=str(os.path.join(motifs_dir, "HZ4.params")), VZN=str(os.path.join(params_dir, "VZN.params")), ) all_params_files = " ".join(params.values()) def c3_peptide(): return pyrosetta.pose_from_file( os.path.join(data_dir, 'peptides/c3_21res_c.107.7_0001.pdb')) def rotcloud_asp_small(): return load(os.path.join(data_dir, 'rotcloud_asp_small.pickle'))
def xtal_build( pdb_name, xspec, aa1, aa2, pose, peptide_sym, peptide_orig, peptide_axis, metal_sym, metal_origin, metal_sym_axis, rpxbody, tag, clash_dis, contact_dis, min_contacts, max_sym_score, debug=False, **kw, ): kw = rp.Bunch(kw) if not kw.timer: kw.timer = rp.Timer().start() lj_sfxn = get_sfxn('sterics') sym1 = xspec.sym1 orig1 = xspec.orig1 axis1 = xspec.axis1 axis1d = xspec.axis1d sym2 = xspec.sym2 orig2 = xspec.orig2 axis2 = xspec.axis2 axis2d = xspec.axis2d dihedral = xspec.dihedral if np.allclose(orig2, [0, 0, 0, 1]): sym1, sym2 = sym2, sym1 orig1, orig2 = orig2, orig1 axis1, axis2 = axis2, axis1 axis1d, axis2d = axis2d, axis1d swapped = True # hopefully won't need this assert sym1 == metal_sym assert sym2 == peptide_sym # axis2 = np.array([0.57735, 0.57735, 0.57735, 0]) # axis1 = np.array([1, 0, 0, 0]) # orig2 = np.array([0.5, 0.5, 0, 1]) elif np.allclose(orig1, [0, 0, 0, 1]): # assert np.allclose(orig1, [0, 0, 0, 1]) assert sym1 == peptide_sym assert sym2 == metal_sym swapped = False # axis1 = np.array([0.57735, 0.57735, 0.57735, 0]) # assert 0, 'maybe ok, check this new branch' else: # print('both sym elements not at origin') pass # raise NotImplementedError('both sym elements not at origin') if sym1 == peptide_sym: pt1, ax1 = peptide_orig, peptide_axis pt2, ax2 = metal_origin, metal_sym_axis first_is_peptide = True else: pt1, ax1 = metal_origin, metal_sym_axis pt2, ax2 = peptide_orig, peptide_axis first_is_peptide = False nfold1 = float(str(sym1)[1]) nfold2 = float(str(sym2)[1]) ax1 = ax1 / np.linalg.norm(ax1) ax2 = ax2 / np.linalg.norm(ax2) # print(rp.homog.line_angle(metal_sym_axis, peptide_axis), np.radians(dihedral)) assert np.allclose(rp.homog.line_angle(metal_sym_axis, peptide_axis), np.radians(dihedral), atol=1e-3) assert np.allclose(rp.homog.line_angle(ax1, ax2), np.radians(dihedral), atol=1e-3) # print(rp.homog.line_angle(ax1, ax2), np.radians(dihedral), dihedral) # print('sym1', sym1, orig1, axis1, ax1) # print('sym2', sym2, orig2, axis2, ax2) # # print('== xtal_build ==') # Xalign, _ = rp.homog.align_lines_isect_axis2(pt1, ax1, pt2, ax2, axis1, orig1, axis2, orig2) Xalign, scale = rp.homog.scale_translate_lines_isect_lines(pt1, ax1, pt2, ax2, orig1, axis1, orig2, axis2) xpt1, xax1 = Xalign @ pt1, Xalign @ ax1 xpt2, xax2 = Xalign @ pt2, Xalign @ ax2 # print('aligned1', xpt1, xax1) # print('aligned2', xpt2, xax2) assert np.allclose(rp.homog.line_angle(xax1, axis1), 0.0, atol=0.001) assert np.allclose(rp.homog.line_angle(xax2, axis2), 0.0, atol=0.001) # from previous req that ax1 isect the origin?? # assert np.allclose(rp.homog.line_angle(xpt1, axis1), 0.0, atol=0.001) isect_error2 = rp.homog.line_line_distance_pa(xpt2, xax2, [0, 0, 0, 1], orig2) assert np.allclose(isect_error2, 0, atol=0.001) # isect = rp.homog.line_line_closest_points_pa(xpt2, xax2, [0, 0, 0, 1], orig2) # isect = (isect[0] + isect[1]) / 2 # orig = orig2 # not always?? # celldims = [isect[i] / o for i, o in enumerate(orig[:3]) if abs(o) > 0.001] celldims = scale[:3] assert np.allclose(min(celldims), max(celldims), atol=0.001) celldim = abs(min(celldims)) if not (kw.min_cell_size <= celldim <= kw.max_cell_size): print(' ', xspec.spacegroup, pdb_name, aa1, aa2, 'Fail on cell_size', celldim) return [] nsym = int(peptide_sym[1]) assert pose.size() % nsym == 0 nres_asym = pose.size() // nsym xtal_pose = rt.protocols.grafting.return_region(pose, 1, nres_asym) solv_frac = mof.filters.approx_solvent_fraction(xtal_pose, xspec, celldim) if kw.max_solv_frac < solv_frac: print(' ', xspec.spacegroup, pdb_name, aa1, aa2, 'Fail on solv_frac', solv_frac) return [] # rt.numeric.xyzVec(hz[0], hz[1], hz[2])) xtal_pose.apply_transform_Rx_plus_v( xyzMat.cols(Xalign[0, 0], Xalign[1, 0], Xalign[2, 0], Xalign[0, 1], Xalign[1, 1], Xalign[2, 1], Xalign[0, 2], Xalign[1, 2], Xalign[2, 2]), xyzVec(Xalign[0, 3], Xalign[1, 3], Xalign[2, 3])) # check ZN sym center location vs zn position????????? # print('--------------') # print(celldim, orig1[:3], orig2[:3]) # print('--------------') if xspec.frames is None: # raise NotImplementedError('no sym frames for', xspec.spacegroup) print(f'{f" generate sym frames for {spec.spacegroup} ":}') dummy_scale = 100.0 if sym1 == peptide_sym: redundant_point = rp.homog.hpoint(dummy_scale * orig1[:3] + 10 * axis1[:3]) else: redundant_point = rp.homog.hpoint(dummy_scale * orig2[:3] + 10 * axis2[:3]) # redundant_point = rp.homog.rand_point() # redundant_point[:3] *= dummy_scale print('redundant_point', redundant_point) print(Xalign @ redundant_point) g1 = rp.homog.hrot(axis1, (2 * np.pi / nfold1) * np.arange(nfold1), dummy_scale * orig1[:3]) g2 = rp.homog.hrot(axis2, (2 * np.pi / nfold2) * np.arange(nfold2), dummy_scale * orig2[:3]) g = np.concatenate([g1, g2]) symxforms = list() count = 0 for x in rp.homog.expand_xforms(g, redundant_point=redundant_point, N=12, maxrad=3.0 * dummy_scale): symxforms.append(x) print(count) count += 1 # rp.dump(list(symxforms), 'i213_redundant111_n16_maxrad2.pickle') # symxforms = rp.load('i213_redundant111_n16_maxrad2_ORIG.pickle') print('num symframes', len(symxforms), type(symxforms[0])) symxforms = np.stack(symxforms, axis=0) print('symframes shape', symxforms.shape) symxforms[:, :3, 3] /= dummy_scale # print(np.around(symxforms[:, :3, 3], 3)) rp.dump(symxforms, 'new_symframes.pickle') symxforms[:, :3, 3] *= celldim rpxbody.move_to(Xalign) rpxbody.dump_pdb('body_I.pdb') for i, x in enumerate(symxforms): rpxbody.move_to(x @ Xalign) rpxbody.dump_pdb('body_%i.pdb' % i) assert 0, "must rerun with newly genrated symframes" symxforms = xspec.frames.copy() symxforms[:, :3, 3] *= celldim # g1 = rp.homog.hrot(axis1, (2 * np.pi / nfold1) * np.arange(0, nfold1), celldim * orig1[:3]) # g2 = rp.homog.hrot(axis2, (2 * np.pi / nfold2) * np.arange(0, nfold2), celldim * orig2[:3]) # # # print('g1', axis1.round(3), 360 / nfold1, (celldim * orig1[:3]).round(3)) # # # print('g2', axis2.round(3), 360 / nfold2, (celldim * orig2[:3]).round(3)) # if swapped: g1, g2 = g2, g1 # g = np.concatenate([g1, g2]) # # print('swapped', swapped) # redundant_point = (xpt1 + xax1) if first_is_peptide else (xpt2 + xax2) # # redundant_point = xpt1 if first_is_peptide else xpt2 # # print('redundancy point', redundant_point) # # # rpxbody.move_to(np.eye(4)) # # # rpxbody.dump_pdb('a_body.pdb') # rpxbody.move_to(Xalign) # # # print(0, Xalign @ rp.homog.hpoint([1, 2, 3])) # # rpxbody.dump_pdb('a_body_xalign.pdb') kw.timer.checkpoint() clash, tot_ncontact = False, 0 rpxbody_pdb, ir_ic = rpxbody.str_pdb(warn_on_chain_overflow=False, use_orig_coords=False) body_xalign = rpxbody.copy() body_xalign.move_to(Xalign) # body_xalign.dump_pdb('body_xalign.pdb') prev = [np.eye(4)] for i, x in enumerate(symxforms): # rp.homog.expand_xforms(g, redundant_point=redundant_point, N=6, maxrad=30)): if np.allclose(x, np.eye(4), atol=1e-4): assert 0 rpxbody.move_to(x @ Xalign) # rpxbody.dump_pdb('clashcheck%02i.pdb' % i) if debug: pdbstr, ir_ic = rpxbody.str_pdb(start=ir_ic, warn_on_chain_overflow=False, use_orig_coords=False) rpxbody_pdb += pdbstr if np.any(rpxbody.intersect(rpxbody, np.stack(prev) @ Xalign, x @ Xalign, mindis=clash_dis)): clash = True print(' ', xspec.spacegroup, pdb_name, aa1, aa2, 'Fail on xtal clash', f'sub{i+1}') return [] ncontact = rpxbody.contact_count(body_xalign, maxdis=contact_dis) tot_ncontact += ncontact prev.append(x) # if clash and debug: # for xprev in prev: # # print(xprev.shape, (xprev @ Xalign).shape, (x @ Xalign).shape) # if rpxbody.intersect(rpxbody, xprev @ Xalign, x @ Xalign, mindis=3.0): # show_body_isect(rpxbody, Xalign, maxdis=3.0) # rp.util.dump_str(rpxbody_pdb, 'sym_bodies.pdb') # assert 0 if tot_ncontact < min_contacts: print(' ', xspec.spacegroup, pdb_name, aa1, aa2, 'Fail on ncontact', tot_ncontact) return [] kw.timer.checkpoint('clash_check') # for i, x in enumerate(symxforms): # # print('sym xform %02i' % i, rp.homog.axis_ang_cen_of(x) # rpxbody.move_to(x @ Xalign) # rpxbody.dump_pdb('clashframe_%02i.pdb' % i) # assert 0 # print('!!!!!!!!!!!!!!!! debug clash check !!!!!!!!!!!!!!!!!!!!!!!!!') # rpxbody.move_to(Xalign) # rpxbody.dump_pdb('body.pdb') # symxforms = rp.homog.expand_xforms(g, redundant_point=redundant_point, N=8, maxrad=30) # for i, x in enumerate(symxforms): # # print('sym xform %02i' % i, rp.homog.axis_ang_cen_of(x)) # rpxbody.move_to(x @ Xalign) # rpxbody.dump_pdb('clashcheck%02i.pdb' % i) # if rpxbody.intersect(rpxbody, Xalign, x @ Xalign, mindis=3.0): # util.show_body_isect(rpxbody, Xalign, maxdis=3.0) # rp.util.dump_str(rpxbody_pdb, 'sym_bodies.pdb') # assert 0 # assert 0, 'xtal build after clashcheck' # fname = f'{tag}_body_xtal.pdb' # print('dumping checked bodies', fname) ci = rt.core.io.CrystInfo() ci.A(celldim) # cell dimensions ci.B(celldim) ci.C(celldim) ci.alpha(90) # cell angles ci.beta(90) ci.gamma(90) ci.spacegroup(xspec.spacegroup) # sace group pi = rt.core.pose.PDBInfo(xtal_pose) pi.set_crystinfo(ci) xtal_pose.pdb_info(pi) nonbonded_energy = 0 if max_sym_score < 1000: sympose = xtal_pose.clone() rt.protocols.cryst.MakeLatticeMover().apply(sympose) syminfo = rt.core.pose.symmetry.symmetry_info(sympose) # rp.util.dump_str(rpxbody_pdb, 'symbodies.pdb') lj_sfxn(sympose) nasym = len(xtal_pose.residues) nchain = syminfo.subunits() # sympose.num_chains() bonded_subunits = [] nterm = sympose.residue(1).xyz('N') cterm = sympose.residue(nasym).xyz('C') for i in range(1, nchain): nres = i * nasym + 1 cres = i * nasym + nasym if 2 > cterm.distance(sympose.residue(nres).xyz('N')): bonded_subunits.append(i + 1) if 2 > nterm.distance(sympose.residue(cres).xyz('C')): bonded_subunits.append(i + 1) energy_graph = sympose.energies().energy_graph() eweights = sympose.energies().weights() nonbonded_energy = 0 for ichain in range(1, nchain): if ichain + 1 in bonded_subunits: continue for i in range(nasym): ir = ichain + i + 1 for j in range(nasym): jr = j + 1 edge = energy_graph.find_edge(ir, jr) if not edge: continue nonbonded_energy += edge.dot(eweights) # print('nonbonded_energy', nonbonded_energy) if nonbonded_energy > max_sym_score: print(' ', xspec.spacegroup, pdb_name, aa1, aa2, 'Fail on nonbonded_energy(max_sym_score)', nonbonded_energy) return [] kw.timer.checkpoint('make sympose and "nonbonded" score') znpos = Xalign @ metal_origin znres = make_residue('VZN') xtal_pose.append_residue_by_jump(znres, 1) znresi = len(xtal_pose.residues) znpos = xyzVec(*znpos[:3]) zndelta = znpos - xtal_pose.residue(znresi).xyz(1) for ia in range(1, xtal_pose.residue(znresi).natoms() + 1): newxyz = zndelta + xtal_pose.residue(znresi).xyz(ia) # print(xtal_pose.residue(znresi).name(), ia, xtal_pose.residue(znresi).atom_name(ia), newxyz) xtal_pose.set_xyz(AtomID(ia, znresi), newxyz) # xtal_pose.dump_pdb('a_xtal_pose.pdb') # assert 0 # rp.util.dump_str(rpxbody_pdb, 'a_symframes.pdb') # assert 0 return [(Xalign, xtal_pose, rpxbody_pdb, tot_ncontact, nonbonded_energy, solv_frac)]
def minimize_mof_xtal(sfxn, xspec, pose, debug=False, **kw): kw = rp.Bunch(kw) # try: # print(''' # minimize.py score initial.................... 687.825 # minimize.py: score before chem bonds......... 687.825 # minimize.py: score after chem bonds.......... 166.551 # minimize.py: score after chainbreaks......... 166.551 # minimize.py: score after metal olap ......... 166.551 # minimize.py: score after metal dist ......... 176.766 # minimize.py: score after metal dir........... 275.546 # minimize.py: score after lig angle added..... 290.724 # minimize.py: score after min no scale........ 111.465 # ========================================================== # '''.strip()) # os.remove('before.pdb') # os.remove('zafter.pdb') # except: # pass nresasym = pose.size() beg = 1 end = nresasym - 1 metalres = rts.name_map('ZN') metalname = 'ZN' metalresnos = [nresasym, 2 * nresasym] # TODO.. make not stupid metalnbonds = 4 metalaid = AtomID(1, metalresnos[0]) # cst_ang_metal = 109.47 # cst_dis_metal = 2.2 # cst_sd_metal_olap = 0.01 # cst_sd_metal_dir = 0.4 # cst_sd_metal_lig_dist = 0.2 # cst_sd_metal_lig_ang = 0.4 # cst_sd_metal_coo = 0.5 # cst_sd_cut_dis = 0.01 # cst_sd_cut_ang = 0.01 # cst_sd_cut_dih = 0.1 pose = pose.clone() r.core.pose.remove_lower_terminus_type_from_pose_residue(pose, beg) r.core.pose.remove_upper_terminus_type_from_pose_residue(pose, end) for ir in range(1, pose.size() + 1): if 'HIS' in pose.residue(ir).name(): newname = pose.residue(ir).name().replace('HIS', 'HIS_D') newname = newname.replace('_D_D', '') r.core.pose.replace_pose_residue_copying_existing_coordinates( pose, ir, rts.name_map(newname)) if False: tmp = pose.clone() r.core.pose.replace_pose_residue_copying_existing_coordinates( tmp, metalresnos[0], metalres) makelattice(tmp) tmp.dump_pdb('before.pdb') makelattice(pose) if debug: print( f'minimize.py score initial.................... {sfxn(pose):10.3f}' ) # print_nonzero_energies(sfxn, pose) syminfo = r.core.pose.symmetry.symmetry_info(pose) symdofs = syminfo.get_dofs() allowed_jumps = list() # for jid, dofinfo in symdofs.items(): # # if dofinfo.allow_dof(1) and not any(dofinfo.allow_dof(i) for i in range(2, 7)): # allowed_jumps.append(jid) # print('minimize_mof_xtal allowed jumps:', allowed_jumps) nxyz = pose.residue(beg).xyz('N') cxyz = pose.residue(end).xyz('C') nac, cac = None, None # (N/C)-(a)djacent (c)hain for isub in range(1, syminfo.subunits()): othern = pose.residue((isub + 0) * nresasym + 1).xyz('N') otherc = pose.residue((isub + 1) * nresasym - 1).xyz('C') if nxyz.distance(otherc) < 2.0: cac = (isub + 1) * nresasym - 1 if cxyz.distance(othern) < 2.0: nac = (isub + 0) * nresasym + 1 assert nac and cac, 'backbone is weird?' if debug: print('peptide connection 1:', cac, beg) if debug: print('peptide_connection 2:', end, nac) # pose.dump_pdb('check_cuts.pdb') # assert 0 f_metal_lig_dist = r.core.scoring.func.HarmonicFunc( kw.cst_dis_metal, kw.cst_sd_metal_lig_dist) f_metal_lig_ang = r.core.scoring.func.HarmonicFunc( np.radians(kw.cst_ang_metal), kw.cst_sd_metal_lig_ang) f_metal_olap = r.core.scoring.func.HarmonicFunc(0.0, kw.cst_sd_metal_olap) f_point_at_metal = r.core.scoring.func.HarmonicFunc( 0.0, kw.cst_sd_metal_dir) f_metal_coo = r.core.scoring.func.CircularHarmonicFunc( 0.0, kw.cst_sd_metal_coo) f_cut_dis = r.core.scoring.func.HarmonicFunc(1.328685, kw.cst_sd_cut_dis) f_cut_ang_cacn = r.core.scoring.func.HarmonicFunc(2.028, kw.cst_sd_cut_ang) f_cut_ang_cnca = r.core.scoring.func.HarmonicFunc(2.124, kw.cst_sd_cut_ang) f_cut_dih = r.core.scoring.func.CircularHarmonicFunc( np.pi, kw.cst_sd_cut_dih) f_cut_dihO = r.core.scoring.func.CircularHarmonicFunc( 0.00, kw.cst_sd_cut_dih) ################### check cutpoint ################## conf = pose.conformation().clone() assert r.core.conformation.symmetry.is_symmetric(conf) # print(pose.pdb_info().crystinfo()) pi = pose.pdb_info() # conf.detect_bonds() conf.declare_chemical_bond(cac, 'C', beg, 'N') # conf.declare_chemical_bond(end, 'N', nac, 'N') pose.set_new_conformation(conf) pose.set_new_energies_object(r.core.scoring.symmetry.SymmetricEnergies()) pose.pdb_info(pi) if debug: print( f'minimize.py: score after chem bonds.......... {sfxn(pose):10.3f}' ) #############################################3 cst_cut, cst_lig_dis, cst_lig_ang, cst_lig_ori = list(), list(), list( ), list() ############### chainbreaks ################3 # this doesn't behave well... # # 39 C / 1 OVU1 # # 39 OVL1 / 1 N # # 29 OVL2 / CA # r.core.pose.add_variant_type_to_pose_residue(pose, 'CUTPOINT_UPPER', beg) # r.core.pose.add_variant_type_to_pose_residue(pose, 'CUTPOINT_LOWER', end) # cres1 = pose.residue(cac) # nres1 = pose.residue(1) # cres2 = pose.residue(end) # nres2 = pose.residue(nac) # # Apc = r.core.scoring.constraints.AtomPairConstraint # # getaid = lambda p, n, i: AtomID(p.residue(i).atom_index(n.strip()), i) # for cst in [ # Apc(getaid(pose, 'C ', cac), getaid(pose, 'OVU1', beg), f_cut), # Apc(getaid(pose, 'OVL1', cac), getaid(pose, 'N ', beg), f_cut), # Apc(getaid(pose, 'OVL2', cac), getaid(pose, 'CA ', beg), f_cut), # Apc(getaid(pose, 'C ', end), getaid(pose, 'OVU1', nac), f_cut), # Apc(getaid(pose, 'OVL1', end), getaid(pose, 'N ', nac), f_cut), # Apc(getaid(pose, 'OVL2', end), getaid(pose, 'CA ', nac), f_cut), # ]: # pose.add_constraint(cst) cst_cut.append(addcst_dis(pose, cac, 'C ', beg, 'N', f_cut_dis)) cst_cut.append(addcst_dis(pose, end, 'C ', nac, 'N', f_cut_dis)) if debug: print( f'minimize.py: score after chainbreak dis...... {sfxn(pose):10.3f}' ) cst_cut.append( addcst_ang(pose, cac, 'CA', cac, 'C', beg, 'N ', f_cut_ang_cacn)) cst_cut.append( addcst_ang(pose, cac, 'C ', beg, 'N', beg, 'CA', f_cut_ang_cnca)) cst_cut.append( addcst_ang(pose, end, 'CA', end, 'C', nac, 'N ', f_cut_ang_cacn)) cst_cut.append( addcst_ang(pose, end, 'C ', nac, 'N', nac, 'CA', f_cut_ang_cnca)) if debug: print( f'minimize.py: score after chainbreak ang...... {sfxn(pose):10.3f}' ) # print(r.numeric.dihedral( # pose.residue(cac).xyz('CA'), # pose.residue(cac).xyz('C'), # pose.residue(beg).xyz('N'), # pose.residue(beg).xyz('CA'), # )) cst_cut.append( addcst_dih(pose, cac, 'CA', cac, 'C', beg, 'N ', beg, 'CA', f_cut_dih)) cst_cut.append( addcst_dih(pose, end, 'CA', end, 'C', nac, 'N ', nac, 'CA', f_cut_dih)) cst_cut.append( addcst_dih(pose, cac, 'O ', cac, 'C', beg, 'N ', beg, 'CA', f_cut_dihO)) cst_cut.append( addcst_dih(pose, end, 'O ', end, 'C', nac, 'N ', nac, 'CA', f_cut_dihO)) if debug: print( f'minimize.py: score after chainbreak dihedral. {sfxn(pose):10.3f}' ) ############## metal constraints ################ for i, j in [(i, j) for i in metalresnos for j in metalresnos if i < j]: addcst_dis(pose, i, metalname, j, metalname, f_metal_olap) if debug: print( f'minimize.py: score after metal olap ......... {sfxn(pose):10.3f}' ) allowed_elems = 'NOS' znpos = pose.residue(metalresnos[0]).xyz(1) znbonded = list() for ir in range(1, len(pose.residues) + 1): res = pose.residue(ir) if not res.is_protein(): continue for ia in range(5, res.nheavyatoms() + 1): aid = AtomID(ia, ir) elem = res.atom_name(ia).strip()[0] if elem in allowed_elems: xyz = pose.xyz(aid) dist = xyz.distance(znpos) if dist < 3.5: if res.atom_name(ia) in ( ' OD2', ' OE2'): # other COO O sometimes closeish continue znbonded.append(aid) if len(znbonded) != metalnbonds: print('WRONG NO OF LIGANDING ATOMS', len(znbonded)) for aid in znbonded: print( pose.residue(aid.rsd()).name(), pose.residue(aid.rsd()).atom_name(aid.atomno())) pose.dump_pdb('WRONG_NO_OF_LIGANDING_ATOMS.pdb') return None, None # raise ValueError(f'WRONG NO OF LIGANDING ATOMS {len(znbonded)}') # metal/lig distance constraints for i, aid in enumerate(znbonded): cst = r.core.scoring.constraints.AtomPairConstraint( metalaid, aid, f_metal_lig_dist) cst_lig_dis.append(cst) pose.add_constraint(cst) if debug: print( f'minimize.py: score after metal dist ......... {sfxn(pose):10.3f}' ) # for aid in znbonded: # print(aid.rsd(), aid.atomno(), # pose.residue(aid.rsd()).name(), # pose.residue(aid.rsd()).atom_name(aid.atomno())) # assert 0 # lig/metal/lig angle constraints (or dihedral in-place constraint for COO) # TODO kinda hacky... will need to be more general? for i, aid in enumerate(znbonded): ir, res = aid.rsd(), pose.residue(aid.rsd()) if all(_ not in res.name() for _ in 'ASP CYS HIS GLU'.split()): assert 0, f'unrecognized res {res.name()}' if any(_ in res.name() for _ in 'ASP GLU'.split()): # metal comes off of OD1/OE1 ir, coo = aid.rsd(), ('OD1 CG OD2' if 'ASP' in res.name() else 'OE1 CD OE2').split() cst_lig_ori.append( addcst_dih(pose, ir, coo[0], ir, coo[1], ir, coo[2], metalaid.rsd(), metalname, f_metal_coo)) else: if 'HIS' in res.name(): aname = 'HD1' if res.has('HD1') else 'HE2' if 'CYS' in res.name(): aname = 'HG' cst_lig_ori.append( addcst_ang(pose, ir, res.atom_name(aid.atomno()), metalaid.rsd(), metalname, ir, aname, f_point_at_metal)) # cst = r.core.scoring.constraints.AngleConstraint(aid, metalaid, aid2, f_point_at_metal) # pose.add_constraint(cst) if debug: print( f'minimize.py: score after metal dir........... {sfxn(pose):10.3f}' ) for i, iaid in enumerate(znbonded): for j, jaid in enumerate(znbonded[:i]): # pripnt(i, j) cst = r.core.scoring.constraints.AngleConstraint( iaid, metalaid, jaid, f_metal_lig_ang) cst_lig_ang.append(cst) pose.add_constraint(cst) if debug: print( f'minimize.py: score after lig angle added..... {sfxn(pose):10.3f}' ) ################ minimization ######################### movemap = r.core.kinematics.MoveMap() movemap.set_bb(True) movemap.set_chi(True) movemap.set_jump(False) for i in allowed_jumps: movemap.set_jump(True, i) minimizer = r.protocols.minimization_packing.symmetry.SymMinMover( movemap, sfxn, 'lbfgs_armijo_nonmonotone', 0.01, True) # tol, nblist if sfxn.has_nonzero_weight(r.core.scoring.ScoreType.cart_bonded): minimizer.cartesian(True) minimizer.apply(pose) if debug: print( f'minimize.py: score after min no scale........ {sfxn(pose):10.3f}' ) # printscores(sfxn, pose) kw.timer.checkpoint(f'min scale 1.0') asym = r.core.pose.Pose() r.core.pose.symmetry.extract_asymmetric_unit(pose, asym, False) r.core.pose.replace_pose_residue_copying_existing_coordinates( asym, metalresnos[0], metalres) # asym.dump_pdb('asym.pdb') # for ir in metalresnos: # r.core.pose.replace_pose_residue_copying_existing_coordinates(pose, ir, metalres) # pose.dump_pdb('zafter.pdb') if debug: print(kw.timer) info = rp.Bunch() info.score = sfxn(pose) ############### score component stuff ################ st = r.core.scoring.ScoreType etot = pose.energies().total_energies() info.score_fa_atr = (etot[st.fa_atr]) info.score_fa_rep = (etot[st.fa_rep]) info.score_fa_sol = (etot[st.fa_sol]) info.score_lk_ball = (etot[st.lk_ball] + etot[st.lk_ball_iso] + etot[st.lk_ball_bridge] + etot[st.lk_ball_bridge_uncpl]) info.score_fa_elec = (etot[st.fa_elec] + etot[st.fa_intra_elec]) info.score_hbond_sr_bb = (etot[st.hbond_sr_bb] + etot[st.hbond_lr_bb] + etot[st.hbond_bb_sc] + etot[st.hbond_sc]) info.score_dslf_fa13 = (etot[st.dslf_fa13]) info.score_atom_pair_constraint = (etot[st.atom_pair_constraint]) info.score_angle_constraint = (etot[st.angle_constraint]) info.score_dihedral_constraint = (etot[st.dihedral_constraint]) info.score_omega = (etot[st.omega]) info.score_rotamer = (etot[st.fa_dun] + etot[st.fa_dun_dev] + etot[st.fa_dun_rot] + etot[st.fa_dun_semi] + etot[st.fa_intra_elec] + etot[st.fa_intra_rep] + etot[st.fa_intra_atr_xover4] + etot[st.fa_intra_rep_xover4] + etot[st.fa_intra_sol_xover4]) info.score_ref = (etot[st.ref]) info.score_rama_prepro = (etot[st.rama_prepro]) info.score_cart_bonded = (etot[st.cart_bonded]) info.score_gen_bonded = (etot[st.gen_bonded]) ############### cst stuff ################ pose.remove_constraints() info.score_wo_cst = sfxn(pose) [pose.add_constraint(cst) for cst in cst_cut] info.score_cst_cut = sfxn(pose) - info.score_wo_cst pose.remove_constraints() [pose.add_constraint(cst) for cst in cst_lig_dis] [pose.add_constraint(cst) for cst in cst_lig_ang] [pose.add_constraint(cst) for cst in cst_lig_ori] info.score_cst_lig_ori = sfxn(pose) - info.score_wo_cst pose.remove_constraints() [pose.add_constraint(cst) for cst in cst_lig_dis] info.score_cst_lig_dis = sfxn(pose) - info.score_wo_cst pose.remove_constraints() [pose.add_constraint(cst) for cst in cst_lig_ang] info.score_cst_lig_ang = sfxn(pose) - info.score_wo_cst pose.remove_constraints() [pose.add_constraint(cst) for cst in cst_lig_ori] info.score_cst_lig_ori = sfxn(pose) - info.score_wo_cst pose.remove_constraints() return asym, info
def xtal_search_two_residues( search_spec, pose, rotcloud1base, rotcloud2base, err_tolerance, dist_err_tolerance, angle_err_tolerance, min_dist_to_z_axis, sym_axes_angle_tolerance, angle_to_cart_err_ratio, debug=False, **kw, ): kw = rp.Bunch(kw) if not kw.timer: kw.timer = rp.Timer().start() kw.timer.checkpoint() spec = search_spec xspec = spec.xtal_spec aa1 = rotcloud1base.amino_acid aa2 = rotcloud2base.amino_acid results = list() dont_replace_these_aas = [spec.rts.name_map('CYS'), spec.rts.name_map('PRO')] farep_orig = search_spec.sfxn_sterics(pose) p_n = pose.pdb_info().name().split('/')[-1] # gets rid of the ".pdb" at the end of the pdb name pdb_name = p_n[:-4] print(f' {pdb_name} searching', aa1, aa2) # check the symmetry type of the pdb last_res = rt.core.pose.chain_end_res(pose).pop() total_res = int(last_res) sym_num = 3 # pose.chain(last_res) sym = 3 # int(sym_num) if sym_num < 2: print('bad pdb', p_n) return list() asym_nres = int(total_res / sym) peptide_sym = "C%i" % sym_num rpxbody = rp.Body(pose) for ires1 in range(1, asym_nres + 1): # if pose.residue_type(ires1) not in (spec.rts.name_map('ALA'), spec.rts.name_map('DALA')): if pose.residue_type(ires1) in dont_replace_these_aas: continue stub1 = rpxbody.stub[ires1 - 1] kw.timer.checkpoint('xtal_search') rots1ok = min_dist_to_z_axis < np.linalg.norm( (stub1 @ rotcloud1base.rotframes)[:, :2, 3], axis=1) if 0 == np.sum(rots1ok): continue rotcloud1 = rotcloud1base.subset(rots1ok) rotframes1 = stub1 @ rotcloud1.rotframes # rotcloud1.dump_pdb(f'cloud_a_{ires1:02}.pdb', position=stub1) kw.timer.checkpoint('position rotcloud') range2 = range(1, int(total_res) + 1) if rotcloud1base is rotcloud2base: range2 = range(ires1 + 1, int(total_res) + 1) for ires2 in range2: if ires1 == ((ires2 - 1) % asym_nres + 1): continue if pose.residue_type(ires2) in dont_replace_these_aas: continue stub2 = rpxbody.stub[ires2 - 1] # rotcloud2.dump_pdb(f'cloud_b_{ires2:02}.pdb', position=stub2) kw.timer.checkpoint('xtal_search') rots2ok = min_dist_to_z_axis < np.linalg.norm( (stub2 @ rotcloud2base.rotframes)[:, :2, 3], axis=1) if 0 == np.sum(rots2ok): continue rotcloud2 = rotcloud2base.subset(rots2ok) rotframes2 = stub2 @ rotcloud2.rotframes kw.timer.checkpoint('rotcloud positioning') dist = rotframes1[:, :, 3].reshape(-1, 1, 4) - rotframes2[:, :, 3].reshape(1, -1, 4) dist = np.linalg.norm(dist, axis=2) kw.timer.checkpoint('rotcloud dist') # if np.min(dist) < 1.0: # print(f'{ires1:02} {ires2:02} {np.sort(dist.flat)[:5]}') dot = np.sum( rotframes1[:, :, 0].reshape(-1, 1, 4) * rotframes2[:, :, 0].reshape(1, -1, 4), axis=2) ang = np.degrees(np.arccos(np.clip(dot, -1, 1))) ang_delta = np.abs(ang - 109.4712206) kw.timer.checkpoint('rotcloud ang') err = np.sqrt((ang_delta / angle_to_cart_err_ratio)**2 + dist**2) rot1err2 = np.min(err, axis=1) bestrot2 = np.argmin(err, axis=1) disterr = dist[np.arange(len(bestrot2)), bestrot2] angerr = ang_delta[np.arange(len(bestrot2)), bestrot2] ok = (rot1err2 < err_tolerance) ok *= (angerr < angle_err_tolerance) ok *= (disterr < dist_err_tolerance) # ok = rot1err2 < err_tolerance # ok = disterr < dist_err_tolerance # ok = angerr < angle_err_tolerance hits1 = np.argwhere(ok).reshape(-1) kw.timer.checkpoint('rotcloud match check') # hits = (ang_delta < angle_err_tolerance) * (dist < dist_err_tolerance) if len(hits1): hits2 = bestrot2[hits1] hits = np.stack([hits1, hits2], axis=1) # print( # f'stats {ires1:2} {ires2:2} {np.sum(ang_delta < 10):7} {np.sum(dist < 1.0):5} {np.sum(hits):3}' # ) for ihit, hit in enumerate(hits): frame1 = rotframes1[hit[0]] frame2 = rotframes2[hit[1]] kw.timer.checkpoint('xtal_search') parl = (frame1[:, 0] + frame2[:, 0]) / 2.0 perp = rp.homog.hcross(frame1[:, 0], frame2[:, 0]) metalaxis1 = rp.homog.hrot(parl, +45) @ perp metalaxis2 = rp.homog.hrot(parl, -45) @ perp symang1 = rp.homog.line_angle(metalaxis1, spec.pept_axis) symang2 = rp.homog.line_angle(metalaxis2, spec.pept_axis) match1 = np.abs(np.degrees(symang1) - xspec.dihedral) < sym_axes_angle_tolerance match2 = np.abs(np.degrees(symang2) - xspec.dihedral) < sym_axes_angle_tolerance if not (match1 or match2): continue matchsymang = symang1 if match1 else symang2 metal_axis = metalaxis1 if match1 else metalaxis2 if rp.homog.angle(metal_axis, spec.pept_axis) > np.pi / 2: metal_axis[:3] = -metal_axis[:3] metal_pos = (rotframes1[hit[0], :, 3] + rotframes2[hit[1], :, 3]) / 2.0 correction_axis = rp.homog.hcross(metal_axis, spec.pept_axis) correction_angle = np.abs(matchsymang - np.radians(xspec.dihedral)) # print('target', xspec.dihedral, '---------------------') # print(np.degrees(correction_angle)) # print(np.degrees(matchsymang)) # print('before', rp.homog.angle_degrees(metal_axis, spec.pept_axis)) for why_do_i_need_this in (-correction_angle, correction_angle): metal_axis_try = rp.homog.hrot(correction_axis, why_do_i_need_this) @ metal_axis if np.allclose(rp.homog.angle_degrees(metal_axis_try, spec.pept_axis), xspec.dihedral, atol=0.001): metal_axis = metal_axis_try break # print('after ', rp.homog.angle_degrees(metal_axis, spec.pept_axis)) assert np.allclose(rp.homog.angle_degrees(metal_axis, spec.pept_axis), xspec.dihedral, atol=0.001) kw.timer.checkpoint('axes geom checks') # pose.dump_pdb('before.pdb') pose2mut = mof.util.mutate_two_res(pose, ires1, aa1, rotcloud1.rotchi[hit[0]], ires2, aa2, rotcloud2.rotchi[hit[1]], sym_num) # pose2mut.dump_pdb('after.pdb') search_spec.sfxn_sterics(pose2mut) sc_2res = (pose2mut.energies().residue_total_energy(ires1) + pose2mut.energies().residue_total_energy(ires2)) sc_2res_orig = (pose.energies().residue_total_energy(ires1) + pose.energies().residue_total_energy(ires2)) kw.timer.checkpoint('mut_two_res') # print('scores', sc_2res, sc_2res_orig) # if sc_2res > kw.max_2res_score: continue if sc_2res - sc_2res_orig > kw.max_2res_score: continue tag = ('hit_%s_%s_%i_%i_%i' % (aa1, aa2, ires1, ires2, ihit)) kw.timer.checkpoint('xtal_search') xtal_poses = mof.xtal_build.xtal_build( pdb_name, xspec, aa1, aa2, pose2mut, peptide_sym, spec.pept_orig, spec.pept_axis, 'C2', metal_pos, metal_axis, rpxbody, tag, **kw, ) if not xtal_poses: continue # for Xalign, xtal_pose, rpxbody_pdb in xtal_poses: # xtal_pose.dump_pdb(tag + '_xtal.pdb') # rp.util.dump_str(rpxbody_pdb, tag + '_clashcheck.pdb') # assert 0 kw.timer.checkpoint('xtal_search') for ixtal, (xalign, xtal_pose, body_pdb, ncontact, enonbonded, solv_frac) in enumerate(xtal_poses): xtal_pose_min, mininfo = mof.minimize.minimize_mof_xtal( spec.sfxn_minimize, xspec, xtal_pose, **kw, ) if not xtal_pose_min: continue if kw.max_score_minimized < mininfo.score: continue print(' ', xspec.spacegroup, pdb_name, aa1, aa2, 'a on minimzied score', mininfo.score) continue celldim = xtal_pose.pdb_info().crystinfo().A() label = f"{pdb_name}_{xspec.spacegroup.replace(' ','_')}_{tag}_cell{int(celldim):03}_ncontact{ncontact:02}_score{int(enonbonded):03}" info = mininfo.sub( # adding to mininfo label=label, xalign=xalign, ncontact=ncontact, enonbonded=enonbonded, sequence=','.join(r.name() for r in xtal_pose.residues), solv_frac=solv_frac, celldim=celldim, spacegroup=xspec.spacegroup, nsubunits=xspec.nsubs, nres=xtal_pose_min.size() - 1, ) bbcoords = np.array( [(v[0], v[1], v[2]) for v in [[r.xyz(n) for n in ('N', 'CA', 'C')] for r in xtal_pose_min.residues[:-1]]]) bbpad = np.zeros(shape=(kw.max_pept_size - xtal_pose_min.size() + 1, 3, 3)) info['bbcoords'] = np.concatenate([bbcoords, bbpad]) results.append( rp.Bunch( xspec=xspec, # rpxbody=rpxbody, # asym_pose=xtal_pose, asym_pose_min=xtal_pose_min, info=info, )) ### debug crap if results: print(' * HIT %10s %7s %7s %3i %3i %9s %-7.3f %5.3f %s' % ( xspec.spacegroup.replace(' ', '_'), aa1, aa2, ires1, ires2, xtal_pose_min.sequence(), info.score, info.solv_frac, pdb_name, )) # rotcloud1.dump_pdb(fn + '_a.pdb', stub1, which=hit[0]) # rotcloud2.dump_pdb(fn + '_b.pdb', stub2, which=hit[1]) # rpxbody2.dump_pdb(fn + '_sym.pdb') # metalaxispos = metal_pos[:3] + metal_axis[:3] + metal_axis[:3] + metal_axis[:3] # pose2mut.dump_pdb(tag + '_before.pdb') # hokey_position_atoms(pose2mut, ires1, ires2, metal_pos, metalaxispos) # pose2mut.dump_pdb(tag + '_after.pdb') # assert 0 ### end debug crap kw.timer.checkpoint('build_result') kw.timer.checkpoint('xtal_search') return results
def xtal_search_single_residue(search_spec, pose, **kw): raise NotImplemntedError('xtal_search_single_residue needs updating') kw = rp.Bunch(kw) spec = search_spec xspec = spec.xtal_spec results = list() p_n = pose.pdb_info().name().split('/')[-1] # gets rid of the ".pdb" at the end of the pdb name pdb_name = p_n[:-4] print(f'{pdb_name} searching') # check the symmetry type of the pdb last_res = rt.core.pose.chain_end_res(pose).pop() total_res = int(last_res) sym_num = pose.chain(last_res) if sym_num < 2: print('bad pdb', p_n) return list() sym = int(sym_num) peptide_sym = "C%i" % sym_num for ires in range(1, int(total_res / sym) + 1): if pose.residue_type(ires) not in (spec.rts.name_map('GLY'), spec.rts.name_map('ALA'), spec.rts.name_map('DALA')): continue lig_poses = util.mut_to_ligand(pose, ires, spec.ligands, spec.sym_of_ligand) bad_rots = 0 for ilig, lig_pose in enumerate(lig_poses): mut_res_name, lig_sym = lig_poses[lig_pose] rotamers = lig_pose.residue(ires).get_rotamers() rotamers = util.extra_rotamers(rotamers, lb=-20, ub=21, bs=20) pose_num = 1 for irot, rotamer in enumerate(rotamers): #for i in range(1, len(rotamer)+1): # if I want to sample the metal-axis too for i in range(len(rotamer)): lig_pose.residue(ires).set_chi(i + 1, rotamer[i]) rot_pose = rt.protocols.grafting.return_region(lig_pose, 1, lig_pose.size()) if kw.debug: rot_pose.set_xyz(AtomID(rot_pose.residue(ires).atom_index('1HB'), ires), rVec(0, 0, -2)) rot_pose.set_xyz(AtomID(rot_pose.residue(ires).atom_index('CB'), ires), rVec(0, 0, +0.0)) rot_pose.set_xyz(AtomID(rot_pose.residue(ires).atom_index('2HB'), ires), rVec(0, 0, +2)) spec.sfxn_rotamer(rot_pose) dun_score = rot_pose.energies().residue_total_energy(ires) if dun_score >= spec.max_dun_score: bad_rots += 1 continue rpxbody = rp.Body(rot_pose) ############ fix this metal_orig = hm.hpoint(util.coord_find(rot_pose, ires, 'VZN')) hz = hm.hpoint(util.coord_find(rot_pose, ires, 'HZ')) ne = hm.hpoint(util.coord_find(rot_pose, ires, 'VNE')) metal_his_bond = hm.hnormalized(metal_orig - ne) metal_sym_axis0 = hm.hnormalized(hz - metal_orig) dihedral = xspec.dihedral ############# ... rots_around_nezn = hm.xform_around_dof_for_vector_target_angle( fix=spec.pept_axis, mov=metal_sym_axis0, dof=metal_his_bond, target_angle=np.radians(dihedral)) for idof, rot_around_nezn in enumerate(rots_around_nezn): metal_sym_axis = rot_around_nezn @ metal_sym_axis0 assert np.allclose(hm.line_angle(metal_sym_axis, spec.pept_axis), np.radians(dihedral)) newhz = util.coord_find(rot_pose, ires, 'VZN') + 2 * metal_sym_axis[:3] aid = rt.core.id.AtomID(rot_pose.residue(ires).atom_index('HZ'), ires) xyz = rVec(newhz[0], newhz[1], newhz[2]) rot_pose.set_xyz(aid, xyz) tag = f'{pdb_name}_{ires}_{lig_poses[lig_pose][0]}_{idof}_{pose_num}' xtal_poses = mof.xtal_build.xtal_build( pdb_name, xspec, aa1, aa2, rot_pose, peptide_sym, spec.pept_orig, spec.pept_axis, lig_sym, metal_orig, metal_sym_axis, rpxbody, tag, ) if False and xtal_poses: print('hoaktolfhtoia') print(rot_pose) print(pdb_name) print(xspec) rot_pose.dump_pdb('test_xtal_build_p213.pdb') print(ires) print(peptide_sym) print(spec.pept_orig) print(spec.pept_axis) print(lig_sym) print(metal_orig) print(metal_sym_axis) print('rp.Body(pose)') xalign, xpose, bodypdb = xtal_poses[0] print(xalign) xpose.dump_pdb('xtal_pose.pdb') assert 0 for ixtal, (xalign, xtal_pose, body_pdb) in enumerate(xtal_poses): celldim = xtal_pose.pdb_info().crystinfo().A() fname = f"{xspec.spacegroup.replace(' ','_')}_cell{int(celldim):03}_{tag}" results.append( mof.result.Result( xspec, fname, xalign, rpxbody, xtal_pose, body_pdb, )) pose_num += 1 # print(pdb_name, 'res', ires, 'bad rots:', bad_rots) return results
def xtal_search_two_residues( search_spec, pose, rotcloud1base, rotcloud2base, err_tolerance=1.5, min_dist_to_z_axis=6.0, sym_axes_angle_tolerance=3.0, **arg, ): arg = rp.Bunch(arg) spec = search_spec xspec = spec.xtal_spec results = list() farep_orig = search_spec.rep_sfxn(pose) p_n = pose.pdb_info().name().split('/')[-1] # gets rid of the ".pdb" at the end of the pdb name pdb_name = p_n[:-4] print(f'{pdb_name} searching') # check the symmetry type of the pdb last_res = rt.core.pose.chain_end_res(pose).pop() total_res = int(last_res) sym_num = pose.chain(last_res) sym = int(sym_num) if sym_num < 2: print('bad pdb', p_n) return list() asym_nres = int(total_res / sym) peptide_sym = "C%i" % sym_num rpxbody = rp.Body(pose) for ires1 in range(1, asym_nres + 1): # if pose.residue_type(ires1) not in (spec.rts.name_map('ALA'), spec.rts.name_map('DALA')): if pose.residue_type(ires1) != spec.rts.name_map('ALA'): continue stub1 = rpxbody.stub[ires1 - 1] rots1ok = min_dist_to_z_axis < np.linalg.norm( (stub1 @ rotcloud1base.rotframes)[:, :2, 3], axis=1) if 0 == np.sum(rots1ok): continue rotcloud1 = rotcloud1base.subset(rots1ok) rotframes1 = stub1 @ rotcloud1.rotframes # rotcloud1.dump_pdb(f'cloud_a_{ires1:02}.pdb', position=stub1) range2 = range(1, int(total_res) + 1) if rotcloud1base is rotcloud2base: range2 = range(ires1 + 1, int(total_res) + 1) for ires2 in range2: if ires1 == ires2 % asym_nres: continue if pose.residue_type(ires2) != spec.rts.name_map('ALA'): continue stub2 = rpxbody.stub[ires2 - 1] # rotcloud2.dump_pdb(f'cloud_b_{ires2:02}.pdb', position=stub2) rots2ok = min_dist_to_z_axis < np.linalg.norm( (stub2 @ rotcloud2base.rotframes)[:, :2, 3], axis=1) if 0 == np.sum(rots2ok): continue rotcloud2 = rotcloud2base.subset(rots2ok) rotframes2 = stub2 @ rotcloud2.rotframes dist = rotframes1[:, :, 3].reshape( -1, 1, 4) - rotframes2[:, :, 3].reshape(1, -1, 4) dist = np.linalg.norm(dist, axis=2) # if np.min(dist) < 1.0: # print(f'{ires1:02} {ires2:02} {np.sort(dist.flat)[:5]}') dot = np.sum(rotframes1[:, :, 0].reshape(-1, 1, 4) * rotframes2[:, :, 0].reshape(1, -1, 4), axis=2) ang = np.degrees(np.arccos(dot)) angerr = np.abs(ang - 107) err = angerr / 15.0 + dist rot1err = np.min(err, axis=1) bestrot2 = np.argmin(err, axis=1) hits1 = np.argwhere(rot1err < err_tolerance).reshape(-1) # hits = (angerr < angle_err_tolerance) * (dist < dist_err_tolerance) if len(hits1): # print(rotcloud1.amino_acid, rotcloud2.amino_acid, ires1, ires2) hits2 = bestrot2[hits1] hits = np.stack([hits1, hits2], axis=1) # print( # f'stats {ires1:2} {ires2:2} {np.sum(angerr < 10):7} {np.sum(dist < 1.0):5} {np.sum(hits):3}' # ) for ihit, hit in enumerate(hits): frame1 = rotframes1[hit[0]] frame2 = rotframes2[hit[1]] parl = (frame1[:, 0] + frame2[:, 0]) / 2.0 perp = rp.homog.hcross(frame1[:, 0], frame2[:, 0]) metalaxis1 = rp.homog.hrot(parl, +45) @ perp metalaxis2 = rp.homog.hrot(parl, -45) @ perp symang1 = rp.homog.line_angle(metalaxis1, spec.pept_axis) symang2 = rp.homog.line_angle(metalaxis2, spec.pept_axis) match11 = np.abs(np.degrees(symang1) - 35.26) < sym_axes_angle_tolerance match12 = np.abs(np.degrees(symang2) - 35.26) < sym_axes_angle_tolerance match21 = np.abs(np.degrees(symang1) - 54.735) < sym_axes_angle_tolerance match22 = np.abs(np.degrees(symang2) - 54.735) < sym_axes_angle_tolerance if not (match11 or match12 or match12 or match22): continue matchsymang = symang1 if (match11 or match21) else symang2 metalaxis = metalaxis1 if (match11 or match21) else metalaxis2 metal_pos = (rotframes1[hit[0], :3, 3] + rotframes2[hit[1], :3, 3]) / 2.0 metalaxispos = metal_pos + metalaxis[:3] + metalaxis[:3] # metal_dist_z = np.sqrt(metal_pos[0]**2 + metal_pos[1]**2) # if metal_dist_z < 4.0: continue pose2 = mof.util.mutate_two_res( pose, ires1, rotcloud1.amino_acid, rotcloud1.rotchi[hit[0]], ires2, rotcloud2.amino_acid, rotcloud2.rotchi[hit[1]], ) if pose2.residue(ires1).has('VZN'): pose2.set_xyz( AtomID( pose2.residue(ires1).atom_index('VZN'), ires1), rVec(metal_pos[0], metal_pos[1], metal_pos[2])) pose2.set_xyz( AtomID( pose2.residue(ires1).atom_index('HZ'), ires1), rVec(metalaxispos[0], metalaxispos[1], metalaxispos[2])) elif pose2.residue(ires2).has('VZN'): pose2.set_xyz( AtomID( pose2.residue(ires2).atom_index('VZN'), ires2), rVec(metal_pos[0], metal_pos[1], metal_pos[2])) pose2.set_xyz( AtomID( pose2.residue(ires2).atom_index('HZ'), ires2), rVec(metalaxispos[0], metalaxispos[1], metalaxispos[2])) farep_delta = search_spec.rep_sfxn(pose2) - farep_orig if farep_delta > 1.0: continue print( "HIT", rotcloud1.amino_acid, rotcloud2.amino_acid, ires1, ires2, np.round(np.degrees(matchsymang), 3), hit, rotcloud1.rotchi[hit[0]], rotcloud2.rotchi[hit[1]], # farep_delta, np.round(dist[tuple(hit)], 3), np.round(angerr[tuple(hit)], 3), ) fn = ('hit_%s_%s_%i_%i_%i.pdb' % (rotcloud1.amino_acid, rotcloud2.amino_acid, ires1, ires2, ihit)) rotcloud1.dump_pdb(fn + '_a.pdb', stub1, which=hit[0]) rotcloud2.dump_pdb(fn + '_b.pdb', stub2, which=hit[1]) pose2.dump_pdb(fn) return results