def _search_hbond(self, O_atom, C_atom, N_atom, chain_around):
   def good_hbond(angle, distance):
     return angle > 140 and distance < 3.8
   results = []
   atoms = self.model.get_atoms()
   for atom in [atoms[i_seq] for i_seq in self.atoms_around]:
     # no need to check the same residue, looking for N atom for bonding
     if atom.parent() == O_atom.parent() or atom.parent() == N_atom.parent():
       # print "skipping same residue ", atom.id_str()
       continue
     if atom.name.strip() == 'N':
       angle = geometry_restraints.angle(
           sites=[C_atom.xyz, O_atom.xyz, atom.xyz],
           angle_ideal=0,
           weight=1).angle_model
       if good_hbond(angle, atom.distance(O_atom)):
         # print "Potential bond:", atom.id_str(), atom.distance(O_atom), angle
         results.append(('forward', atom.distance(O_atom), angle))
     if atom.name.strip() == 'O':
       # now we want to find attached N atom (another one)
       another_C_atom = atom.parent().get_atom("C")
       if another_C_atom is not None:
         angle = geometry_restraints.angle(
             sites=[another_C_atom.xyz, atom.xyz, N_atom.xyz],
             angle_ideal=0,
             weight=1).angle_model
         if good_hbond(angle, atom.distance(N_atom)):
           # print "Potential backwards bond:", atom.id_str(), atom.distance(N_atom), angle
           results.append(('backward', atom.distance(N_atom), angle))
   return results
def exercise_angle():
  eps = 1
  n_trials = 20
  for i_trial in xrange(n_trials):
    if (i_trial < -99):
      if (i_trial == n_trials-1):
        eps = 0
      else:
        eps *= 0.1
      sites = [col(site) for site in [(-1,0,0),(0,0,0),(1,eps,0)]]
      angle_ideal = 170
    else:
      while 1:
        sites = random_sites(n_sites=3)
        angle_ideal = geometry_restraints.angle(
          sites, angle_ideal=0, weight=0).angle_model
        if (angle_ideal > 10):
          break
    sigma = angle_ideal * 0.1
    weight = 1 / sigma**2
    residual_obj = residual_functor(
      restraint_type=geometry_restraints.angle,
      angle_ideal=angle_ideal,
      weight=weight)
    for i_pert in xrange(5):
      if (i_pert == 0):
        sites_mod = sites
      else:
        sites_mod = []
        for site in sites:
          shift = col([random.uniform(3,3)*sigma for i in xrange(3)])
          sites_mod.append(site+shift)
      a = geometry_restraints.angle(
        sites=sites_mod, angle_ideal=angle_ideal, weight=weight)
      if (eps != 0):
        ag = a.gradients()
      fg = finite_differences(sites_mod, residual_obj)
      if (eps == 0):
        for finite in fg:
          print finite
          print
      else:
        for analytical,finite in zip(ag,fg):
          if (0):
            print analytical
            print finite
          if (0):
            for x,y in zip(analytical, finite):
              if (y == 0): print None,
              else: print x/y,
            print
          if (0):
            print
          assert approx_equal(analytical, finite,
                              eps=max(1.e-6,max(analytical)*1.e-6))
Example #3
0
def get_angle_outliers(angle_proxies, chain, sites_cart, hierarchy):
  i_seq_name_hash = build_name_hash(pdb_hierarchy=hierarchy)
  kin_text = "@subgroup {geom devs} dominant\n"
  for ap in angle_proxies:
    restraint = geometry_restraints.angle(sites_cart=sites_cart,
                                          proxy=ap)
    res = i_seq_name_hash[ap.i_seqs[0]][5:]
    altloc = i_seq_name_hash[ap.i_seqs[0]][4:5].lower()
    cur_chain = i_seq_name_hash[ap.i_seqs[0]][8:10]
    if chain.id.strip() is not cur_chain.strip():
      continue
    atom1 = i_seq_name_hash[ap.i_seqs[0]][0:4].strip()
    atom2 = i_seq_name_hash[ap.i_seqs[1]][0:4].strip()
    atom3 = i_seq_name_hash[ap.i_seqs[2]][0:4].strip()
    if atom1[0] == "H" or atom2[0] == "H" or atom3[0] == "H":
      continue
    sigma = ((1/restraint.weight)**(.5))
    num_sigmas = - (restraint.delta / sigma) #negative to match MolProbity direction
    if abs(num_sigmas) >= 4.0:
      angle_key = altloc+res[0:3].lower()+res[3:]+' '+atom1.lower()+ \
                  '-'+atom2.lower()+'-'+atom3.lower()
      kin = add_fan(sites=restraint.sites,
                    delta=restraint.delta,
                    num_sigmas=num_sigmas,
                    angle_key=angle_key)
      kin_text += kin
  return kin_text
Example #4
0
def angles_as_cif_loop(xray_structure, proxies):
    space_group_info = sgtbx.space_group_info(
        group=xray_structure.space_group())
    unit_cell = xray_structure.unit_cell()
    sites_cart = xray_structure.sites_cart()
    site_labels = xray_structure.scatterers().extract_labels()
    fmt = "%.4f"
    loop = model.loop(header=(
        "_restr_angle_atom_site_label_1",
        "_restr_angle_atom_site_label_2",
        "_restr_angle_atom_site_label_3",
        "_restr_angle_site_symmetry_1",
        "_restr_angle_site_symmetry_2",
        "_restr_angle_site_symmetry_3",
        "_restr_angle_target",
        "_restr_angle_target_weight_param",
        "_restr_angle_diff",
    ))
    unit_mxs = [sgtbx.rt_mx()] * 3
    for proxy in proxies:
        restraint = geometry_restraints.angle(unit_cell=unit_cell,
                                              sites_cart=sites_cart,
                                              proxy=proxy)
        sym_ops = proxy.sym_ops
        if sym_ops is None: sym_ops = unit_mxs
        i_seqs = proxy.i_seqs
        loop.add_row(
            (site_labels[i_seqs[0]], site_labels[i_seqs[1]],
             site_labels[i_seqs[2]],
             space_group_info.cif_symmetry_code(sym_ops[0]),
             space_group_info.cif_symmetry_code(sym_ops[1]),
             space_group_info.cif_symmetry_code(sym_ops[2]),
             fmt % restraint.angle_ideal,
             fmt % math.sqrt(1 / restraint.weight), fmt % restraint.delta))
    return loop
