IMP  2.4.0
The Integrative Modeling Platform
comparisons.py
1 """@namespace IMP.EMageFit.imp_general.comparisons
2  Utility functions for comparisons.
3 """
4 
5 
6 import IMP
7 import IMP.algebra as alg
8 import IMP.core as core
9 import IMP.em as em
10 import IMP.atom as atom
11 import IMP.EMageFit.imp_general.alignments as alignments
12 import IMP.EMageFit.imp_general.representation as representation
13 
14 import random
15 import itertools
16 import math
17 import csv
18 import itertools
19 import logging
20 log = logging.getLogger("comparisons")
21 
22 
23 def get_coordinates(hierarchy):
24  xyz = [core.XYZ(l) for l in atom.get_leaves(hierarchy)]
25  coords = [x.get_coordinates() for x in xyz]
26  return coords
27 
28 
29 def get_assembly_placement_score(assembly, native_assembly, align=False):
30  """
31  Computes the placement score of an assembly respect to the native_assembly.
32  @param assembly. An atom.Molecule object
33  @param native_assembly An atom.Molecule object
34  @param align If True, assembly is aligned to native_assembly before
35  calculating the placement score
36  """
37 
38  distances, angles = get_components_placement_scores(assembly,
39  native_assembly, align)
40  n = 1. * len(distances)
41  return sum(distances) / n, sum(angles) / n
42 
43 
44 def get_components_placement_scores(assembly, native_assembly, align=False):
45  """
46  Compute the placement score of each of the children of an assembly.
47  The function does not do any time of alignment of the coordinates
48  @param assembly An atom.Molecule object
49  @param native_assembly An atom.Molecule object with the native conformation
50  Obviously the atoms in assembly and native assembly
51  must be the same
52  @return The function returns 2 lists. The first list contains the
53  placement distances of the children. The second list contains the
54  placnement angles
55  """
56  model_coords_per_child = [get_coordinates(c)
57  for c in assembly.get_children()]
58  native_coords_per_child = [get_coordinates(c)
59  for c in native_assembly.get_children()]
60  if align:
61  model_coords = []
62  nil = [model_coords.extend(x) for x in model_coords_per_child]
63  native_coords = []
64  nil = [native_coords.extend(x) for x in native_coords_per_child]
65  T = alg.get_transformation_aligning_first_to_second(model_coords,
66  native_coords)
67  # get aligned coordinates
68  new_model_coords_per_child = []
69  for c in model_coords_per_child:
70  coords = [T.get_transformed(x) for x in c]
71  new_model_coords_per_child.append(coords)
72  model_coords_per_child = new_model_coords_per_child
73  distances, angles = get_placement_scores_from_coordinates(
74  native_coords_per_child, model_coords_per_child)
75  return distances, angles
76 
77 
78 def get_placement_scores_from_coordinates(model_components_coords,
79  native_components_coords):
80  """
81  Computes the placement score for each of the components
82  @param model_components_coords A list with the coordinates for each
83  component
84  @param native_components_coords A list with the coordinates for each
85  component in the native assembly
86  """
87  distances = []
88  angles = []
89  for model_coords, native_coords in zip(
90  model_components_coords, native_components_coords):
91  distance, angle = get_placement_score_from_coordinates(model_coords,
92  native_coords)
93  distances.append(distance)
94  angles.append(angle)
95  return distances, angles
96 
97 
98 def get_placement_score_from_coordinates(model_coords, native_coords):
99  """
100  Computes the position error (placement distance) and the orientation
101  error (placement angle) of the coordinates in model_coords respect to
102  the coordinates in native_coords.
103  placement distance - translation between the centroids of the
104  coordinates
105  placement angle - Angle in the axis-angle formulation of the rotation
106  aligning the two rigid bodies.
107  """
108  native_centroid = alg.get_centroid(native_coords)
109  model_centroid = alg.get_centroid(model_coords)
110  translation_vector = native_centroid - model_centroid
111  distance = translation_vector.get_magnitude()
112  if(len(model_coords) != len(native_coords)):
113  raise ValueError(
114  "Mismatch in the number of members %d %d " % (
115  len(model_coords),
116  len(native_coords)))
117  TT = alg.get_transformation_aligning_first_to_second(model_coords,
118  native_coords)
119  P = alg.get_axis_and_angle(TT.get_rotation())
120  angle = P.second
121  return distance, angle
122 
123 
124 def get_rmsd(hierarchy1, hierarchy2):
125  xyz1 = [core.XYZ(l) for l in atom.get_leaves(hierarchy1)]
126  xyz2 = [core.XYZ(l) for l in atom.get_leaves(hierarchy2)]
127  return atom.get_rmsd(xyz1, xyz2)
128 
129 
130 def get_ccc(native_assembly, assembly, resolution, voxel_size,
131  threshold, write_maps=False):
132  """
133  Threshold - threshold used for the map of the native assembly. Pixels
134  with values above this threshold in the native map are used for the
135  calculation of the cross_correlation_coefficient
136  """
137  import IMP.em as em
138  particles_native = atom.get_leaves(native_assembly)
139  particles_solution = atom.get_leaves(assembly)
140  bb_native = core.get_bounding_box(core.XYZs(particles_native))
141  bb_solution = core.get_bounding_box(core.XYZs(particles_solution))
142  # bounding box enclosing both the particles of the native assembly
143  # and the particles of the model
144  bb_union = alg.get_union(bb_native, bb_solution)
145  # add border of 4 voxels
146  border = 4 * voxel_size
147  bottom = bb_union.get_corner(0)
148  bottom += alg.Vector3D(-border, -border, -border)
149  top = bb_union.get_corner(1)
150  top += alg.Vector3D(border, border, border)
151  bb_union = alg.BoundingBox3D(bottom, top)
152 
153  mrw = em.MRCReaderWriter()
154  header = em.create_density_header(bb_union, voxel_size)
155  header.set_resolution(resolution)
156 
157  map_native = em.SampledDensityMap(header)
158  map_native.set_particles(particles_native)
159  map_native.resample()
160 
161  map_solution = em.SampledDensityMap(header)
162  map_solution.set_particles(particles_solution)
163  map_solution.resample()
164 
165  if(write_maps):
166  em.write_map(map_solution, "map_solution.mrc", mrw)
167  em.write_map(map_native, "map_native.mrc", mrw)
168  map_native.calcRMS()
169  map_solution.calcRMS()
170  coarse_cc = em.CoarseCC()
171  # base the calculation of the cross_correlation coefficient on the threshold]
172  # for the native map, because the threshold for the map of the model changes
173  # with each model
174  threshold = 0.25 # threshold AFTER normalization using calcRMS()
175  ccc = coarse_cc.cross_correlation_coefficient(map_solution,
176  map_native, threshold)
177  log.debug("cross_correlation_coefficient (based on native_map "
178  "treshold %s) %s", threshold, ccc)
179  return ccc
180 
181 
182 def get_drms_for_backbone(assembly, native_assembly):
183  """
184  Measure the DRMS ob the backbone between two assemblies.
185  @param assembly The DRMS is computed for this assembly
186  @param native_assembly The assembly that acts as a reference
187 
188  Notes:
189  1) The components of the assembly can be proteins or nucleic acids
190  2) If a protein, the c-alphas are used for calculating the drms
191  3) If a nucleic acid, the backbone of C4' atoms is used
192  4) The chains are treated as rigid bodies to speed the calculation.
193 
194  WARNING: if the function fails with a segmentation fault, one of the
195  possible problems is that IMP reads some HETATM as calphas. Check that
196  the chain does not have heteroatoms.
197  """
198  log.debug("Measuring DRMS of the backbone")
199  begin_range = 0
200  ranges = []
201  backbone = []
202  h_chains = atom.get_by_type(assembly, atom.CHAIN_TYPE)
203  for h in h_chains:
204  atoms = representation.get_backbone(h)
205  """"
206  for a in atoms:
207  print "atom ===> ",
208  at = atom.Atom(a)
209  hr = at.get_parent()
210  res = atom.Residue(hr)
211  ch = atom.Chain(h)
212  ch.show()
213  print " - ",
214  res.show()
215  print " - ",
216  at.show()
217  print ""
218  """
219  backbone.extend(atoms)
220  end_range = begin_range + len(atoms)
221  ranges.append((begin_range, end_range))
222  begin_range = end_range
223  log.debug("Ranges %s number of atoms %s", ranges, len(backbone))
224  xyzs = [core.XYZ(l) for l in backbone]
225  native_chains = atom.get_by_type(native_assembly, atom.CHAIN_TYPE)
226  names = [atom.Chain(ch).get_id() for ch in native_chains]
227  native_backbone = []
228  for h in native_chains:
229  native_backbone.extend(representation.get_backbone(h))
230  native_xyzs = [core.XYZ(l) for l in native_backbone]
231  if len(xyzs) != len(native_xyzs):
232  raise ValueError(
233  "Cannot compute DRMS for sets of atoms of different size")
234  log.debug("Getting rigid bodies rmsd")
235  drms = atom.get_rigid_bodies_drms(xyzs, native_xyzs, ranges)
236  if drms < 0 or math.isnan(drms): # or drms > 100:
237  log.debug(
238  "len(xyzs) = %s. len(native_xyzs) = %s",
239  len(xyzs),
240  len(native_xyzs))
241  log.debug("drms = %s", drms)
242  atom.write_pdb(assembly, "drms_model_calphas.pdb")
243  atom.write_pdb(native_assembly, "drms_native_calphas.pdb")
244  raise ValueError("There is a problem with the drms. I wrote the pdbs "
245  "for you: drms_model_calphas.pdb drms_native_calphas.pdb")
246  return drms
def get_assembly_placement_score
Computes the placement score of an assembly respect to the native_assembly.
Definition: comparisons.py:29
def get_placement_scores_from_coordinates
Computes the placement score for each of the components.
Definition: comparisons.py:78
Utility functions to handle representation.
Utility functions to handle alignments.
Definition: alignments.py:1
def get_drms_for_backbone
Measure the DRMS ob the backbone between two assemblies.
Definition: comparisons.py:182
Responsible for performing coarse fitting between two density objects.
Definition: CoarseCC.h:28
Class for sampling a density map from particles.
double get_rmsd(const Vector3DsOrXYZs0 &m1, const Vector3DsOrXYZs1 &m2)
def get_ccc
Threshold - threshold used for the map of the native assembly.
Definition: comparisons.py:130
Basic utilities for handling cryo-electron microscopy 3D density maps.
A decorator for a particle with x,y,z coordinates.
Definition: XYZ.h:30
def get_placement_score_from_coordinates
Computes the position error (placement distance) and the orientation error (placement angle) of the c...
Definition: comparisons.py:98
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...
Store info for a chain of a protein.
Definition: Chain.h:21
def get_components_placement_scores
Compute the placement score of each of the children of an assembly.
Definition: comparisons.py:44
Functionality for loading, creating, manipulating and scoring atomic structures.