def align_rigid_bodies_states(self): """ Aligns the set of structures considered for DOMINO sampling. The function: 1) reads the possible reference frames that the rb_states_table stores for each rigid body. This table must be filled before using this function. Usually it is filled with the results from a previous Monte Carlo sampling. If the solutions from Monte Carlo seem to have the same structure but they are not aligned to each other, this function can help setting better starting positions to use with DOMINO. 2) Gets the first state for each of the rigid bodies and sets a reference structure using such states. 3) Aligns all the rest of the structures respect to the reference 4) Replaces the values of the reference frames stored in the rb_states_table with the new values obtained from the alignments. It does it for all states of a rigid body. @note: If this function is applied, the parameters "anchor" and "fixed" are ignored, as they are superseded by the use of the alignments calculated here. """ log.debug("Align the configurations read from the database before " "running DOMINO") rb_states = [] n_states = [] for rb in self.components_rbs: ps = self.rb_states_table.get_particle_states(rb) n = ps.get_number_of_particle_states() if n == 0: raise ValueError( "There are no particle states for %s" % rb.get_name()) n_states.append(n) rb_states.append(ps) # coordinates of the first configuration (there is at least one for all # the rbs) for rb, states in zip(self.components_rbs, rb_states): states.load_particle_state(0, rb) reference_coords = get_coordinates(self.components_rbs) aligned_transformations = [[] for rb in self.components_rbs] for i in range(1, max(n_states)): log.debug("Aligning rigid bodies configuration %s" % i) # load the configuration for j in range(len(self.components_rbs)): # if there are no more particle states for this rigid body, use # the last state_index = min(i, n_states[j] - 1) rb_states[j].load_particle_state( state_index, self.components_rbs[j]) coords = get_coordinates(self.components_rbs) T = alg.get_transformation_aligning_first_to_second( coords, reference_coords) for j, rb in enumerate(self.components_rbs): t = rb.get_reference_frame().get_transformation_to() new_t = alg.compose(T, t) aligned_transformations[j].append(new_t) # set the new possible transformations for i, rb in enumerate(self.components_rbs): self.set_rb_states(rb, aligned_transformations[i])
def get_restraints_for_native(self, restraints_names): """ Get values of the restraints for the native structure @param restraints_names Names of the restraints requested @return a list with the values of all scores, and the total score """ saved = [rb.get_reference_frame() for rb in self.components_rbs] # Set the state of the model to native for rb, rn in zip(self.components_rbs, self.native_rbs): # remove sub-rigid bodies rb_members = [m for m in rb.get_members() if not core.RigidBody.get_is_setup(m.get_particle())] rn_members = [m for m in rn.get_members() if not core.RigidBody.get_is_setup(m.get_particle())] rb_coords = [m.get_coordinates() for m in rb_members] rn_coords = [m.get_coordinates() for m in rn_members] # align and put rb in the position of rn if len(rn_coords) != len(rb_coords): raise ValueError("Mismatch in the number of members. " "Reference %d Aligned %d " % (len(rn_coords), len(rb_coords))) T = alg.get_transformation_aligning_first_to_second(rb_coords, rn_coords) t = rb.get_reference_frame().get_transformation_to() new_t = alg.compose(T, t) rb.set_reference_frame(alg.ReferenceFrame3D(new_t)) scores = [] for name in restraints_names: scores.append(self.restraints[name].evaluate(False)) total_score = sum(scores) representation.set_reference_frames(self.components_rbs, saved) return scores, total_score
def align_centroids_using_pca(ref_frames, ref_frames_reference): """ Align the centroids of 2 sets of rigid bodyes using PCA using their reference frames. returns the best rmsd and the ref_frames to get it. """ if(len(ref_frames) != len(ref_frames_reference)): raise ValueError("The number of reference frames must be the same") Ts1 = [r.get_transformation_to() for r in ref_frames] vs1 = [T.get_translation() for T in Ts1] Ts2 = [r.get_transformation_to() for r in ref_frames_reference] vs2 = [T.get_translation() for T in Ts2] # align with PCA pc1 = alg.get_principal_components(vs1) pc2 = alg.get_principal_components(vs2) pcTs = alg.get_alignments_from_first_to_second(pc1, pc2) best_refs = [] best_rmsd = 1e5 for j, pcT in enumerate(pcTs): new_Ts1 = [alg.compose(pcT, T) for T in Ts1] new_vs1 = [T.get_translation() for T in new_Ts1] r = atom.get_rmsd(new_vs1, vs2) if(r < best_rmsd): best_rmsd = r best_refs = [alg.ReferenceFrame3D(T) for T in new_Ts1] return best_rmsd, best_refs
def get_reference_frames_from_chain_alignment(reference_rbs, reference_index, rbs_to_align, index_to_align): """ Align the rigid bodies rbs_to_align to the the reference frames of reference_rbs. The rb with index_to_align is aligned to the reference rb with reference_index. The function returns the reference frames to apply to the rbs_to_align. """ ref_coords = \ [m.get_coordinates() for m in reference_rbs[reference_index].get_members()] coords = [m.get_coordinates() for m in rbs_to_align[index_to_align].get_members()] if(len(coords) != len(ref_coords)): raise ValueError( "Mismatch in the number of members. Reference %d Aligned %d " % ( len(ref_coords), len(coords))) T = alg.get_transformation_aligning_first_to_second(coords, ref_coords) new_refs = [] for rb in rbs_to_align: # log.debug("aligning ... %s",rb) t = rb.get_reference_frame().get_transformation_to() new_t = alg.compose(T, t) new_refs.append(alg.ReferenceFrame3D(new_t)) return new_refs
def move_xlinks(self, ): """ Function equivalent to move_one_xlink() for the case where there are more than one cross-link restraints available. Puts the ligand residues as close as possible to the receptor residues """ rec_residues = [x[0] for x in self.xlinks] lig_residues = [x[1] for x in self.xlinks] rec_coords = [self.get_residue_coordinates(self.h_receptor, x) for x in rec_residues] lig_coords = [self.get_residue_coordinates(self.h_ligand, x) for x in lig_residues] log.debug( "Receptor residues before moving %s", rec_coords) log.debug( "Ligand residues before moving %s", lig_coords) ref = self.rb_ligand.get_reference_frame() # new coords for the ligand aminoacids Tr = alg.get_transformation_aligning_first_to_second(lig_coords, rec_coords) T = ref.get_transformation_to() newT = alg.compose(Tr, T) self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT)) moved_lig_coords = [self.get_residue_coordinates(self.h_ligand, x) for x in lig_residues] log.debug( "Ligand residues after moving %s", moved_lig_coords)
def move_xlinks(self, ): """ Function equivalent to move_one_xlink() for the case where there are more than one cross-link restraints available. Puts the ligand residues as close as possible to the receptor residues """ rec_coords = [] lig_coords = [] for xl in self.xlinks_list: c = self.get_residue_coordinates(self.h_receptor, xl.first_chain, xl.first_residue) rec_coords.append(c) c = self.get_residue_coordinates(self.h_ligand, xl.second_chain, xl.second_residue) lig_coords.append(c) log.debug("Receptor residues before moving %s", rec_coords) log.debug("Ligand residues before moving %s", lig_coords) ref = self.rb_ligand.get_reference_frame() Tr = alg.get_transformation_aligning_first_to_second(lig_coords, rec_coords) T = ref.get_transformation_to() newT = alg.compose(Tr, T) self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT)) moved_lig_coords = [] for xl in self.xlinks_list: c = self.get_residue_coordinates(self.h_ligand, xl.second_chain, xl.second_residue) moved_lig_coords.append(c) log.debug("Ligand residues after moving %s", moved_lig_coords)
def move_xlinks(self, ): """ Function equivalent to move_one_xlink() for the case where there are more than one cross-link restraints available. Puts the ligand residues as close as possible to the receptor residues """ rec_coords = [] lig_coords = [] for xl in self.xlinks_list: c = self.get_residue_coordinates(self.h_receptor, xl.first_chain, xl.first_residue) rec_coords.append(c) c = self.get_residue_coordinates(self.h_ligand, xl.second_chain, xl.second_residue) lig_coords.append(c) log.debug("Receptor residues before moving %s", rec_coords) log.debug("Ligand residues before moving %s", lig_coords) ref = self.rb_ligand.get_reference_frame() Tr = alg.get_transformation_aligning_first_to_second( lig_coords, rec_coords) T = ref.get_transformation_to() newT = alg.compose(Tr, T) self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT)) moved_lig_coords = [] for xl in self.xlinks_list: c = self.get_residue_coordinates(self.h_ligand, xl.second_chain, xl.second_residue) moved_lig_coords.append(c) log.debug("Ligand residues after moving %s", moved_lig_coords)
def get_docked_reference_frames(relative_transforms, rb_lig): Tinitial = rb_lig.get_reference_frame().get_transformation_to() docked_ref_frames = [] for Trelative in relative_transforms: Tdock = alg.compose(Trelative, Tinitial) docked_rf = alg.ReferenceFrame3D(Tdock) docked_ref_frames.append(docked_rf) return docked_ref_frames
def get_internal_transform(Thex, rb_receptor, rb_ligand): """ Get the internal transform (Ti) resulting from applying the transformation Thex (from HEX) that docks the ligand. The relationship betwen the reference frame of the ligand docked (Tdock) and the internal transformation (Ti) respect to the receptor (Trec) is Tdock = Trec * Tinternal @param Thex HEX transformation @param rb_receptor Rigid body of the receptor @param rb_ligand Rigid body of the ligand @return The internal transformation """ Trb = rb_ligand.get_reference_frame().get_transformation_to() Trec = rb_receptor.get_reference_frame().get_transformation_to() Tdock = alg.compose(Thex, Trb) Ti = alg.compose(Trec.get_inverse(), Tdock) return Ti
def apply_rotation_around_centroid(rb,rot): """ Rotates the reference frame of a rigid body around the centroid """ c = rb.get_coordinates() ref = rb.get_reference_frame() R = ref.get_transformation_to().get_rotation() R2 = alg.compose(rot, R) T = alg.Transformation3D(R2, c) ref = alg.ReferenceFrame3D(T) rb.set_reference_frame(ref)
def apply_rotation_around_centroid(rb, rot): """ Rotates the reference frame of a rigid body around the centroid """ c = rb.get_coordinates() ref = rb.get_reference_frame() R = ref.get_transformation_to().get_rotation() R2 = alg.compose(rot, R) T = alg.Transformation3D(R2, c) ref = alg.ReferenceFrame3D(T) rb.set_reference_frame(ref)
def apply_random_transform(rb, max_trans=100): """ Apply a random transformation to the rigid body and change the reference frame """ bb = alg.BoundingBox3D(alg.Vector3D(-max_trans, -max_trans, -max_trans), alg.Vector3D(max_trans, max_trans, max_trans)) Trand = alg.Transformation3D(alg.get_random_rotation_3d(), alg.get_random_vector_in(bb)) ref = rb.get_reference_frame() Tr = ref.get_transformation_to() T = alg.compose(Trand, Tr) rb.set_reference_frame(alg.ReferenceFrame3D(T))
def get_docked_reference_frames(hex_transforms, rb_ligand): """ @param hex_transforms A list of HEX transformations @param rb_ligand The rigid body of the ligand @return The reference frames that the rigid body of the ligand has when docked. The docked reference frame has transformation: Tdock = Thex * Tinitial """ Trb = rb_ligand.get_reference_frame().get_transformation_to() docked_ref_frames = [] for Thex in hex_transforms: Tdock = alg.compose(Thex, Trb) docked_rf = alg.ReferenceFrame3D(Tdock) docked_ref_frames.append(docked_rf) return docked_ref_frames
def get_orientations_nearby(rotation, n, f): """ Rotations nearby a given one. They are got intepolating with the rotations of the uniform coverage. The parameter f (0 <= f <= 1) must be close to 0 to get orientations that are close to the given orientation - Values from 0.1 (tight cluster) to 0.4 (loose) seem to be ok n - number of rotations requested """ log.debug("Computing nearby rotations around %s", rotation) unif = alg.get_uniform_cover_rotations_3d(n) id_rot = alg.get_identity_rotation_3d() oris = [] for rot in unif: r = alg.get_interpolated(rot, id_rot, f) r = alg.compose(r, rotation ) oris.append(r) return oris
def get_orientations_nearby(rotation, n, f): """ Rotations nearby a given one. They are got intepolating with the rotations of the uniform coverage. The parameter f (0 <= f <= 1) must be close to 0 to get orientations that are close to the given orientation - Values from 0.1 (tight cluster) to 0.4 (loose) seem to be ok n - number of rotations requested """ log.debug("Computing nearby rotations around %s", rotation) unif = alg.get_uniform_cover_rotations_3d(n) id_rot = alg.get_identity_rotation_3d() oris = [] for rot in unif: r = alg.get_interpolated(rot, id_rot, f) r = alg.compose(r, rotation) oris.append(r) return oris
sel = atom.ATOMPDBSelector() m = IMP.Model() h_receptor = atom.read_pdb(args.fn_receptor, m, sel) rb_receptor = atom.create_rigid_body(h_receptor) h_ligand = atom.read_pdb(args.fn_ligand, m, sel) rb_ligand = atom.create_rigid_body(h_ligand) if args.dock: check_for_hexdock() if not args.fn_transforms or not args.fn_internal_transforms: raise IOError("Docking requires the --int and --hex arguments") hex_docking = HexDocking() hex_docking.dock(args.fn_receptor, args.fn_ligand, args.fn_transforms) # read the HEX file of solutions and get the internal transformations # giving the relative orientation of the ligand respect to the receptor Ts = read_hex_transforms(args.fn_transforms) rb_receptor = atom.create_rigid_body(h_receptor) Tis = [get_internal_transform(T, rb_receptor, rb_ligand) for T in Ts] io.write_transforms(Tis, args.fn_internal_transforms) elif args.write: # To write the positions correctly, the script requires that the # ligand file is the same that was used for the docking Tinternal = io.read_transforms(args.fn_internal_transforms) max_number = min(args.write, len(Tinternal)) Trec = rb_receptor.get_reference_frame().get_transformation_to() for i in range(max_number): Tdock = alg.compose(Trec, Tinternal[i]) ref = alg.ReferenceFrame3D(Tdock) rb_ligand.set_reference_frame(ref) atom.write_pdb(h_ligand,"docked-%03d.pdb" % i)
rigid_bodies.append(rbd) print "chain has",rbd.get_number_of_members(), \ "atoms","coordinates: ",rbd.get_coordinates() native_chain_centers.append(rbd.get_coordinates()) bb=alg.BoundingBox3D(alg.Vector3D(-25, -40,-60), alg.Vector3D( 25, 40, 60)) # rotate and translate the chains for rbd in rigid_bodies: # rotation rotation= alg.get_random_rotation_3d() transformation1=alg.get_rotation_about_point(rbd.get_coordinates(),rotation) # translation transformation2=alg.Transformation3D(alg.get_random_vector_in(bb)) # Apply final_transformation = alg.compose(transformation1,transformation2) core.transform(rbd,final_transformation) print "Writing transformed assembly" atom.write_pdb (prot,"1z5s-transformed.pdb") # set distance restraints measusring some distances between rigid bodies # for the solution. d01 = alg.get_distance(native_chain_centers[0],native_chain_centers[1]) r01 = core.DistanceRestraint(core.Harmonic(d01,1),chains[0],chains[1]) r01.set_name("distance 0-1") d12 = alg.get_distance(native_chain_centers[1],native_chain_centers[2]) r12 = core.DistanceRestraint(core.Harmonic(d12,1),chains[1],chains[2]) r12.set_name("distance 1-2") d23 = alg.get_distance(native_chain_centers[2],native_chain_centers[3]) r23 = core.DistanceRestraint(core.Harmonic(d23,1),chains[2],chains[3]) r23.set_name("distance 2-3")
def get_internal_transform3(Trelative, rb_rec, rb_lig): Trb = rb_lig.get_reference_frame().get_transformation_to() Trec = rb_rec.get_reference_frame().get_transformation_to() Tdock = alg.compose(Trelative, Trb) Ti = alg.compose(Trec.get_inverse(), Tdock) return Ti
def create_dockings_from_xlinks(exp): """ Perform dockings that satisfy the cross-linking restraints. 1) Based on the number of restraints, creates an order for the docking between pairs of subunits, favouring the subunits with more crosslinks to be the "receptors" 2) Moves the subunits that are going to be docked to a position that satisfies the x-linking restraints. There is no guarantee that this position is correct. Its purpose is to help the docking algorithm with a clue of the proximity/orientation between subunits 3) Performs docking between the subunits 4) Filters the results of the docking that are not consistent with the cross-linking restraints 5) Computes the relative transformations between the rigid bodies of the subunits that have been docked @param exp Class with the parameters for the experiment """ log.info("Creating initial assembly from xlinks and docking") import docking_related as dock import buildxlinks as bx m = DominoModel.DominoModel() m.set_assembly_components(exp.fn_pdbs, exp.names) set_xlink_restraints(exp, m) order = bx.DockOrder() order.set_xlinks(m.xlinks) docking_pairs = order.get_docking_order() if hasattr(exp, "have_hexdock"): if not exp.have_hexdock: return for rec, lig in docking_pairs: pair_xlinks = m.xlinks.get_xlinks_for_pair((rec,lig)) log.debug("Xlinks for the pair %s %s %s",rec, lig, pair_xlinks) h_receptor = representation.get_component(m.assembly, rec) h_ligand = representation.get_component(m.assembly, lig) rb_receptor = representation.get_rigid_body(m.components_rbs, representation.get_rb_name(rec)) rb_ligand = representation.get_rigid_body(m.components_rbs, representation.get_rb_name(lig)) initial_ref = rb_ligand.get_reference_frame() # move to the initial docking position mv = bx.InitialDockingFromXlinks() mv.set_xlinks(pair_xlinks) mv.set_hierarchies(h_receptor, h_ligand) mv.set_rigid_bodies(rb_receptor, rb_ligand) mv.move_ligand() fn_initial_docking = "%s-%s_initial_docking.pdb" % (rec,lig) mv.write_ligand(fn_initial_docking) # dock hex_docking = dock.HexDocking() receptor_index = exp.names.index(rec) fn_transforms = "hex_solutions_%s-%s.txt" % (rec, lig) fn_docked = "%s-%s_hexdock.pdb" % (rec, lig) hex_docking.dock(exp.fn_pdbs[receptor_index], fn_initial_docking, fn_transforms, fn_docked, False) sel = atom.ATOMPDBSelector() new_m = IMP.Model() # After reading the file with the initial solution, the reference frame # for the rigid body of the ligand is not necessarily the same one # that it had when saved. # Thus reading the file again ensures consisten results when # using the HEXDOCK transforms new_h_ligand = atom.read_pdb(fn_initial_docking, new_m, sel) new_rb_ligand = atom.create_rigid_body(new_h_ligand) Tlig = new_rb_ligand.get_reference_frame().get_transformation_to() fn_filtered = "hex_solutions_%s-%s_filtered.txt" % (rec, lig) # h_ligand contains the coordinates of the ligand after moving it # to the initial position for the docking dock.filter_docking_results(h_receptor, new_h_ligand, pair_xlinks, fn_transforms, fn_filtered) # transforms to apply to the ligand as it is in the file # fn_initial_docking Thex = dock.read_hex_transforms(fn_filtered) Trec = rb_receptor.get_reference_frame().get_transformation_to() Tinternal = [] for i,T in enumerate(Thex): Tdock = alg.compose(T, Tlig) ref = alg.ReferenceFrame3D(Tdock) new_rb_ligand.set_reference_frame(ref) # internal transformation. The relationship is Tdock = Trec * Ti Ti = alg.compose(Trec.get_inverse(), Tdock) Tinternal.append(Ti) fn_relative = "relative_positions_%s-%s.txt" % (rec, lig) io.write_transforms(Tinternal, fn_relative) rb_ligand.set_reference_frame(initial_ref)