Example #5
0
def ca_measures(protein):
  for resid2 in protein:
    res2 = protein[resid2]  #residue n
    gotall = False
    if res2.prevres:
      res1 = res2.prevres  # n-1
      if res1.prevres:
        res0 = res1.prevres  # n-2
        if res2.nextres:
          res3 = res2.nextres  # n+1
          if res3.nextres:
            res4 = res3.nextres  # n+2
            gotall = True
    if not gotall:
      continue

    CA_0 = res0.getatomxyz('CA')
    CA_1 = res1.getatomxyz('CA')
    CA_2 = res2.getatomxyz('CA')
    CA_3 = res3.getatomxyz('CA')
    CA_4 = res4.getatomxyz('CA')
    if None in [CA_0,CA_1,CA_2,CA_3,CA_4]:
      #getatomxyz returns either an xyz list (tuple?) or None
      continue

    d_in = geometry_restraints.dihedral(sites=[CA_0,CA_1,CA_2,CA_3],
      angle_ideal=-40, weight=1)
    d_out = geometry_restraints.dihedral(sites=[CA_1,CA_2,CA_3,CA_4],
      angle_ideal=-40, weight=1)
    a     = geometry_restraints.angle(sites=[CA_1,CA_2,CA_3],
      angle_ideal=120, weight=1)

    res2.measures['CA_d_in']  = d_in.angle_model
    res2.measures['CA_d_out'] = d_out.angle_model
    res2.measures['CA_a']     = a.angle_model
 def _get_angle(sites_cart, angle_proxies, i_proxy):
     if i_proxy is not None:
         # compute angle
         angle = geometry_restraints.angle(sites_cart=sites_cart,
                                           proxy=angle_proxies[i_proxy])
         return angle
     return None
Example #7
0
def CApseudos(protein, dodihedrals=True, doangles=True):
    for resid2 in protein:
        res2 = protein[resid2]  #residue n
        gotall = False
        if res2.prevres:
            res1 = res2.prevres  # n-1
            if res1.prevres:
                res0 = res1.prevres  # n-2
                if res2.nextres:
                    res3 = res2.nextres  # n+1
                    if res3.nextres:
                        res4 = res3.nextres  # n+2
                        gotall = True
        if not gotall:
            continue

        CA_0 = res0.getatomxyz('CA')
        CA_1 = res1.getatomxyz('CA')
        CA_2 = res2.getatomxyz('CA')
        CA_3 = res3.getatomxyz('CA')
        CA_4 = res4.getatomxyz('CA')
        if None in [CA_0, CA_1, CA_2, CA_3, CA_4]:
            continue

        if dodihedrals:
            d_in = geometry_restraints.dihedral(sites=[CA_0, CA_1, CA_2, CA_3],
                                                angle_ideal=-40,
                                                weight=1)
            d_out = geometry_restraints.dihedral(
                sites=[CA_1, CA_2, CA_3, CA_4], angle_ideal=-40, weight=1)

            res2.measures['CA_d_in'] = d_in.angle_model
            res2.measures['CA_d_out'] = d_out.angle_model

        if doangles:
            a_in = geometry_restraints.angle(sites=[CA_0, CA_1, CA_2],
                                             angle_ideal=120,
                                             weight=1)
            a = geometry_restraints.angle(sites=[CA_1, CA_2, CA_3],
                                          angle_ideal=120,
                                          weight=1)
            a_out = geometry_restraints.angle(sites=[CA_2, CA_3, CA_4],
                                              angle_ideal=120,
                                              weight=1)
            res2.measures['CA_a_in'] = a_in.angle_model
            res2.measures['CA_a'] = a.angle_model
            res2.measures['CA_a_out'] = a_out.angle_model
Example #8
0
def CApseudos(protein, dodihedrals = True, doangles = True):
  for resid2 in protein:
    res2 = protein[resid2]  #residue n
    gotall = False
    if res2.prevres:
      res1 = res2.prevres  # n-1
      if res1.prevres:
        res0 = res1.prevres  # n-2
        if res2.nextres:
          res3 = res2.nextres  # n+1
          if res3.nextres:
            res4 = res3.nextres  # n+2
            gotall = True
    if not gotall:
      continue

    CA_0 = res0.getatomxyz('CA')
    CA_1 = res1.getatomxyz('CA')
    CA_2 = res2.getatomxyz('CA')
    CA_3 = res3.getatomxyz('CA')
    CA_4 = res4.getatomxyz('CA')
    if None in [CA_0,CA_1,CA_2,CA_3,CA_4]:
      continue

    if dodihedrals:
      d_in = geometry_restraints.dihedral(sites=[CA_0,CA_1,CA_2,CA_3],
        angle_ideal=-40, weight=1)
      d_out = geometry_restraints.dihedral(sites=[CA_1,CA_2,CA_3,CA_4],
        angle_ideal=-40, weight=1)

      res2.measures['CA_d_in']  = d_in.angle_model
      res2.measures['CA_d_out'] = d_out.angle_model

    if doangles:
      a_in  = geometry_restraints.angle(sites=[CA_0,CA_1,CA_2],
        angle_ideal=120, weight=1)
      a     = geometry_restraints.angle(sites=[CA_1,CA_2,CA_3],
        angle_ideal=120, weight=1)
      a_out = geometry_restraints.angle(sites=[CA_2,CA_3,CA_4],
        angle_ideal=120, weight=1)
      res2.measures['CA_a_in']  = a_in.angle_model
      res2.measures['CA_a']     = a.angle_model
      res2.measures['CA_a_out'] = a_out.angle_model
Example #9
0
def write_plots(method, rot_scale=2, rot_step=1, c_truncate_at=-2e4):
    assert method in ["ana", "fin"]
    plot_file_names = []
    site0 = (-1, 0, 0)
    site1 = (0, 0, 0)
    axis = matrix.col((0, 0, 1))
    for angle_ideal in [180, 120]:

        def init_plots():
            result = []
            for j in range(3):
                result.append([])
            return result

        g_plots = init_plots()
        c_plots = init_plots()
        for rot_deg_sc in range(90 * rot_scale, 270 * rot_scale + rot_step,
                                rot_step):
            rot_deg = rot_deg_sc / rot_scale
            r = axis.axis_and_angle_as_r3_rotation_matrix(angle=rot_deg,
                                                          deg=True)
            a = angle(sites=[site0, site1, r * site0],
                      angle_ideal=angle_ideal,
                      weight=1)
            if (method == "ana"):
                gc = a.grads_and_curvs()
            else:
                gc = derivs_fd(a=a, order=1)
                gc.extend(derivs_fd(a=a, order=2))
            for j in range(3):
                g_plots[j].append((rot_deg, gc[2][j]))
            for j in range(3):
                c_plots[j].append((rot_deg, gc[5][j]))

        def write(deriv, plots):
            file_name = "angle_%d_%s_%s.xy" % (angle_ideal, deriv, method)
            plot_file_names.append(file_name)
            f = open(file_name, "w")
            print("@with g0", file=f)
            print('@ title "%s ideal=%d method=%s"' %
                  (deriv, angle_ideal, method),
                  file=f)
            for j in range(3):
                print('@ s%d legend "%s"' % (j, "xyz"[j]), file=f)
            for plot in plots:
                for x, y in plot:
                    if (deriv == "curv" and y < c_truncate_at):
                        y = c_truncate_at
                    print(x, y, file=f)
                print("&", file=f)

        write(deriv="grad", plots=g_plots)
        write(deriv="curv", plots=c_plots)
    return plot_file_names
Example #10
0
def taucalc(protein):
  for resid2 in protein:
    res2 = protein[resid2]

    N  = res2.getatomxyz('N')
    CA = res2.getatomxyz('CA')
    C  = res2.getatomxyz('C')
    if None in [N,CA,C]:
      continue

    tau = geometry_restraints.angle(sites=[N,CA,C], angle_ideal=120, weight=1)
    res2.measures['tau']  = tau.angle_model
