1 """@namespace IMP.EMageFit.buildxlinks
2 Utility functions to handle cross links.
13 log = logging.getLogger(
"buildxlinks")
19 Class defining a cross-link
22 def __init__(self, id1, chain1, residue1,
23 id2, chain2, residue2,
27 @param[in] id1 Id of the first component of the cross-link
28 @param[in] chain1 Chain of the first component
29 @param[in] residue1 Residue cross-linked in the first component
30 @param[in] id2 Id of the second component of the cross-link
31 @param[in] chain2 chain1 Chain of the second component
32 @param[in] residue2 Residue cross-linked in the second component
33 @param[in] distance Maximum distance
36 self.first_chain = chain1
37 self.first_residue = residue1
39 self.second_chain = chain2
40 self.second_residue = residue2
41 self.distance = distance
44 xl =
Xlink(self.first_id, self.first_chain, self.first_residue,
45 self.second_id, self.second_chain, self.second_residue,
49 def __eq__(self, other):
50 if self.first_id != other.first_id
or \
51 self.second_id != other.second_id
or \
52 self.first_chain != other.first_chain
or \
53 self.second_chain != other.second_chain
or \
54 self.first_residue != other.first_residue
or \
55 self.second_residue != other.second_residue
or \
56 abs(other.distance - self.distance) > 0.01:
62 swaps the order of the residues in the restraint
64 self.first_id, self.second_id = self.second_id, self.first_id
65 self.first_residue, self.second_residue = \
66 self.second_residue, self.first_residue
67 self.first_chain, self.second_chain = \
68 self.second_chain, self.first_chain
71 s =
"Cross Link: %s %s %d - %s %s %d. Distance %f" % (
72 self.first_id, self.first_chain, self.first_residue,
73 self.second_id, self.second_chain, self.second_residue,
79 Generate a unique name for the restraint.
80 @note: The name cannot start with a number, upsets sqlite
82 name =
"cl_%s_%s%d_%s_%s%d" % (self.first_id, self.first_chain,
83 self.first_residue, self.second_id,
84 self.second_chain, self.second_residue)
90 Build a set of nodes and edges from the set of crosslinking
92 @param xlinks_dict a XlinksDict class
97 for key
in xlinks_dict.keys():
100 edge = sorted([key[0], key[1]])
101 if edge
not in edges:
103 log.debug(
"Subunits %s", subunits)
104 log.debug(
"Edges %s", edges)
105 return subunits, edges
111 Description of crosslinking restraints as a python
113 The keys are a pair with the ids of the cross-linked subunits.
114 Note: The pairs are considered in alphabetic order
119 Add a xlink. It is ensured that the id of the first element is
120 is lower that the second
122 if xlink.second_id < xlink.first_id:
124 key = (xlink.first_id, xlink.second_id)
125 if key
not in self.keys():
127 self[key].append(xlink)
131 @param pair_ids Ids for the subunits that are cross-linked
134 xlinks_list = self[pair_ids]
135 ys = [xl.clone()
for xl
in xlinks_list]
139 xlinks_list = self[(pair_ids[1], pair_ids[0])]
140 ys = [xl.clone()
for xl
in xlinks_list]
145 except KeyError
as e:
151 return self[pair_ids]
153 print pair_ids,"NOT FOUND, swapping to",(pair_ids[1], pair_ids[0])
154 # If not found, invert the pair
155 xlinks_list = self[(pair_ids[1], pair_ids[0])]
156 # swap the xlinks, so the first element of the pair corresponds
157 # to the first id in the xlink
158 for xl in xlinks_list:
160 for xl in xlinks_list:
169 Compute the order of the docking experiments. The order is derived
170 from the cross-linking restraints:
171 1) The subunit with the highest number of cross-links with others
172 works as the first receptor (A)
173 2) All the subunits cross-linked with A are docked into A.
174 3) The next receptor (B) is the subunit that has the highest number of
176 4) All the subunits cross-linked to B are docked into B (except A)
177 5) The procedure is repeated until there are no more cross-links
185 Instead of setting the xlink restraints, init the graph directly
186 Example of what to pass with the structure in 3sfd
187 G.add_nodes_from(["A", "B", "C", "D"])
188 G.add_edges_from([("B","C"), ("B","A"), ("B","D"), ("C","D")])
189 ("B","C") means that there are cross-links between B and C
191 self.G.add_nodes_from(subunits)
192 self.G.add_edges_from(edges)
196 Sets the xlinks used for computing the docking order
197 @param xlinks_dict XlinksDict class
203 """ return the order to dock components from the cross links """
205 degs = self.G.degree(self.G.nodes())
206 log.debug(
"Degrees: %s", degs)
207 sorted_degrees = sorted(((v, k)
for (k, v)
in dict(degs).items()),
210 receptors_considered = []
211 for degree, node
in sorted_degrees:
212 for n
in self.G.neighbors(node):
213 if n
not in receptors_considered:
214 docking_pairs.append((node, n))
215 receptors_considered.append(node)
216 log.info(
"The suggested order for the docking pairs is %s",
224 Puts two subunits together using the Xlinkins restraints. The solutions
225 offered by this class are just an initial position of the components
229 def clear_xlinks(self):
230 self.xlinks_list = []
234 Sets the xlinks used for the computation for the initial rough
236 @param xlinks_list A list of Xlink classes
237 residue1 belongs to the receptor and residue2 belongs to the ligand
239 self.xlinks_list = xlinks_list
243 Set the name of the PDB files of the receptor and the ligand
249 self.h_receptor = atom.read_pdb(fn_receptor, self.m_receptor, sel)
251 self.h_ligand = atom.read_pdb(fn_ligand, self.m_ligand, sel)
255 Set the hierarchies (atom.Hierarchy objects) for the receptor and
260 self.h_receptor = h_receptor
261 self.h_ligand = h_ligand
265 Sets the rigid bodies (core.RigidBody objects) for the receptor and
270 self.rb_receptor = rb_receptor
271 self.rb_ligand = rb_ligand
275 Movest the ligand close to the receptor based on the xlinks
276 provided by set_xlinks()
278 log.debug(
"Moving ligand close to the receptor using the xlinks")
279 n = len(self.xlinks_list)
287 Get the particle representing a residue in a hierarchy
288 @param h atom.Hierarchy containing the residue
289 @param ch The chain id
290 @param res index of the residue
293 return s.get_selected_particles()[0]
297 Get the coordinates for a residue in a molecular hierarchy
298 @param h atom.Hierarchy object
299 @param ch The chain id
300 @param res Residue index
303 return core.XYZ(p).get_coordinates()
307 Write a pdb file the coordinates of the ligand
310 atom.write_pdb(self.h_ligand, fn)
314 Put the residues in a random distance between 0 and the maximum
315 cross-linkin distance
317 xl = self.xlinks_list[0]
320 sph = alg.Sphere3D(center, xl.distance)
321 v = alg.get_random_vector_in(sph)
322 ref = self.rb_ligand.get_reference_frame()
323 coords = ref.get_transformation_to().get_translation()
324 R = ref.get_transformation_to().get_rotation()
327 log.debug(
"Ligand residue before moving %s", lig)
328 displacement = v - lig
329 T = alg.Transformation3D(R, coords + displacement)
330 self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(T))
332 self.h_ligand, xl.second_chain,
334 log.debug(
"ligand after moving %s", new_coords)
338 Function equivalent to move_one_xlink() for the case where there
339 are more than one cross-link restraints available.
340 Puts the ligand residues as close as possible to the receptor
345 for xl
in self.xlinks_list:
352 log.debug(
"Receptor residues before moving %s", rec_coords)
353 log.debug(
"Ligand residues before moving %s", lig_coords)
354 ref = self.rb_ligand.get_reference_frame()
355 Tr = alg.get_transformation_aligning_first_to_second(lig_coords,
357 T = ref.get_transformation_to()
358 newT = alg.compose(Tr, T)
359 self.rb_ligand.set_reference_frame(alg.ReferenceFrame3D(newT))
361 moved_lig_coords = []
362 for xl
in self.xlinks_list:
365 moved_lig_coords.append(c)
366 log.debug(
"Ligand residues after moving %s", moved_lig_coords)
def write_ligand
Write a pdb file the coordinates of the ligand.
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.
Class for storing model, its restraints, constraints, and particles.
Select all non-alternative ATOM records.
def set_xlinks
Sets the xlinks used for the computation for the initial 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
std::ostream & show(Hierarchy h, std::ostream &out=std::cout)
Print the hierarchy using a given decorator to display each node.
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
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.
def move_xlinks
Function equivalent to move_one_xlink() for the case where there are more than one cross-link restrai...