1 """@namespace IMP.EMageFit.buildxlinks
2 Utility functions to handle cross links.
12 log = logging.getLogger(
"buildxlinks")
19 from sets
import Set
as set
25 Class defining a cross-link
28 def __init__(self, id1, chain1, residue1,
29 id2, chain2, residue2,
33 @param[in] id1 Id of the first component of the cross-link
34 @param[in] chain1 Chain of the first component
35 @param[in] residue1 Residue cross-linked in the first component
36 @param[in] id2 Id of the second component of the cross-link
37 @param[in] chain2 chain1 Chain of the second component
38 @param[in] residue2 Residue cross-linked in the second component
39 @param[in] distance Maximum distance
42 self.first_chain = chain1
43 self.first_residue = residue1
45 self.second_chain = chain2
46 self.second_residue = residue2
47 self.distance = distance
50 xl =
Xlink(self.first_id, self.first_chain, self.first_residue,
51 self.second_id, self.second_chain, self.second_residue,
55 def __eq__(self, other):
56 if self.first_id != other.first_id
or \
57 self.second_id != other.second_id
or \
58 self.first_chain != other.first_chain
or \
59 self.second_chain != other.second_chain
or \
60 self.first_residue != other.first_residue
or \
61 self.second_residue != other.second_residue
or \
62 abs(other.distance - self.distance) > 0.01:
68 swaps the order of the residues in the restraint
70 self.first_id, self.second_id = self.second_id, self.first_id
71 self.first_residue, self.second_residue = \
72 self.second_residue, self.first_residue
73 self.first_chain, self.second_chain = \
74 self.second_chain, self.first_chain
77 s =
"Cross Link: %s %s %d - %s %s %d. Distance %f" % (self.first_id,
78 self.first_chain, self.first_residue,
79 self.second_id, self.second_chain,
80 self.second_residue, self.distance)
85 Generate a unique name for the restraint.
86 @note: The name cannot start with a number, upsets sqlite
88 name =
"cl_%s_%s%d_%s_%s%d" % (self.first_id, self.first_chain,
89 self.first_residue, self.second_id,
90 self.second_chain, self.second_residue)
96 Build a set of nodes and edges from the set of crosslinking
98 @param xlinks_dict a XlinksDict class
103 for key
in xlinks_dict.keys():
106 edge = sorted([key[0], key[1]])
107 if edge
not in edges:
109 log.debug(
"Subunits %s", subunits)
110 log.debug(
"Edges %s", edges)
111 return subunits, edges
117 Description of crosslinking restraints as a python
119 The keys are a pair with the ids of the cross-linked subunits.
120 Note: The pairs are considered in alphabetic order
125 Add a xlink. It is ensured that the id of the first element is
126 is lower that the second
128 if xlink.second_id < xlink.first_id:
130 key = (xlink.first_id, xlink.second_id)
131 if key
not in self.keys():
133 self[key].append(xlink)
137 @param pair_ids Ids fo the subunits that are cross-linked
140 xlinks_list = self[pair_ids]
141 ys = [xl.clone()
for xl
in xlinks_list]
145 xlinks_list = self[(pair_ids[1], pair_ids[0])]
146 ys = [xl.clone()
for xl
in xlinks_list]
151 except KeyError
as e:
157 return self[pair_ids]
159 print pair_ids,"NOT FOUND, swapping to",(pair_ids[1], pair_ids[0])
160 # If not found, invert the pair
161 xlinks_list = self[(pair_ids[1], pair_ids[0])]
162 # swap the xlinks, so the first element of the pair corresponds to the
163 # first id in the xlink
164 for xl in xlinks_list:
166 for xl in xlinks_list:
175 Compute the order of the docking experiments. The order is derived
176 from the cross-linking restraints:
177 1) The subunit with the highest number of cross-links with others
178 works as the first receptor (A)
179 2) All the subunits cross-linked with A are docked into A.
180 3) The next receptor (B) is the subunit that has the highest number of
182 4) All the subunits cross-linked to B are docked into B (except A)
183 5) The procedure is repeated until there are no more cross-links
191 Instead of setting the xlink restraints, init the graph directly
192 Example of what to pass with the structure in 3sfd
193 G.add_nodes_from(["A", "B", "C", "D"])
194 G.add_edges_from([("B","C"), ("B","A"), ("B","D"), ("C","D")])
195 ("B","C") means that there are cross-links between B and C
197 self.G.add_nodes_from(subunits)
198 self.G.add_edges_from(edges)
202 Sets the xlinks used for computing the docking order
203 @param xlinks_dict XlinksDict class
209 """ return the order to dock components from the cross links """
211 degs = self.G.degree(self.G.nodes())
212 log.debug(
"Degrees: %s", degs)
213 sorted_degrees = sorted([(v, k)
214 for v, k
in zip(degs.values(), degs.keys())])
215 sorted_degrees.reverse()
217 receptors_considered = []
218 for degree, node
in sorted_degrees:
219 for n
in self.G.neighbors(node):
220 if not n
in receptors_considered:
221 docking_pairs.append((node, n))
222 receptors_considered.append(node)
223 log.info(
"The suggested order for the docking pairs is %s",
231 Puts two subunits together using the Xlinkins restraints. The solutions
232 offered by this class are just an initial position of the components
236 def clear_xlinks(self):
237 self.xlinks_list = []
241 Sets the xlinks used for the computation fo the intial rough
243 @param xlinks_list A list of Xlink classes
244 residue1 belongs to the receptor and residue2 belongs to the ligand
246 self.xlinks_list = xlinks_list
250 Set the name of the PDB files of the receptor and the ligand
256 self.h_receptor = atom.read_pdb(fn_receptor, self.m_receptor, sel)
258 self.h_ligand = atom.read_pdb(fn_ligand, self.m_ligand, sel)
262 Set the hierarchies (atom.Hierarchy objects) for the receptor and
267 self.h_receptor = h_receptor
268 self.h_ligand = h_ligand
272 Sets the rigid bodies (core.RigidBody objects) for the receptor and
277 self.rb_receptor = rb_receptor
278 self.rb_ligand = rb_ligand
282 Movest the ligand close to the receptor based on the xlinks
283 provided by set_xlinks()
285 log.debug(
"Moving ligand close to the receptor using the xlinks")
286 n = len(self.xlinks_list)
294 Get the particle representing a residue in a hierarchy
295 @param h atom.Hierarchy containing the residue
296 @param ch The chain id
297 @param res index of the residue
300 return s.get_selected_particles()[0]
304 Get the coordinates for a residue in a molecular hierarchy
305 @param h atom.Hierarchy object
306 @param ch The chain id
307 @param res Residue index
310 return core.XYZ(p).get_coordinates()
314 Write a pdb file the coordinates of the ligand
317 atom.write_pdb(self.h_ligand, fn)
321 Put the residues in a random distance between 0 and the maximum
322 cross-linkin distance
324 xl = self.xlinks_list[0]
327 sph = alg.Sphere3D(center, xl.distance)
328 v = alg.get_random_vector_in(sph)
329 ref = self.rb_ligand.get_reference_frame()
330 coords = ref.get_transformation_to().get_translation()
331 R = ref.get_transformation_to().get_rotation()
334 log.debug(
"Ligand residue before moving %s", lig)
335 displacement = v - lig
336 T = alg.Transformation3D(R, coords + displacement)
337 self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(T))
339 self.h_ligand, xl.second_chain,
341 log.debug(
"ligand after moving %s", new_coords)
345 Function equivalent to move_one_xlink() for the case where there
346 are more than one cross-link restraints available.
347 Puts the ligand residues as close as possible to the receptor
352 for xl
in self.xlinks_list:
359 log.debug(
"Receptor residues before moving %s", rec_coords)
360 log.debug(
"Ligand residues before moving %s", lig_coords)
361 ref = self.rb_ligand.get_reference_frame()
362 Tr = alg.get_transformation_aligning_first_to_second(lig_coords,
364 T = ref.get_transformation_to()
365 newT = alg.compose(Tr, T)
366 self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT))
368 moved_lig_coords = []
369 for xl
in self.xlinks_list:
372 moved_lig_coords.append(c)
373 log.debug(
"Ligand residues after moving %s", moved_lig_coords)
def write_ligand
Write a pdb file the coordinates of the ligand.
Utility functions to extract min/max from the inputs.
def move_ligand
Movest the ligand close to the receptor based on the xlinks provided by set_xlinks() ...
def set_pdbs
Set the name of the PDB files of the receptor and the ligand.
Class defining a cross-link.
def get_name
Generate a unique name for the restraint.
Select all non-alternative ATOM records.
def set_xlinks
Sets the xlinks used for the computation fo the intial rough docking solution.
def set_xlinks
Sets the xlinks used for computing the docking order.
Compute the order of the docking experiments.
def build_xlinks_graph
Build a set of nodes and edges from the set of crosslinking restraints.
def __init__
Initialize the class.
A decorator for a particle with x,y,z coordinates.
def get_residue_particle
Get the particle representing a residue in a hierarchy.
def get_docking_order
return the order to dock components from the cross links
Description of crosslinking restraints as a python dictionary.
Basic functionality that is expected to be used by a wide variety of IMP users.
General purpose algebraic and geometric methods that are expected to be used by a wide variety of IMP...
def swap
swaps the order of the residues in the restraint
void show(Hierarchy h, std::ostream &out=std::cout)
Print out a molecular hierarchy.
def set_components_and_connections
Instead of setting the xlink restraints, init the graph directly Example of what to pass with the str...
def move_one_xlink
Put the residues in a random distance between 0 and the maximum cross-linkin distance.
def set_rigid_bodies
Sets the rigid bodies (core.RigidBody objects) for the receptor and the ligand.
Functionality for loading, creating, manipulating and scoring atomic structures.
def get_residue_coordinates
Get the coordinates for a residue in a molecular hierarchy.
Select hierarchy particles identified by the biological name.
def set_hierarchies
Set the hierarchies (atom.Hierarchy objects) for the receptor and the ligand.
Puts two subunits together using the Xlinkins restraints.
Class for storing model, its restraints, constraints, and particles.
def move_xlinks
Function equivalent to move_one_xlink() for the case where there are more than one cross-link restrai...