Example #11
0
def taucalc(protein):
    for resid2 in protein:
        res2 = protein[resid2]

        N = res2.getatomxyz('N')
        CA = res2.getatomxyz('CA')
        C = res2.getatomxyz('C')
        if None in [N, CA, C]:
            continue

        tau = geometry_restraints.angle(sites=[N, CA, C],
                                        angle_ideal=120,
                                        weight=1)
        res2.measures['tau'] = tau.angle_model
def write_plots(method, rot_scale=2, rot_step=1, c_truncate_at=-2e4):
  assert method in ["ana", "fin"]
  plot_file_names = []
  site0 = (-1,0,0)
  site1 = (0,0,0)
  axis = matrix.col((0,0,1))
  for angle_ideal in [180, 120]:
    def init_plots():
      result = []
      for j in xrange(3):
        result.append([])
      return result
    g_plots = init_plots()
    c_plots = init_plots()
    for rot_deg_sc in xrange(90*rot_scale, 270*rot_scale+rot_step, rot_step):
      rot_deg = rot_deg_sc / rot_scale
      r = axis.axis_and_angle_as_r3_rotation_matrix(angle=rot_deg, deg=True)
      a = angle(
        sites=[site0, site1, r*site0],
        angle_ideal=angle_ideal,
        weight=1)
      if (method == "ana"):
        gc = a.grads_and_curvs()
      else:
        gc = derivs_fd(a=a, order=1)
        gc.extend(derivs_fd(a=a, order=2))
      for j in xrange(3):
        g_plots[j].append((rot_deg, gc[2][j]))
      for j in xrange(3):
        c_plots[j].append((rot_deg, gc[5][j]))
    def write(deriv, plots):
      file_name = "angle_%d_%s_%s.xy" % (angle_ideal, deriv, method)
      plot_file_names.append(file_name)
      f = open(file_name, "w")
      print >> f, "@with g0"
      print >> f, '@ title "%s ideal=%d method=%s"' % (
        deriv, angle_ideal, method)
      for j in xrange(3):
        print >> f, '@ s%d legend "%s"' % (j, "xyz"[j])
      for plot in plots:
        for x,y in plot:
          if (deriv == "curv" and y < c_truncate_at): y = c_truncate_at
          print >> f, x,y
        print >> f, "&"
    write(deriv="grad", plots=g_plots)
    write(deriv="curv", plots=c_plots)
  return plot_file_names
Example #13
0
def cablam_measures(protein):
    for resid2 in protein:
        res2 = protein[resid2]  #residue n
        gotall = False
        if res2.prevres:
            res1 = res2.prevres  # n-1
            if res1.prevres:
                res0 = res1.prevres  # n-2
                if res2.nextres:
                    res3 = res2.nextres  # n+1
                    if res3.nextres:
                        res4 = res3.nextres  # n+2
                        gotall = True
        if not gotall:
            continue

        CA_0 = res0.getatomxyz('CA')
        CA_1, O_1 = res1.getatomxyz('CA'), res1.getatomxyz('O')
        CA_2, O_2 = res2.getatomxyz('CA'), res2.getatomxyz('O')
        CA_3 = res3.getatomxyz('CA')
        CA_4 = res4.getatomxyz('CA')
        if None in [CA_0, CA_1, CA_2, CA_3, CA_4, O_1, O_2]:
            #getatomxyz returns either an xyz list (tuple?) or None
            continue

        d_in = geometry_restraints.dihedral(sites=[CA_0, CA_1, CA_2, CA_3],
                                            angle_ideal=-40,
                                            weight=1)
        d_out = geometry_restraints.dihedral(sites=[CA_1, CA_2, CA_3, CA_4],
                                             angle_ideal=-40,
                                             weight=1)
        pseudoC_1 = perptersect(CA_1, CA_2, O_1)
        pseudoC_2 = perptersect(CA_2, CA_3, O_2)
        co_in = geometry_restraints.dihedral(
            sites=[O_1, pseudoC_1, pseudoC_2, O_2], angle_ideal=-40, weight=1)
        ca_a = geometry_restraints.angle(sites=[CA_1, CA_2, CA_3],
                                         angle_ideal=120,
                                         weight=1)

        res2.measures['CA_d_in'] = d_in.angle_model
        res2.measures['CA_d_out'] = d_out.angle_model
        res2.measures['CO_d_in'] = co_in.angle_model
        res2.measures['CA_a'] = ca_a.angle_model
Example #14
0
def derivs_fd(a, order, eps=1.e-6):
  result = flex.vec3_double()
  sites0 = a.sites
  sites = [list(site) for site in sites0]
  for i_site in xrange(3):
    ds = []
    for i_dim in xrange(3):
      samples = []
      for signed_eps in [eps, -eps]:
        sites[i_site][i_dim] = sites0[i_site][i_dim] + signed_eps
        a_eps = angle(sites=sites, angle_ideal=a.angle_ideal, weight=a.weight)
        if (order == 1):
          samples.append(a_eps.residual())
        elif (order == 2):
          samples.append(a_eps.gradients()[i_site][i_dim])
        else:
          raise RuntimeError
      sites[i_site][i_dim] = sites0[i_site][i_dim]
      ds.append((samples[0]-samples[1])/(2*eps))
    result.append(tuple(ds))
  return result
Example #15
0
 def __init__(self,
              pdb_hierarchy,
              pdb_atoms,
              geometry_restraints_manager,
              outliers_only=True):
     rna_geometry.__init__(self)
     cutoff = 4
     sites_cart = pdb_atoms.extract_xyz()
     flags = geometry_restraints.flags.flags(default=True)
     i_seq_name_hash = utils.build_name_hash(pdb_hierarchy=pdb_hierarchy)
     for proxy in geometry_restraints_manager.angle_proxies:
         restraint = geometry_restraints.angle(sites_cart=sites_cart,
                                               proxy=proxy)
         atom1 = pdb_atoms[proxy.i_seqs[0]].name
         atom2 = pdb_atoms[proxy.i_seqs[1]].name
         atom3 = pdb_atoms[proxy.i_seqs[2]].name
         labels = pdb_atoms[proxy.i_seqs[0]].fetch_labels()
         if (atom1.strip() not in rna_backbone_atoms
                 or atom2.strip() not in rna_backbone_atoms
                 or atom3.strip() not in rna_backbone_atoms):
             continue
         self.n_total += 1
         sigma = sqrt(1 / restraint.weight)
         num_sigmas = restraint.delta / sigma
         is_outlier = (abs(num_sigmas) >= cutoff)
         if (is_outlier or not outliers_only):
             self.n_outliers += 1
             self.results.append(
                 rna_angle(chain_id=labels.chain_id,
                           resseq=labels.resseq,
                           icode=labels.icode,
                           altloc=labels.altloc,
                           resname=labels.resname,
                           atoms_info=validation.get_atoms_info(
                               pdb_atoms, proxy.i_seqs),
                           sigma=sigma,
                           score=num_sigmas,
                           delta=restraint.delta,
                           outlier=is_outlier))
Example #16
0
def angles_as_cif_loop(xray_structure, proxies):
  space_group_info = sgtbx.space_group_info(group=xray_structure.space_group())
  unit_cell = xray_structure.unit_cell()
  sites_cart = xray_structure.sites_cart()
  site_labels = xray_structure.scatterers().extract_labels()
  fmt = "%.4f"
  loop = model.loop(header=(
    "_restr_angle_atom_site_label_1",
    "_restr_angle_atom_site_label_2",
    "_restr_angle_atom_site_label_3",
    "_restr_angle_site_symmetry_1",
    "_restr_angle_site_symmetry_2",
    "_restr_angle_site_symmetry_3",
    "_restr_angle_target",
    "_restr_angle_target_weight_param",
    "_restr_angle_diff",
  ))
  unit_mxs = [sgtbx.rt_mx()]*3
  for proxy in proxies:
    restraint = geometry_restraints.angle(
      unit_cell=unit_cell,
      sites_cart=sites_cart,
      proxy=proxy)
    sym_ops = proxy.sym_ops
    if sym_ops is None: sym_ops = unit_mxs
    i_seqs = proxy.i_seqs
    loop.add_row((site_labels[i_seqs[0]],
                  site_labels[i_seqs[1]],
                  site_labels[i_seqs[2]],
                  space_group_info.cif_symmetry_code(sym_ops[0]),
                  space_group_info.cif_symmetry_code(sym_ops[1]),
                  space_group_info.cif_symmetry_code(sym_ops[2]),
                  fmt % restraint.angle_ideal,
                  fmt % math.sqrt(1/restraint.weight),
                  fmt % restraint.delta))
  return loop
Example #17
0
 def __init__ (self, pdb_hierarchy, pdb_atoms, geometry_restraints_manager,
               outliers_only=True) :
   rna_geometry.__init__(self)
   cutoff = 4
   sites_cart = pdb_atoms.extract_xyz()
   flags = geometry_restraints.flags.flags(default=True)
   i_seq_name_hash = utils.build_name_hash(pdb_hierarchy=pdb_hierarchy)
   for proxy in geometry_restraints_manager.angle_proxies:
     restraint = geometry_restraints.angle(
       sites_cart=sites_cart,
       proxy=proxy)
     atom1 = pdb_atoms[proxy.i_seqs[0]].name
     atom2 = pdb_atoms[proxy.i_seqs[1]].name
     atom3 = pdb_atoms[proxy.i_seqs[2]].name
     labels = pdb_atoms[proxy.i_seqs[0]].fetch_labels()
     if (atom1.strip() not in rna_backbone_atoms or
         atom2.strip() not in rna_backbone_atoms or
         atom3.strip() not in rna_backbone_atoms):
       continue
     self.n_total += 1
     sigma = sqrt(1 / restraint.weight)
     num_sigmas = restraint.delta / sigma
     is_outlier = (abs(num_sigmas) >= cutoff)
     if (is_outlier or not outliers_only):
       self.n_outliers += 1
       self.results.append(rna_angle(
         chain_id=labels.chain_id,
         resseq=labels.resseq,
         icode=labels.icode,
         altloc=labels.altloc,
         resname=labels.resname,
         atoms_info=validation.get_atoms_info(pdb_atoms, proxy.i_seqs),
         sigma=sigma,
         score=num_sigmas,
         delta=restraint.delta,
         outlier=is_outlier))
Example #18
0
def run(args):
  assert args in [[], ["--verbose"]]
  if (len(args) == 0):
    out = null_out()
  else:
    out = sys.stdout
  #
  mt = flex.mersenne_twister(seed=0)
  #
  for i_trial in xrange(10):
    l0 = mt.random_double() + 0.5
    l1 = mt.random_double() + 0.5
    l2 = mt.random_double() + 0.5
    angle_model = mt.random_double() * 178 + 1 \
                + 180 * (mt.random_size_t() % 3 - 1)
    v = matrix.col(mt.random_double_point_on_sphere())
    axis = v.ortho()
    site1 = v * l1
    site0 = site1 + v * l0
    r = axis.axis_and_angle_as_r3_rotation_matrix(angle=angle_model, deg=True)
    site2 = site1 + (r * v) * l2
    a = angle(
      sites=[site0, site1, site2],
      angle_ideal=mt.random_double() * 720 - 360,
      weight=mt.random_double() * 10 + 0.1)
    assert approx_equal(min(
      abs(angle_delta_deg(angle_1=a.angle_model, angle_2= angle_model)),
      abs(angle_delta_deg(angle_1=a.angle_model, angle_2=-angle_model))), 0)
    check_derivs(out=out, a=a)
  #
  for site2 in [(0,2.3,0), (0,0,2.5)]:
    perm = flex.size_t([0,1,2])
    while True:
      a = angle(
        sites=tuple(flex.vec3_double(
          [(1.2,0,0), (0,0,0), site2]).select(perm)),
        angle_ideal=mt.random_double() * 720 - 360,
        weight=mt.random_double() * 10 + 0.1)
      check_derivs(out=out, a=a)
      if (not perm.next_permutation()):
        break
  #
  for site0 in [(1,0,0),(0,1,0),(0,0,1),(1,1,1)]:
    perm = flex.size_t([0,1,2])
    while True:
      a = angle(
        sites=tuple(flex.vec3_double(
          [site0, (0,0,0), -matrix.col(site0)]).select(perm)),
        angle_ideal=180,
        weight=1.3)
      check_derivs(out=out, a=a, expect_failure=True)
      if (not perm.next_permutation()):
        break
  #
  plot_file_names = []
  for method in ["ana", "fin"]:
    plot_file_names.extend(write_plots(method=method))
  f = open("angle_xy_as_pdf_commands", "w")
  for file_name in plot_file_names:
    print >> f, "ppdf %s > %s" % (file_name, file_name.replace(".xy", ".pdf"))
  f.close()
  #
  print "OK"
Example #19
0
  def ensemble_mean_geometry_stats(self,
                                   restraints_manager,
                                   xray_structure,
                                   ensemble_xray_structures,
                                   ignore_hd = True,
                                   verbose = False,
                                   out = None,
                                   return_pdb_string = False):
    if (out is None): out = sys.stdout
    if verbose:
      utils.print_header("Ensemble mean geometry statistics", out = out)
    ensemble_size = len(ensemble_xray_structures)
    print("Ensemble size : ", ensemble_size, file=out)

    # Dictionaries to store deltas
    ensemble_bond_deltas = {}
    ensemble_angle_deltas = {}
    ensemble_chirality_deltas = {}
    ensemble_planarity_deltas = {}
    ensemble_dihedral_deltas = {}

    # List to store rmsd of each model
    structures_bond_rmsd = flex.double()
    structures_angle_rmsd = flex.double()
    structures_chirality_rmsd = flex.double()
    structures_planarity_rmsd = flex.double()
    structures_dihedral_rmsd = flex.double()

    # Remove water and hd atoms from global restraints manager
    selection = flex.bool()
    for sc in xray_structure.scatterers():
      if sc.label.find('HOH') > -1:
        selection.append(True)
      else:
        selection.append(False)
    if ignore_hd:
      hd_selection = xray_structure.hd_selection()
      assert hd_selection.size() == selection.size()
      for n in range(hd_selection.size()):
        if hd_selection[n] or selection[n]:
          selection[n] = True
    restraints_manager = restraints_manager.select(selection = ~selection)

    # Get all deltas
    for n, structure in enumerate(ensemble_xray_structures):
      if verbose:
        print("\nModel : ", n+1, file=out)
      sites_cart = structure.sites_cart()
      # Remove water and hd atoms from individual structures sites cart
      selection = flex.bool()
      for sc in structure.scatterers():
        if sc.label.find('HOH') > -1:
          selection.append(True)
        else:
          selection.append(False)
      if ignore_hd:
        hd_selection = structure.hd_selection()
        assert hd_selection.size() == selection.size()
        for n in range(hd_selection.size()):
          if hd_selection[n] or selection[n]:
            selection[n] = True
      sites_cart = sites_cart.select(~selection)
      assert sites_cart is not None
      site_labels = None
      energies_sites = restraints_manager.energies_sites(
          sites_cart        = sites_cart,
          compute_gradients = False)

      # Rmsd of individual model
      bond_rmsd = energies_sites.geometry.bond_deviations()[2]
      angle_rmsd = energies_sites.geometry.angle_deviations()[2]
      chirality_rmsd = energies_sites.geometry.chirality_deviations()[2]
      planarity_rmsd = energies_sites.geometry.planarity_deviations()[2]
      dihedral_rmsd = energies_sites.geometry.dihedral_deviations()[2]

      structures_bond_rmsd.append(bond_rmsd)
      structures_angle_rmsd.append(angle_rmsd)
      structures_chirality_rmsd.append(chirality_rmsd)
      structures_planarity_rmsd.append(planarity_rmsd)
      structures_dihedral_rmsd.append(dihedral_rmsd)

      if verbose:
        print("  Model RMSD", file=out)
        print("    bond      : %.6g" % bond_rmsd, file=out)
        print("    angle     : %.6g" % angle_rmsd, file=out)
        print("    chirality : %.6g" % chirality_rmsd, file=out)
        print("    planarity : %.6g" % planarity_rmsd, file=out)
        print("    dihedral  : %.6g" % dihedral_rmsd, file=out)

      # Bond
      pair_proxies = restraints_manager.geometry.pair_proxies(flags=None, sites_cart=sites_cart)
      assert pair_proxies is not None
      if verbose:
        pair_proxies.bond_proxies.show_histogram_of_deltas(
          sites_cart  = sites_cart,
          n_slots     = 10,
          f           = out)
      for proxy in pair_proxies.bond_proxies.simple:
        bond_simple_proxy = geometry_restraints.bond(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_bond_deltas:
          ensemble_bond_deltas[proxy.i_seqs][0]+=bond_simple_proxy.delta
          ensemble_bond_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_bond_deltas[proxy.i_seqs] = [bond_simple_proxy.delta, 1]
        if verbose:
          print("bond simple :", proxy.i_seqs, file=out)
          print("  distance_ideal : %.6g" % proxy.distance_ideal, file=out)
          print("  distance_model : %.6g" % bond_simple_proxy.distance_model, file=out)
          print("  detla          : %.6g" % bond_simple_proxy.delta, file=out)
      if (pair_proxies.bond_proxies.asu.size() > 0):
        asu_mappings = pair_proxies.bond_proxies.asu_mappings()
        for proxy in pair_proxies.bond_proxies.asu:
          rt_mx = asu_mappings.get_rt_mx_ji(pair=proxy)
          bond_asu_proxy = geometry_restraints.bond(
              sites_cart   = sites_cart,
              asu_mappings = asu_mappings,
              proxy        = proxy)
          proxy_i_seqs = (proxy.i_seq, proxy.j_seq)
          if proxy_i_seqs in ensemble_bond_deltas:
            ensemble_bond_deltas[proxy_i_seqs][0]+=bond_asu_proxy.delta
            ensemble_bond_deltas[proxy_i_seqs][1]+=1
          else:
            ensemble_bond_deltas[proxy_i_seqs] = [bond_asu_proxy.delta, 1]
          if verbose:
            print("bond asu :", (proxy.i_seq, proxy.j_seq), rt_mx, file=out)
            print("  distance_ideal : %.6g" % proxy.distance_ideal, file=out)
            print("  distance_model : %.6g" % bond_asu_proxy.distance_model, file=out)
            print("  delta          : %.6g" % bond_asu_proxy.delta, file=out)

      # Angle
      if verbose:
        restraints_manager.geometry.angle_proxies.show_histogram_of_deltas(
            sites_cart  = sites_cart,
            n_slots     = 10,
            f           = out)
      for proxy in restraints_manager.geometry.angle_proxies:
        angle_proxy = geometry_restraints.angle(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_angle_deltas:
          ensemble_angle_deltas[proxy.i_seqs][0]+=angle_proxy.delta
          ensemble_angle_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_angle_deltas[proxy.i_seqs] = [angle_proxy.delta, 1]
        if verbose:
          print("angle : ", proxy.i_seqs, file=out)
          print("  angle_ideal   : %.6g" % proxy.angle_ideal, file=out)
          print("  angle_model   : %.6g" % angle_proxy.angle_model, file=out)
          print("  delta         : %.6g" % angle_proxy.delta, file=out)

      # Chirality
      if verbose:
        restraints_manager.geometry.chirality_proxies.show_histogram_of_deltas(
            sites_cart  = sites_cart,
            n_slots     = 10,
            f           = out)
      for proxy in restraints_manager.geometry.chirality_proxies:
        chirality_proxy = geometry_restraints.chirality(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_chirality_deltas:
          ensemble_chirality_deltas[proxy.i_seqs][0]+=chirality_proxy.delta
          ensemble_chirality_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_chirality_deltas[proxy.i_seqs] = [chirality_proxy.delta, 1]
        if verbose:
          print("chirality : ", proxy.i_seqs, file=out)
          print("  chirality_ideal : %.6g" % proxy.volume_ideal, file=out)
          print("  chirality_model : %.6g" % chirality_proxy.volume_model, file=out)
          print("  chirality       : %.6g" % chirality_proxy.delta, file=out)

      # Planarity
      for proxy in restraints_manager.geometry.planarity_proxies:
        planarity_proxy = geometry_restraints.planarity(
            sites_cart = sites_cart,
            proxy      = proxy)
        proxy_i_seqs = []
        for i_seq in proxy.i_seqs:
          proxy_i_seqs.append(i_seq)
        proxy_i_seqs = tuple(proxy_i_seqs)
        if proxy_i_seqs in ensemble_planarity_deltas:
          ensemble_planarity_deltas[proxy_i_seqs][0]+=planarity_proxy.rms_deltas()
          ensemble_planarity_deltas[proxy_i_seqs][1]+=1
        else:
          ensemble_planarity_deltas[proxy_i_seqs] = [planarity_proxy.rms_deltas(), 1]
        if verbose:
          print("planarity : ", proxy_i_seqs, file=out)
          print("  planarity rms_deltas : %.6g" % planarity_proxy.rms_deltas(), file=out)

      # Dihedral
      if verbose:
        restraints_manager.geometry.dihedral_proxies.show_histogram_of_deltas(
            sites_cart  = sites_cart,
            n_slots     = 10,
            f           = out)
      for proxy in restraints_manager.geometry.dihedral_proxies:
        dihedral_proxy = geometry_restraints.dihedral(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_dihedral_deltas:
          ensemble_dihedral_deltas[proxy.i_seqs][0]+=dihedral_proxy.delta
          ensemble_dihedral_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_dihedral_deltas[proxy.i_seqs] = [dihedral_proxy.delta, 1]
        if verbose:
          print("dihedral : ", proxy.i_seqs, file=out)
          print("  dihedral_ideal  : %.6g" % proxy.angle_ideal, file=out)
          print("  periodicity     : %.6g" % proxy.periodicity, file=out)
          print("  dihedral_model  : %.6g" % dihedral_proxy.angle_model, file=out)
          print("  delta           : %.6g" % dihedral_proxy.delta, file=out)

    # Calculate RMSDs for ensemble model
    # Bond
    mean_bond_delta = flex.double()
    for proxy, info in six.iteritems(ensemble_bond_deltas):
      # assert info[1] == ensemble_size
      if info[1]!=ensemble_size:
        print('skipping bond RMSD calns of ensemble %s' % info, file=out)
        continue
      mean_delta = info[0] / info[1]
      mean_bond_delta.append(mean_delta)
    bond_delta_sq = mean_bond_delta * mean_bond_delta
    ensemble_bond_rmsd = math.sqrt(flex.mean_default(bond_delta_sq, 0))

    # Angle
    mean_angle_delta = flex.double()
    for proxy, info in six.iteritems(ensemble_angle_deltas):
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_angle_delta.append(mean_delta)
    angle_delta_sq = mean_angle_delta * mean_angle_delta
    ensemble_angle_rmsd = math.sqrt(flex.mean_default(angle_delta_sq, 0))

    # Chirality
    mean_chirality_delta = flex.double()
    for proxy, info in six.iteritems(ensemble_chirality_deltas):
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_chirality_delta.append(mean_delta)
    chirality_delta_sq = mean_chirality_delta * mean_chirality_delta
    ensemble_chirality_rmsd = math.sqrt(flex.mean_default(chirality_delta_sq, 0))

    # Planarity
    mean_planarity_delta = flex.double()
    for proxy, info in six.iteritems(ensemble_planarity_deltas):
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_planarity_delta.append(mean_delta)
    planarity_delta_sq = mean_planarity_delta * mean_planarity_delta
    ensemble_planarity_rmsd = math.sqrt(flex.mean_default(planarity_delta_sq, 0))

    # Dihedral
    mean_dihedral_delta = flex.double()
    for proxy, info in six.iteritems(ensemble_dihedral_deltas):
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_dihedral_delta.append(mean_delta)
    dihedral_delta_sq = mean_dihedral_delta * mean_dihedral_delta
    ensemble_dihedral_rmsd = math.sqrt(flex.mean_default(dihedral_delta_sq, 0))

    # Calculate <structure rmsd>
    assert ensemble_size == structures_bond_rmsd
    assert ensemble_size == structures_angle_rmsd
    assert ensemble_size == structures_chirality_rmsd
    assert ensemble_size == structures_planarity_rmsd
    assert ensemble_size == structures_dihedral_rmsd
    structure_bond_rmsd_mean = structures_bond_rmsd.min_max_mean().mean
    structure_angle_rmsd_mean = structures_angle_rmsd.min_max_mean().mean
    structure_chirality_rmsd_mean = structures_chirality_rmsd.min_max_mean().mean
    structure_planarity_rmsd_mean = structures_planarity_rmsd.min_max_mean().mean
    structure_dihedral_rmsd_mean = structures_dihedral_rmsd.min_max_mean().mean

    # Show summary
    utils.print_header("Ensemble RMSD summary", out = out)
    print("  RMSD (mean delta per restraint)", file=out)
    print("    bond      : %.6g" % ensemble_bond_rmsd, file=out)
    print("    angle     : %.6g" % ensemble_angle_rmsd, file=out)
    print("    chirality : %.6g" % ensemble_chirality_rmsd, file=out)
    print("    planarity : %.6g" % ensemble_planarity_rmsd, file=out)
    print("    dihedral  : %.6g" % ensemble_dihedral_rmsd, file=out)
    print("  RMSD (mean RMSD per structure)", file=out)
    print("    bond      : %.6g" % structure_bond_rmsd_mean, file=out)
    print("    angle     : %.6g" % structure_angle_rmsd_mean, file=out)
    print("    chirality : %.6g" % structure_chirality_rmsd_mean, file=out)
    print("    planarity : %.6g" % structure_planarity_rmsd_mean, file=out)
    print("    dihedral  : %.6g" % structure_dihedral_rmsd_mean, file=out)
    if ignore_hd:
      print("\n  Calculated excluding H/D", file=out)
    else:
      print("\n  Calculated including H/D", file=out)

    if return_pdb_string:
      ens_geo_pdb_string  = "REMARK   3"
      ens_geo_pdb_string += "\nREMARK   3  NUMBER STRUCTURES IN ENSEMBLE : {0:5d}".format(ensemble_size)
      if ignore_hd:
        ens_geo_pdb_string += "\nREMARK   3  RMS DEVIATIONS FROM IDEAL VALUES (EXCLUDING H/D)"
      else:
        ens_geo_pdb_string += "\nREMARK   3  RMS DEVIATIONS FROM IDEAL VALUES (INCLUDING H/D)"
      ens_geo_pdb_string += "\nREMARK   3  RMSD (MEAN DELTA PER RESTRAINT)"
      ens_geo_pdb_string += "\nREMARK   3    BOND      : {0:5.3f}".format(ensemble_bond_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    ANGLE     : {0:5.3f}".format(ensemble_angle_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    CHIRALITY : {0:5.3f}".format(ensemble_chirality_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    PLANARITY : {0:5.3f}".format(ensemble_planarity_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    DIHEDRAL  : {0:5.2f}".format(ensemble_dihedral_rmsd)
      ens_geo_pdb_string += "\nREMARK   3  RMSD (MEAN RMSD PER STRUCTURE)"
      ens_geo_pdb_string += "\nREMARK   3    BOND      : {0:5.3f}".format(structure_bond_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    ANGLE     : {0:5.3f}".format(structure_angle_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    CHIRALITY : {0:5.3f}".format(structure_chirality_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    PLANARITY : {0:5.3f}".format(structure_planarity_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    DIHEDRAL  : {0:5.2f}".format(structure_dihedral_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3"
      return ens_geo_pdb_string
 def _get_angle(sites_cart, angle_proxies, i_proxy):
     if i_proxy is not None:
         # compute angle
         angle = geometry_restraints.angle(sites_cart=sites_cart, proxy=angle_proxies[i_proxy])
         return angle
     return None
Example #21
0
  def ensemble_mean_geometry_stats(self,
                                   restraints_manager,
                                   xray_structure,
                                   ensemble_xray_structures,
                                   ignore_hd = True,
                                   verbose = False,
                                   out = None,
                                   return_pdb_string = False):
    if (out is None): out = sys.stdout
    if verbose:
      utils.print_header("Ensemble mean geometry statistics", out = out)
    ensemble_size = len(ensemble_xray_structures)
    print >> out, "Ensemble size : ", ensemble_size

    # Dictionaries to store deltas
    ensemble_bond_deltas = {}
    ensemble_angle_deltas = {}
    ensemble_chirality_deltas = {}
    ensemble_planarity_deltas = {}
    ensemble_dihedral_deltas = {}

    # List to store rmsd of each model
    structures_bond_rmsd = flex.double()
    structures_angle_rmsd = flex.double()
    structures_chirality_rmsd = flex.double()
    structures_planarity_rmsd = flex.double()
    structures_dihedral_rmsd = flex.double()

    # Remove water and hd atoms from global restraints manager
    selection = flex.bool()
    for sc in xray_structure.scatterers():
      if sc.label.find('HOH') > -1:
        selection.append(True)
      else:
        selection.append(False)
    if ignore_hd:
      hd_selection = xray_structure.hd_selection()
      assert hd_selection.size() == selection.size()
      for n in xrange(hd_selection.size()):
        if hd_selection[n] or selection[n]:
          selection[n] = True
    restraints_manager = restraints_manager.select(selection = ~selection)

    # Get all deltas
    for n, structure in enumerate(ensemble_xray_structures):
      if verbose:
        print >> out, "\nModel : ", n+1
      sites_cart = structure.sites_cart()
      # Remove water and hd atoms from individual structures sites cart
      selection = flex.bool()
      for sc in structure.scatterers():
        if sc.label.find('HOH') > -1:
          selection.append(True)
        else:
          selection.append(False)
      if ignore_hd:
        hd_selection = structure.hd_selection()
        assert hd_selection.size() == selection.size()
        for n in xrange(hd_selection.size()):
          if hd_selection[n] or selection[n]:
            selection[n] = True
      sites_cart = sites_cart.select(~selection)
      assert sites_cart is not None
      site_labels = None
      energies_sites = restraints_manager.energies_sites(
          sites_cart        = sites_cart,
          compute_gradients = False)

      # Rmsd of individual model
      bond_rmsd = energies_sites.geometry.bond_deviations()[2]
      angle_rmsd = energies_sites.geometry.angle_deviations()[2]
      chirality_rmsd = energies_sites.geometry.chirality_deviations()[2]
      planarity_rmsd = energies_sites.geometry.planarity_deviations()[2]
      dihedral_rmsd = energies_sites.geometry.dihedral_deviations()[2]

      structures_bond_rmsd.append(bond_rmsd)
      structures_angle_rmsd.append(angle_rmsd)
      structures_chirality_rmsd.append(chirality_rmsd)
      structures_planarity_rmsd.append(planarity_rmsd)
      structures_dihedral_rmsd.append(dihedral_rmsd)

      if verbose:
        print >> out, "  Model RMSD"
        print >> out, "    bond      : %.6g" % bond_rmsd
        print >> out, "    angle     : %.6g" % angle_rmsd
        print >> out, "    chirality : %.6g" % chirality_rmsd
        print >> out, "    planarity : %.6g" % planarity_rmsd
        print >> out, "    dihedral  : %.6g" % dihedral_rmsd

      # Bond
      pair_proxies = restraints_manager.geometry.pair_proxies(flags=None, sites_cart=sites_cart)
      assert pair_proxies is not None
      if verbose:
        pair_proxies.bond_proxies.show_histogram_of_deltas(
          sites_cart  = sites_cart,
          n_slots     = 10,
          f           = out)
      for proxy in pair_proxies.bond_proxies.simple:
        bond_simple_proxy = geometry_restraints.bond(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_bond_deltas:
          ensemble_bond_deltas[proxy.i_seqs][0]+=bond_simple_proxy.delta
          ensemble_bond_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_bond_deltas[proxy.i_seqs] = [bond_simple_proxy.delta, 1]
        if verbose:
          print >> out, "bond simple :", proxy.i_seqs
          print >> out, "  distance_ideal : %.6g" % proxy.distance_ideal
          print >> out, "  distance_model : %.6g" % bond_simple_proxy.distance_model
          print >> out, "  detla          : %.6g" % bond_simple_proxy.delta
      if (pair_proxies.bond_proxies.asu.size() > 0):
        asu_mappings = pair_proxies.bond_proxies.asu_mappings()
        for proxy in pair_proxies.bond_proxies.asu:
          rt_mx = asu_mappings.get_rt_mx_ji(pair=proxy)
          bond_asu_proxy = geometry_restraints.bond(
              sites_cart   = sites_cart,
              asu_mappings = asu_mappings,
              proxy        = proxy)
          proxy_i_seqs = (proxy.i_seq, proxy.j_seq)
          if proxy_i_seqs in ensemble_bond_deltas:
            ensemble_bond_deltas[proxy_i_seqs][0]+=bond_asu_proxy.delta
            ensemble_bond_deltas[proxy_i_seqs][1]+=1
          else:
            ensemble_bond_deltas[proxy_i_seqs] = [bond_asu_proxy.delta, 1]
          if verbose:
            print >> out, "bond asu :", (proxy.i_seq, proxy.j_seq), rt_mx
            print >> out, "  distance_ideal : %.6g" % proxy.distance_ideal
            print >> out, "  distance_model : %.6g" % bond_asu_proxy.distance_model
            print >> out, "  delta          : %.6g" % bond_asu_proxy.delta

      # Angle
      if verbose:
        restraints_manager.geometry.angle_proxies.show_histogram_of_deltas(
            sites_cart  = sites_cart,
            n_slots     = 10,
            f           = out)
      for proxy in restraints_manager.geometry.angle_proxies:
        angle_proxy = geometry_restraints.angle(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_angle_deltas:
          ensemble_angle_deltas[proxy.i_seqs][0]+=angle_proxy.delta
          ensemble_angle_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_angle_deltas[proxy.i_seqs] = [angle_proxy.delta, 1]
        if verbose:
          print >> out, "angle : ", proxy.i_seqs
          print >> out, "  angle_ideal   : %.6g" % proxy.angle_ideal
          print >> out, "  angle_model   : %.6g" % angle_proxy.angle_model
          print >> out, "  delta         : %.6g" % angle_proxy.delta

      # Chirality
      if verbose:
        restraints_manager.geometry.chirality_proxies.show_histogram_of_deltas(
            sites_cart  = sites_cart,
            n_slots     = 10,
            f           = out)
      for proxy in restraints_manager.geometry.chirality_proxies:
        chirality_proxy = geometry_restraints.chirality(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_chirality_deltas:
          ensemble_chirality_deltas[proxy.i_seqs][0]+=chirality_proxy.delta
          ensemble_chirality_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_chirality_deltas[proxy.i_seqs] = [chirality_proxy.delta, 1]
        if verbose:
          print >> out, "chirality : ", proxy.i_seqs
          print >> out, "  chirality_ideal : %.6g" % proxy.volume_ideal
          print >> out, "  chirality_model : %.6g" % chirality_proxy.volume_model
          print >> out, "  chirality       : %.6g" % chirality_proxy.delta

      # Planarity
      for proxy in restraints_manager.geometry.planarity_proxies:
        planarity_proxy = geometry_restraints.planarity(
            sites_cart = sites_cart,
            proxy      = proxy)
        proxy_i_seqs = []
        for i_seq in proxy.i_seqs:
          proxy_i_seqs.append(i_seq)
        proxy_i_seqs = tuple(proxy_i_seqs)
        if proxy_i_seqs in ensemble_planarity_deltas:
          ensemble_planarity_deltas[proxy_i_seqs][0]+=planarity_proxy.rms_deltas()
          ensemble_planarity_deltas[proxy_i_seqs][1]+=1
        else:
          ensemble_planarity_deltas[proxy_i_seqs] = [planarity_proxy.rms_deltas(), 1]
        if verbose:
          print >> out, "planarity : ", proxy_i_seqs
          print >> out, "  planarity rms_deltas : %.6g" % planarity_proxy.rms_deltas()

      # Dihedral
      if verbose:
        restraints_manager.geometry.dihedral_proxies.show_histogram_of_deltas(
            sites_cart  = sites_cart,
            n_slots     = 10,
            f           = out)
      for proxy in restraints_manager.geometry.dihedral_proxies:
        dihedral_proxy = geometry_restraints.dihedral(
            sites_cart = sites_cart,
            proxy      = proxy)
        if proxy.i_seqs in ensemble_dihedral_deltas:
          ensemble_dihedral_deltas[proxy.i_seqs][0]+=dihedral_proxy.delta
          ensemble_dihedral_deltas[proxy.i_seqs][1]+=1
        else:
          ensemble_dihedral_deltas[proxy.i_seqs] = [dihedral_proxy.delta, 1]
        if verbose:
          print >> out, "dihedral : ", proxy.i_seqs
          print >> out, "  dihedral_ideal  : %.6g" % proxy.angle_ideal
          print >> out, "  periodicity     : %.6g" % proxy.periodicity
          print >> out, "  dihedral_model  : %.6g" % dihedral_proxy.angle_model
          print >> out, "  delta           : %.6g" % dihedral_proxy.delta

    # Calculate RMSDs for ensemble model
    # Bond
    mean_bond_delta = flex.double()
    for proxy, info in ensemble_bond_deltas.iteritems():
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_bond_delta.append(mean_delta)
    bond_delta_sq = mean_bond_delta * mean_bond_delta
    ensemble_bond_rmsd = math.sqrt(flex.mean_default(bond_delta_sq, 0))

    # Angle
    mean_angle_delta = flex.double()
    for proxy, info in ensemble_angle_deltas.iteritems():
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_angle_delta.append(mean_delta)
    angle_delta_sq = mean_angle_delta * mean_angle_delta
    ensemble_angle_rmsd = math.sqrt(flex.mean_default(angle_delta_sq, 0))

    # Chirality
    mean_chirality_delta = flex.double()
    for proxy, info in ensemble_chirality_deltas.iteritems():
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_chirality_delta.append(mean_delta)
    chirality_delta_sq = mean_chirality_delta * mean_chirality_delta
    ensemble_chirality_rmsd = math.sqrt(flex.mean_default(chirality_delta_sq, 0))

    # Planarity
    mean_planarity_delta = flex.double()
    for proxy, info in ensemble_planarity_deltas.iteritems():
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_planarity_delta.append(mean_delta)
    planarity_delta_sq = mean_planarity_delta * mean_planarity_delta
    ensemble_planarity_rmsd = math.sqrt(flex.mean_default(planarity_delta_sq, 0))

    # Dihedral
    mean_dihedral_delta = flex.double()
    for proxy, info in ensemble_dihedral_deltas.iteritems():
      assert info[1] == ensemble_size
      mean_delta = info[0] / info[1]
      mean_dihedral_delta.append(mean_delta)
    dihedral_delta_sq = mean_dihedral_delta * mean_dihedral_delta
    ensemble_dihedral_rmsd = math.sqrt(flex.mean_default(dihedral_delta_sq, 0))

    # Calculate <structure rmsd>
    assert ensemble_size == structures_bond_rmsd
    assert ensemble_size == structures_angle_rmsd
    assert ensemble_size == structures_chirality_rmsd
    assert ensemble_size == structures_planarity_rmsd
    assert ensemble_size == structures_dihedral_rmsd
    structure_bond_rmsd_mean = structures_bond_rmsd.min_max_mean().mean
    structure_angle_rmsd_mean = structures_angle_rmsd.min_max_mean().mean
    structure_chirality_rmsd_mean = structures_chirality_rmsd.min_max_mean().mean
    structure_planarity_rmsd_mean = structures_planarity_rmsd.min_max_mean().mean
    structure_dihedral_rmsd_mean = structures_dihedral_rmsd.min_max_mean().mean

    # Show summary
    utils.print_header("Ensemble RMSD summary", out = out)
    print >> out, "  RMSD (mean delta per restraint)"
    print >> out, "    bond      : %.6g" % ensemble_bond_rmsd
    print >> out, "    angle     : %.6g" % ensemble_angle_rmsd
    print >> out, "    chirality : %.6g" % ensemble_chirality_rmsd
    print >> out, "    planarity : %.6g" % ensemble_planarity_rmsd
    print >> out, "    dihedral  : %.6g" % ensemble_dihedral_rmsd
    print >> out, "  RMSD (mean RMSD per structure)"
    print >> out, "    bond      : %.6g" % structure_bond_rmsd_mean
    print >> out, "    angle     : %.6g" % structure_angle_rmsd_mean
    print >> out, "    chirality : %.6g" % structure_chirality_rmsd_mean
    print >> out, "    planarity : %.6g" % structure_planarity_rmsd_mean
    print >> out, "    dihedral  : %.6g" % structure_dihedral_rmsd_mean
    if ignore_hd:
      print >> out, "\n  Calculated excluding H/D"
    else:
      print >> out, "\n  Calculated including H/D"

    if return_pdb_string:
      ens_geo_pdb_string  = "REMARK   3"
      ens_geo_pdb_string += "\nREMARK   3  NUMBER STRUCTURES IN ENSEMBLE : {0:5d}".format(ensemble_size)
      if ignore_hd:
        ens_geo_pdb_string += "\nREMARK   3  RMS DEVIATIONS FROM IDEAL VALUES (EXCLUDING H/D)"
      else:
        ens_geo_pdb_string += "\nREMARK   3  RMS DEVIATIONS FROM IDEAL VALUES (INCLUDING H/D)"
      ens_geo_pdb_string += "\nREMARK   3  RMSD (MEAN DELTA PER RESTRAINT)"
      ens_geo_pdb_string += "\nREMARK   3    BOND      : {0:5.3f}".format(ensemble_bond_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    ANGLE     : {0:5.3f}".format(ensemble_angle_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    CHIRALITY : {0:5.3f}".format(ensemble_chirality_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    PLANARITY : {0:5.3f}".format(ensemble_planarity_rmsd)
      ens_geo_pdb_string += "\nREMARK   3    DIHEDRAL  : {0:5.2f}".format(ensemble_dihedral_rmsd)
      ens_geo_pdb_string += "\nREMARK   3  RMSD (MEAN RMSD PER STRUCTURE)"
      ens_geo_pdb_string += "\nREMARK   3    BOND      : {0:5.3f}".format(structure_bond_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    ANGLE     : {0:5.3f}".format(structure_angle_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    CHIRALITY : {0:5.3f}".format(structure_chirality_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    PLANARITY : {0:5.3f}".format(structure_planarity_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3    DIHEDRAL  : {0:5.2f}".format(structure_dihedral_rmsd_mean)
      ens_geo_pdb_string += "\nREMARK   3"
      return ens_geo_pdb_string