Ejemplo n.º 1
0
  def __init__(self,
               pdb_hierarchy,
               chain_ID_light='L',
               chain_ID_heavy='H',
               limit_light=107,
               limit_heavy=113):
    '''
    Get elbow angle for Fragment antigen-binding (Fab)

    - Default heavy and light chains IDs are: H : heavy,  L : light
    - Default limit (cutoff) between variable and constant parts
      is residue number 107/113 for light/heavy chains
    - Variable domain is from residue 1 to limit.
      Constant domain form limit+1 to end.
    - Method of calculating angle is based on Stanfield, et al., JMB 2006
    '''
     # create selection strings for the heavy/light var/const part of chains
    self.select_str(
      chain_ID_H=chain_ID_heavy,
      limit_H=limit_heavy,
      chain_ID_L=chain_ID_light,
      limit_L=limit_light)
    # get the hirarchy for and divide using selection strings
    self.pdb_hierarchy = pdb_hierarchy
    self.get_pdb_chains()
    # Get heavy to light reference vector before alignment !!!
    vh_end = self.pdb_var_H.atoms()[-1].xyz
    vl_end = self.pdb_var_L.atoms()[-1].xyz
    mid_H_to_L = self.norm_vec(start=vh_end,end=vl_end)
    # Get transformations objects
    tranformation_const= self.get_transformation(
      fixed_selection=self.pdb_const_H,
      moving_selection=self.pdb_const_L)
    tranformation_var = self.get_transformation(
      fixed_selection=self.pdb_var_H,
      moving_selection=self.pdb_var_L)
    # Get the angle and eigenvalues
    eigen_const = eigensystem.real_symmetric(tranformation_const.r.as_sym_mat3())
    eigen_var = eigensystem.real_symmetric(tranformation_var.r.as_sym_mat3())
    # c : consttant, v : variable
    eigenvectors_c = self.get_eigenvector(eigen_const)
    eigenvectors_v = self.get_eigenvector(eigen_var)
    # test eignevectors pointing in oposite directions
    if eigenvectors_c.dot(eigenvectors_v) > 0:
      eigenvectors_v = - eigenvectors_v
    # Calc Feb elbow angle
    angle = self.get_angle(vec1=eigenvectors_c, vec2=eigenvectors_v)
    # Test if elbow angle larger or smaller than 180
    zaxis = self.cross(eigenvectors_v, eigenvectors_c)
    xaxis = self.cross(eigenvectors_c,zaxis)
    # choose ref axis
    ref_axis = zaxis
    #if abs(mid_H_to_L.dot(xaxis)) > abs(mid_H_to_L.dot(zaxis)):
      #ref_axis = xaxis
    if mid_H_to_L.dot(ref_axis) < 0:
      angle = 360 - angle
    self.fab_elbow_angle = angle
def compute_mode(mu, sigma):

    # Compute the eigen decomposition of the covariance matrix
    eigen_decomposition = eigensystem.real_symmetric(
        sigma.as_flex_double_matrix())
    Q = matrix.sqr(eigen_decomposition.vectors())
    L = matrix.diag(eigen_decomposition.values())

    # To simplify calculation of the mode, we change basis
    mu_prime = Q.transpose() * mu

    # Compute the initial value of the lagrange multiplier
    l0 = compute_l0(mu_prime.normalize(), mu_prime, L)

    # Compute the value via Halley's method
    while True:
        mu1, mu2, mu3 = mu_prime
        s1, s2, s3 = L[0], L[4], L[8]
        U = f(l0, mu1, mu2, mu3, s1, s2, s3)
        Up = df(l0, mu1, mu2, mu3, s1, s2, s3)
        Up2 = d2f(l0, mu1, mu2, mu3, s1, s2, s3)
        l = l0 - 2 * U * Up / (2 * Up**2 - U * Up2)
        if abs(l - l0) < 1e-7:
            break
        l0 = l

    # Compute the mode
    x = matrix.col((
        mu_prime[0] / (1 - l * L[0]),
        mu_prime[1] / (1 - l * L[4]),
        mu_prime[2] / (1 - l * L[8]),
    ))

    # Now transform back into the original basis
    return Q * x
Ejemplo n.º 3
0
def print_eigen_values_and_vectors(A):
    """
    Print the eigen values and vectors of a matrix

    """

    # Compute the eigen decomposition of the covariance matrix
    eigen_decomposition = eigensystem.real_symmetric(A.as_flex_double_matrix())
    Q = matrix.sqr(eigen_decomposition.vectors())
    L = matrix.diag(eigen_decomposition.values())

    # Print the matrix eigen values
    print("")
    print("Eigen Values:")
    print("")
    print_matrix(L, indent=2)
    print("")

    print("Eigen Vectors:")
    print("")
    print_matrix(Q, indent=2)
    print("")

    print("Mosaicity in degrees equivalent units")
    print("M1: %.5f degrees" % (sqrt(L[0]) * 180.0 / pi))
    print("M2: %.5f degrees" % (sqrt(L[4]) * 180.0 / pi))
    print("M3: %.5f degrees" % (sqrt(L[8]) * 180.0 / pi))
Ejemplo n.º 4
0
def kabsch_rotation(reference_sites, other_sites):
  """
Kabsch, W. (1976). Acta Cryst. A32, 922-923.
A solution for the best rotation to relate two sets of vectors

Based on a prototype by Erik McKee and Reetal K. Pai.

This implementation does not handle degenerate situations correctly
(e.g. if all atoms are on a line or plane) and should therefore not
be used in applications. It is retained here for development purposes
only.
  """
  assert reference_sites.size() == other_sites.size()
  sts = matrix.sqr(other_sites.transpose_multiply(reference_sites))
  eigs = eigensystem.real_symmetric((sts * sts.transpose()).as_sym_mat3())
  vals = list(eigs.values())
  vecs = list(eigs.vectors())
  a3 = list(matrix.col(vecs[:3]).cross(matrix.col(vecs[3:6])))
  a = matrix.sqr(list(vecs[:6])+a3)
  b = list(a * sts)
  for i in xrange(3):
    d = math.sqrt(math.fabs(vals[i]))
    if (d > 0):
      for j in xrange(3):
        b[i*3+j] /= d
  b3 = list(matrix.col(b[:3]).cross(matrix.col(b[3:6])))
  b = matrix.sqr(b[:6]+b3)
  return b.transpose() * a
Ejemplo n.º 5
0
    def eigen_system_default_handler(self, m, suffix):
        ###
        def zero(x, e):
            for i in xrange(len(x)):
                if (abs(x[i]) < e): x[i] = 0
            return x

        ###
        # special case
        m11, m12, m13, m21, m22, m23, m31, m32, m33 = m.as_flex_double_matrix()
        if (self.is_zero(m12) and self.is_zero(m13) and self.is_zero(m21)
                and self.is_zero(m23) and self.is_zero(m31)
                and self.is_zero(m32)):
            l_x = matrix.col((1.0, 0.0, 0.0))
            l_y = matrix.col((0.0, 1.0, 0.0))
            l_z = matrix.col((0.0, 0.0, 1.0))
            return group_args(x=l_x,
                              y=l_y,
                              z=l_z,
                              vals=zero([m11, m22, m33], self.eps))
        #
        es = eigensystem.real_symmetric(m.as_sym_mat3())
        vals, vecs = es.values(), es.vectors()
        print >> self.log, "  eigen values  (%s):" % suffix, " ".join(
            [self.ff % i for i in vals])
        print >> self.log, "  eigen vectors (%s):" % suffix, " ".join(
            [self.ff % i for i in vecs])
        assert vals[0] >= vals[1] >= vals[2]
        ###
        vals = zero(vals, self.eps)
        vecs = zero(vecs, self.eps)
        ###
        # case 1: all different
        if (abs(vals[0] - vals[1]) >= self.eps
                and abs(vals[1] - vals[2]) >= self.eps
                and abs(vals[0] - vals[2]) >= self.eps):
            l_z = matrix.col((vecs[0], vecs[1], vecs[2]))
            l_y = matrix.col((vecs[3], vecs[4], vecs[5]))
            l_x = l_y.cross(l_z)
            vals = [vals[2], vals[1], vals[0]]
        # case 2: all three coincide
        elif ((abs(vals[0] - vals[1]) < self.eps
               and abs(vals[1] - vals[2]) < self.eps
               and abs(vals[0] - vals[2]) < self.eps)):
            print >> self.log, "  three eigenvalues are equal: make eigenvectors unit."
            l_x = matrix.col((1, 0, 0))
            l_y = matrix.col((0, 1, 0))
            l_z = matrix.col((0, 0, 1))
        elif ([
                abs(vals[0] - vals[1]) < self.eps,
                abs(vals[1] - vals[2]) < self.eps,
                abs(vals[0] - vals[2]) < self.eps
        ].count(True) == 1):
            print >> self.log, "  two eigenvalues are equal."
            #
            l_z = matrix.col((vecs[0], vecs[1], vecs[2]))
            l_y = matrix.col((vecs[3], vecs[4], vecs[5]))
            l_x = l_y.cross(l_z)
            vals = [vals[2], vals[1], vals[0]]
        return group_args(x=l_x, y=l_y, z=l_z, vals=vals)
Ejemplo n.º 6
0
def compare_times(max_n_power=8):
    from scitbx.linalg import lapack_dsyev
    mt = flex.mersenne_twister(seed=0)
    show_tab_header = True
    tfmt = "%5.2f"
    for n_power in xrange(5, max_n_power + 1):
        n = 2**n_power
        l = mt.random_double(size=n * (n + 1) // 2) * 2 - 1
        a = l.matrix_packed_l_as_symmetric()
        aes = a.deep_copy()
        ala = [a.deep_copy(), a.deep_copy()]
        wla = [flex.double(n, -1e100), flex.double(n, -1e100)]
        t0 = time.time()
        es = eigensystem.real_symmetric(aes)
        tab = [n, tfmt % (time.time() - t0)]
        for i, use_fortran in enumerate([False, True]):
            t0 = time.time()
            info = lapack_dsyev(jobz="V",
                                uplo="U",
                                a=ala[i],
                                w=wla[i],
                                use_fortran=use_fortran)
            if (info == 99):
                tab.append(" --- ")
            else:
                assert info == 0
                tab.append(tfmt % (time.time() - t0))
                assert approx_equal(list(reversed(es.values())), wla[i])
        if (show_tab_header):
            print "      time [s]           eigenvalues"
            print " n    es   fem   for     min    max"
            show_tab_header = False
        tab.extend([es.values()[-1], es.values()[0]])
        print "%3d %s %s %s [%6.2f %6.2f]" % tuple(tab)
Ejemplo n.º 7
0
 def callback_after_step(O, minimizer):
   xk = O.prev_x
   xl = O.x
   gk = O.fgh.g(xk)
   gl = O.fgh.g(xl)
   def check(bk, hk):
     hl = bfgs.h_update(hk, xl-xk, gl-gk)
     bl = bfgs.b_update(bk, xl-xk, gl-gk)
     assert approx_equal(matrix.sqr(hl).inverse(), bl)
     es = eigensystem.real_symmetric(bl)
     assert es.values().all_gt(0)
     assert bfgs.h0_scaling(sk=xl-xk, yk=gl-gk) > 0
   #
   bk = flex.double([[1,0],[0,1]])
   hk = bk
   check(bk, hk)
   #
   bk = O.fgh.h(xk)
   es = eigensystem.real_symmetric(bk)
   if (es.values().all_gt(0)):
     hk = bk.deep_copy()
     hk.matrix_inversion_in_place()
     check(bk, hk)
   #
   h0 = flex.double([[0.9,0.1],[-0.2,0.8]])
   hg_tlr = bfgs.hg_two_loop_recursion(memory=O.memory, hk0=h0, gk=gl)
   h_upd = h0
   for m in O.memory:
     h_upd = bfgs.h_update(hk=h_upd, sk=m.s, yk=m.y)
   hg_upd = h_upd.matrix_multiply(gl)
   assert approx_equal(hg_tlr, hg_upd)
   #
   O.memory.append(bfgs.memory_element(s=xl-xk, y=gl-gk))
   O.prev_x = O.x.deep_copy()
Ejemplo n.º 8
0
 def check(bk, hk):
   hl = bfgs.h_update(hk, xl-xk, gl-gk)
   bl = bfgs.b_update(bk, xl-xk, gl-gk)
   assert approx_equal(matrix.sqr(hl).inverse(), bl)
   es = eigensystem.real_symmetric(bl)
   assert es.values().all_gt(0)
   assert bfgs.h0_scaling(sk=xl-xk, yk=gl-gk) > 0
Ejemplo n.º 9
0
def get_rotation_vec(r):
  """ get the eigen vector associated with the eigen value 1"""
  eigen = eigensystem.real_symmetric(r.as_sym_mat3())
  eigenvectors = eigen.vectors()
  eigenvalues = eigen.values()
  i = list(eigenvalues.round(4)).index(1)
  return eigenvectors[i:(i+3)]
Ejemplo n.º 10
0
def compare_times(max_n_power=8):
  from scitbx.linalg import lapack_dsyev
  mt = flex.mersenne_twister(seed=0)
  show_tab_header = True
  tfmt = "%5.2f"
  for n_power in xrange(5,max_n_power+1):
    n = 2**n_power
    l = mt.random_double(size=n*(n+1)//2) * 2 - 1
    a = l.matrix_packed_l_as_symmetric()
    aes = a.deep_copy()
    ala = [a.deep_copy(), a.deep_copy()]
    wla = [flex.double(n, -1e100), flex.double(n, -1e100)]
    t0 = time.time()
    es = eigensystem.real_symmetric(aes)
    tab = [n, tfmt % (time.time() - t0)]
    for i,use_fortran in enumerate([False, True]):
      t0 = time.time()
      info = lapack_dsyev(
        jobz="V", uplo="U", a=ala[i], w=wla[i], use_fortran=use_fortran)
      if (info == 99):
        tab.append(" --- ")
      else:
        assert info == 0
        tab.append(tfmt % (time.time() - t0))
        assert approx_equal(list(reversed(es.values())), wla[i])
    if (show_tab_header):
      print "      time [s]           eigenvalues"
      print " n    es   fem   for     min    max"
      show_tab_header = False
    tab.extend([es.values()[-1], es.values()[0]])
    print "%3d %s %s %s [%6.2f %6.2f]" % tuple(tab)
Ejemplo n.º 11
0
def RealSymmetricPseudoInverse(A_, filtered, min_to_filter=0):
    """Compute the pseudo-inverse of a real symmetric matrix

  filters (i.e. makes 0) small and negative eigen values before
  calculating the pseudo-inverse.
  """

    A = A_.deep_copy(
    )  # make a copy to avoid changing the original when scaling

    #A is a flex array, size N by N
    (M, N) = A.all()
    assert (M == N)
    A_scale = []
    for i in range(N):
        assert (A[i, i] > 0)
        A_scale.append(A[i, i]**-0.5)
    for i in range(N):
        for j in range(N):
            A[i, j] = A_scale[i] * A_scale[j] * A[i, j]

    # Call the scitbx routine to find eigenvalues and eigenvectors
    eigen = eigensystem.real_symmetric(A)

    # Set condition number for range of eigenvalues.
    evCondition = min(1.e9, 0.01 / float_info.epsilon)
    evMax = eigen.values()[0]  # (Eigen values are stored in descending order.)
    evMin = evMax / evCondition
    ZERO = 0.
    lambdaInv = flex.double(N * N, ZERO)
    lambdaInv.reshape(flex.grid(N, N))  # Matrix of zeros

    filtered = 0
    for i in range(N - 1, -1, -1):
        if (eigen.values()[i] < evMin) or (filtered < min_to_filter):
            lambdaInv[i, i] = ZERO
            filtered += 1
        else:
            lambdaInv[i, i] = 1.0 / eigen.values()[i]

    # Compute the result that we are after - the pseudo inverse
    # The formula from wikipedia is (A^-1) = (Q)(lam^-1)(Q^T)
    # where Q has eigen vectors as columns
    # eigen.vectors() has eigenvectors as rows
    # let V be eigen.vectors(). The formula is now: (A^-1) = (V^T)(lam^-1)(V)

    # get a transposed matrix
    vectors_transposed = eigen.vectors().deep_copy()
    vectors_transposed.matrix_transpose_in_place()
    inverse_matrix = vectors_transposed.matrix_multiply(
        lambdaInv.matrix_multiply(eigen.vectors()))

    # Rescale the matrix
    for i in range(N):
        for j in range(N):
            inverse_matrix[i,
                           j] = A_scale[i] * A_scale[j] * inverse_matrix[i, j]

    return (inverse_matrix, filtered)
Ejemplo n.º 12
0
 def eigen_system_default_handler(self, m, suffix):
   ###
   def zero(x, e):
     for i in xrange(len(x)):
       if(abs(x[i])<e): x[i]=0
     return x
   ###
   # special case
   m11,m12,m13, m21,m22,m23, m31,m32,m33 = m.as_flex_double_matrix()
   if(self.is_zero(m12) and self.is_zero(m13) and
      self.is_zero(m21) and self.is_zero(m23) and
      self.is_zero(m31) and self.is_zero(m32)):
     l_x = matrix.col((1.0, 0.0, 0.0))
     l_y = matrix.col((0.0, 1.0, 0.0))
     l_z = matrix.col((0.0, 0.0, 1.0))
     return group_args(x=l_x, y=l_y, z=l_z, vals=zero([m11,m22,m33], self.eps))
   #
   es = eigensystem.real_symmetric(m.as_sym_mat3())
   vals, vecs = es.values(), es.vectors()
   print >> self.log, "  eigen values  (%s):"%suffix, " ".join([self.ff%i for i in vals])
   print >> self.log, "  eigen vectors (%s):"%suffix, " ".join([self.ff%i for i in vecs])
   assert vals[0]>=vals[1]>=vals[2]
   ###
   vals = zero(vals, self.eps)
   vecs = zero(vecs, self.eps)
   ###
   # case 1: all different
   if(abs(vals[0]-vals[1])>=self.eps and
      abs(vals[1]-vals[2])>=self.eps and
      abs(vals[0]-vals[2])>=self.eps):
     l_z = matrix.col((vecs[0], vecs[1], vecs[2]))
     l_y = matrix.col((vecs[3], vecs[4], vecs[5]))
     l_x = l_y.cross(l_z)
     vals = [vals[2], vals[1], vals[0]]
   # case 2: all three coincide
   elif((abs(vals[0]-vals[1])<self.eps and
        abs(vals[1]-vals[2])<self.eps and
        abs(vals[0]-vals[2])<self.eps)):
     print >> self.log, "  three eigenvalues are equal: make eigenvectors unit."
     l_x = matrix.col((1, 0, 0))
     l_y = matrix.col((0, 1, 0))
     l_z = matrix.col((0, 0, 1))
   elif([abs(vals[0]-vals[1])<self.eps,
         abs(vals[1]-vals[2])<self.eps,
         abs(vals[0]-vals[2])<self.eps].count(True)==1):
     print >> self.log, "  two eigenvalues are equal."
     #
     l_z = matrix.col((vecs[0], vecs[1], vecs[2]))
     l_y = matrix.col((vecs[3], vecs[4], vecs[5]))
     l_x = l_y.cross(l_z)
     vals = [vals[2], vals[1], vals[0]]
   return group_args(x=l_x, y=l_y, z=l_z, vals=vals)
Ejemplo n.º 13
0
    def update_model(self, state):
        """
        Update the model

        """

        # Compute the eigen decomposition of the covariance matrix and check
        # largest eigen value
        eigen_decomposition = eigensystem.real_symmetric(
            state.get_M().as_flex_double_matrix()
        )
        L = eigen_decomposition.values()
        if L[0] > 1e-5:
            raise RuntimeError("Mosaicity matrix is unphysically large")

        self.params = state.get_M_params()
Ejemplo n.º 14
0
    def __init__(self, experiment, reflections):
        from dials.algorithms.refinement.parameterisation.crystal_parameters import (
            CrystalUnitCellParameterisation, )
        from dials.algorithms.refinement.parameterisation.crystal_parameters import (
            CrystalOrientationParameterisation, )
        from dials_scratch.jmp.stills import Model
        from dials.array_family import flex
        from scitbx import simplex
        from math import sqrt

        # Store the input
        self.experiment = experiment
        self.reflections = reflections

        self.crystal = self.experiment.crystal

        # Get the current values and generate some offsets
        values = flex.double((0.001, 0, 0.001, 0, 0, 0.001))
        offset = flex.double([0.001 for v in values])

        # The optimization history
        self.history = []

        # Get the initial cell and initial score
        M = matrix.sqr((values[0], 0, 0, values[1], values[2], 0, values[3],
                        values[4], values[5]))
        initial_sigma = M * M.transpose()
        initial_score = self.target(values)

        self.sigma = initial_sigma

        # Perform the optimization
        optimizer = simple_simplex(values, offset, self, 2000)
        result = optimizer.get_solution()
        M = matrix.sqr((result[0], 0, 0, result[1], result[2], 0, result[3],
                        result[4], result[5]))
        self.sigma = M * M.transpose()
        print("Initial sigma:", initial_sigma)
        print("Final sigma:  ", self.sigma)

        # Compute the eigen decomposition of the covariance matrix
        eigen_decomposition = eigensystem.real_symmetric(
            self.sigma.as_flex_double_matrix())
        Q = matrix.sqr(eigen_decomposition.vectors())
        L = matrix.diag(eigen_decomposition.values())
        print(Q)
        print(L)
Ejemplo n.º 15
0
 def add_const(u):
     es = eigensystem.real_symmetric(u)
     vecs = es.vectors()
     l_z = matrix.col((vecs[0], vecs[1], vecs[2]))
     l_y = matrix.col((vecs[3], vecs[4], vecs[5]))
     l_x = matrix.col((vecs[6], vecs[7], vecs[8]))
     #l_x = l_y.cross(l_z)
     u = matrix.sym(sym_mat3=u)
     R = matrix.sqr([
         l_x[0], l_y[0], l_z[0], l_x[1], l_y[1], l_z[1], l_x[2], l_y[2],
         l_z[2]
     ])
     uD = R.transpose() * u * R
     result = R * (uD + eps) * R.transpose()
     tmp = R * uD * R.transpose()
     for i in xrange(6):
         assert approx_equal(tmp[i], u[i])
     return R * (uD + eps) * R.transpose()
    def draw_rlp():

        # Compute the eigen decomposition of the covariance matrix
        eigen_decomposition = eigensystem.real_symmetric(
            sigma.as_flex_double_matrix())
        Q = matrix.sqr(eigen_decomposition.vectors())
        L = eigen_decomposition.values()
        radii = 3 * L

        # now carry on with EOL's answer
        u = np.linspace(0.0, 2.0 * np.pi, 100)
        v = np.linspace(0.0, np.pi, 100)
        x = radii[0] * np.outer(np.cos(u), np.sin(v))
        y = radii[1] * np.outer(np.sin(u), np.sin(v))
        z = radii[2] * np.outer(np.ones_like(u), np.cos(v))
        for i in range(len(x)):
            for j in range(len(x)):
                [x[i, j], y[i, j], z[i, j]] = (
                    np.dot([x[i, j], y[i, j], z[i, j]], Q.as_list_of_lists()) +
                    mu)

        # plot
        ax.plot_wireframe(x, y, z, rstride=4, cstride=4, color="b", alpha=0.2)
Ejemplo n.º 17
0
# Description:  The commands to find the eigenvalues and eigenvectors on a tensor. The code is from a post to cctbxbb on 10 December 2020 by Richard Gildea in a reply to Robert Oeffner about code in cctbx for finding eigenvalues and eigenvectors. Robert was requesting the analog in cctbx to scipy.linalg.eig.
# Source:  NA

"""
from scitbx.array_family import flex;
from scitbx.linalg import eigensystem;
m = flex.double(($1:-2, -4, 2, -2, 1, 2, 4, 2, 5}));
m.reshape(flex.grid(3,3));
es = eigensystem.real_symmetric(m);
list(es.values());
list(es.vectors());
"""

from scitbx.array_family import flex;
from scitbx.linalg import eigensystem;
m = flex.double(($1:-2, -4, 2, -2, 1, 2, 4, 2, 5));
m.reshape(flex.grid(3,3));
es = eigensystem.real_symmetric(m);
list(es.values());
list(es.vectors());
Ejemplo n.º 18
0
 def is_pd(self, m):
   es = eigensystem.real_symmetric(deepcopy(m))
   r = flex.min(es.values())
   if(r > 0 or self.is_zero(r)): return True
   else:                         return False
Ejemplo n.º 19
0
 def step_C(self):
   """
   Determination of screw components.
   """
   print_step("Step C:", self.log)
   T_ = self.T_CL.as_sym_mat3()
   self.T_CLxx, self.T_CLyy, self.T_CLzz = T_[0], T_[1], T_[2]
   #
   # Left branch
   #
   if(not (self.is_zero(self.Lxx) or
           self.is_zero(self.Lyy) or
           self.is_zero(self.Lzz))):
     tlxx = self.T_CLxx*self.Lxx
     tlyy = self.T_CLyy*self.Lyy
     tlzz = self.T_CLzz*self.Lzz
     t11, t22, t33 = tlxx, tlyy, tlzz # the rest is below
     rx, ry, rz = math.sqrt(tlxx), math.sqrt(tlyy), math.sqrt(tlzz)
     t12 = self.T_CL[1] * math.sqrt(self.Lxx*self.Lyy)
     t13 = self.T_CL[2] * math.sqrt(self.Lxx*self.Lzz)
     t23 = self.T_CL[5] * math.sqrt(self.Lyy*self.Lzz)
     t_min_C = max(self.Sxx-rx, self.Syy-ry, self.Szz-rz)
     t_max_C = min(self.Sxx+rx, self.Syy+ry, self.Szz+rz)
     self.show_number(x=[t_min_C, t_max_C], title="t_min_C,t_max_C eq.(24):")
     if(t_min_C > t_max_C):
       raise Sorry("Step C (left branch): Empty (tmin_c,tmax_c) interval.")
     t_0 = self.S_L.trace()/3.
     self.show_number(x=t_0, title="t_0 eq.(20):")
     # compose T_lambda and find tau_max (30)
     T_lambda = matrix.sqr(
       [t11, t12, t13,
        t12, t22, t23,
        t13, t23, t33])
     self.show_matrix(x=T_lambda, title="T_lambda eq.(29)")
     es = eigensystem.real_symmetric(T_lambda.as_sym_mat3())
     vals = es.values()
     assert vals[0]>=vals[1]>=vals[2]
     tau_max = vals[0]
     #
     if(tau_max < 0):
       raise Sorry("Step C (left branch): Eq.(32): tau_max<0.")
     t_min_tau = max(self.Sxx,self.Syy,self.Szz)-math.sqrt(tau_max)
     t_max_tau = min(self.Sxx,self.Syy,self.Szz)+math.sqrt(tau_max)
     self.show_number(x=[t_min_tau, t_max_tau],
       title="t_min_tau, t_max_tau eq.(31):")
     if(t_min_tau > t_max_tau):
       raise Sorry("Step C (left branch): Empty (tmin_t,tmax_t) interval.")
     # (38):
     arg = t_0**2 + (t11+t22+t33)/3. - (self.Sxx**2+self.Syy**2+self.Szz**2)/3.
     if(arg < 0):
       raise Sorry("Step C (left branch): Negative argument when estimating tmin_a.")
     t_a = math.sqrt(arg)
     self.show_number(x=t_a, title="t_a eq.(38):")
     t_min_a = t_0-t_a
     t_max_a = t_0+t_a
     self.show_number(x=[t_min_a, t_max_a], title="t_min_a, t_max_a eq.(37):")
     # compute t_min, t_max - this is step b)
     t_min = max(t_min_C, t_min_tau, t_min_a)
     t_max = min(t_max_C, t_max_tau, t_max_a)
     if(t_min > t_max):
       raise Sorry("Step C (left branch): Intersection of the intervals for t_S is empty.")
     elif(self.is_zero(t_min-t_max)):
       _, b_s, c_s = self.as_bs_cs(t=t_min, txx=t11,tyy=t22,tzz=t33,
         txy=t12,tyz=t23,tzx=t13)
       if( (self.is_zero(b_s) or bs>0) and (c_s<0 or self.is_zero(c_s))):
         self.t_S = t_min
       else:
         raise Sorry("Step C (left branch): t_min=t_max gives non positive semidefinite V_lambda.")
     elif(t_min < t_max):
       step = (t_max-t_min)/100000.
       target = 1.e+9
       t_S_best = t_min
       while t_S_best <= t_max:
         _, b_s, c_s = self.as_bs_cs(t=t_S_best, txx=t11,tyy=t22,tzz=t33,
           txy=t12,tyz=t23,tzx=t13)
         if(b_s >= 0 and c_s <= 0):
           target_ = abs(t_0-t_S_best)
           if(target_ < target):
             target = target_
             self.t_S = t_S_best
         t_S_best += step
       assert self.t_S <= t_max
       if(self.t_S is None):
         raise Sorry("Step C (left branch): Interval (t_min,t_max) has no t giving positive semidefinite V.")
       self.t_S = self.t_S
   #
   # Right branch, Section 4.4
   #
   else:
     Lxx, Lyy, Lzz = self.Lxx, self.Lyy, self.Lzz
     if(self.is_zero(self.Lxx)): Lxx = 0
     if(self.is_zero(self.Lyy)): Lyy = 0
     if(self.is_zero(self.Lzz)): Lzz = 0
     tlxx = self.T_CLxx*Lxx
     tlyy = self.T_CLyy*Lyy
     tlzz = self.T_CLzz*Lzz
     t11, t22, t33 = tlxx, tlyy, tlzz # the rest is below
     rx, ry, rz = math.sqrt(tlxx), math.sqrt(tlyy), math.sqrt(tlzz)
     t12 = self.T_CL[1] * math.sqrt(Lxx*Lyy)
     t13 = self.T_CL[2] * math.sqrt(Lxx*Lzz)
     t23 = self.T_CL[5] * math.sqrt(Lyy*Lzz)
     # helper-function to check Cauchy conditions
     def cauchy_conditions(i,j,k, tSs): # diagonals: 0,4,8; 4,0,8; 8,0,4
       if(self.is_zero(self.L_L[i])):
         t_S = self.S_L[i]
         cp1 = (self.S_L[j] - t_S)**2 - self.T_CL[j]*self.L_L[j]
         cp2 = (self.S_L[k] - t_S)**2 - self.T_CL[k]*self.L_L[k]
         if( not ((cp1 < 0 or self.is_zero(cp1)) and
                  (cp2 < 0 or self.is_zero(cp2))) ):
           raise Sorry("Step C (right branch): Cauchy condition failed (23).")
         a_s, b_s, c_s = self.as_bs_cs(t=t_S, txx=t11,tyy=t22,tzz=t33,
           txy=t12,tyz=t23,tzx=t13)
         self.check_33_34_35(a_s=a_s, b_s=b_s, c_s=c_s)
         tSs.append(t_S)
     #
     tSs = []
     cauchy_conditions(i=0,j=4,k=8, tSs=tSs)
     cauchy_conditions(i=4,j=0,k=8, tSs=tSs)
     cauchy_conditions(i=8,j=0,k=4, tSs=tSs)
     if(len(tSs)==1): self.t_S = tSs[0]
     elif(len(tSs)==0): raise RuntimeError
     else:
       self.t_S = tSs[0]
       for tSs_ in tSs[1:]:
         if(not self.is_zero(x = self.t_S-tSs_)):
           assert 0
   # end-of-procedure check, then truncate
   if(self.t_S is None):
     raise RuntimeError
   # override with provided value
   if(self.force_t_S is not None):
     self.t_S = self.force_t_S
   #
   # At this point t_S is found or procedure terminated earlier.
   #
   self.show_number(x=self.t_S, title="t_S:")
   # compute S_C(t_S_), (19)
   self.S_C = self.S_L - matrix.sqr(
     [self.t_S,        0,        0,
             0, self.t_S,        0,
             0,        0, self.t_S])
   self.S_C = matrix.sqr(self.S_C)
   self.show_matrix(x=self.S_C, title="S_C, (26)")
   # find sx, sy, sz
   if(self.is_zero(self.Lxx)):
     if(not self.is_zero(self.S_C[0])):
       raise Sorry("Step C: incompatible L_L and S_C matrices.")
   else:
     self.sx = self.S_C[0]/self.Lxx
   if(self.is_zero(self.Lyy)):
     if(not self.is_zero(self.S_C[4])):
       raise Sorry("Step C: incompatible L_L and S_C matrices.")
   else:
     self.sy = self.S_C[4]/self.Lyy
   if(self.is_zero(self.Lzz)):
     if(not self.is_zero(self.S_C[8])):
       raise Sorry("Step C: incompatible L_L and S_C matrices.")
   else:
     self.sz = self.S_C[8]/self.Lzz
   self.show_number(x=[self.sx,self.sy,self.sz],
     title="Screw parameters (section 4.5): sx,sy,sz:")
   # compose C_L_t_S (26), and V_L (27)
   self.C_L_t_S = matrix.sqr(
     [self.sx*self.S_C[0],                   0,                   0,
                        0, self.sy*self.S_C[4],                   0,
                        0,                   0, self.sz*self.S_C[8]])
   self.C_L_t_S = self.C_L_t_S
   self.show_matrix(x=self.C_L_t_S, title="C_L(t_S) (26)")
   self.V_L = matrix.sqr(self.T_CL - self.C_L_t_S)
   self.show_matrix(x=self.V_L, title="V_L (26-27)")
   if(not self.is_pd(self.V_L.as_sym_mat3())):
     raise Sorry("Step C: Matrix V[L] is not positive semidefinite.")
def exercise_floating_origin_dynamic_weighting(verbose=False):
  from cctbx import covariance
  import scitbx.math

  worst_condition_number_acceptable = 10

  # light elements only
  xs0 = random_structure.xray_structure(elements=['C', 'C', 'C', 'O', 'N'],
                                        use_u_aniso=True)
  msg = "light elements in %s ..." % (
    xs0.space_group_info().type().hall_symbol())
  if verbose:
    print(msg, end=' ')
  fo_sq = xs0.structure_factors(d_min=0.8).f_calc().norm()
  fo_sq = fo_sq.customized_copy(sigmas=flex.double(fo_sq.size(), 1.))
  xs = xs0.deep_copy_scatterers()
  xs.shake_adp()
  xs.shake_sites_in_place(rms_difference=0.1)
  for sc in xs.scatterers():
    sc.flags.set_grad_site(True).set_grad_u_aniso(True)
  ls = least_squares.crystallographic_ls(
    fo_sq.as_xray_observations(),
    constraints.reparametrisation(
      structure=xs,
      constraints=[],
      connectivity_table=smtbx.utils.connectivity_table(xs)),
    weighting_scheme=least_squares.unit_weighting(),
    origin_fixing_restraints_type=
    origin_fixing_restraints.atomic_number_weighting)
  ls.build_up()
  lambdas = eigensystem.real_symmetric(
    ls.normal_matrix_packed_u().matrix_packed_u_as_symmetric()).values()
  # assert the restrained L.S. problem is not too ill-conditionned
  cond = math.log10(lambdas[0]/lambdas[-1])
  if verbose:
    print("normal matrix condition: %.1f" % cond)
  assert cond < worst_condition_number_acceptable, msg

  # one heavy element
  xs0 = random_structure.xray_structure(
    space_group_info=sgtbx.space_group_info('hall: P 2yb'),
    elements=['Zn', 'C', 'C', 'C', 'O', 'N'],
    use_u_aniso=True)
  msg = "one heavy element + light elements (synthetic data) in %s ..." % (
    xs0.space_group_info().type().hall_symbol())
  if verbose:
    print(msg, end=' ')
  fo_sq = xs0.structure_factors(d_min=0.8).f_calc().norm()
  fo_sq = fo_sq.customized_copy(sigmas=flex.double(fo_sq.size(), 1.))
  xs = xs0.deep_copy_scatterers()
  xs.shake_adp()
  xs.shake_sites_in_place(rms_difference=0.1)
  for sc in xs.scatterers():
    sc.flags.set_grad_site(True).set_grad_u_aniso(True)
  ls = least_squares.crystallographic_ls(
    fo_sq.as_xray_observations(),
    constraints.reparametrisation(
      structure=xs,
      constraints=[],
      connectivity_table=smtbx.utils.connectivity_table(xs)),
    weighting_scheme=least_squares.mainstream_shelx_weighting(),
    origin_fixing_restraints_type=
    origin_fixing_restraints.atomic_number_weighting)
  ls.build_up()
  lambdas = eigensystem.real_symmetric(
    ls.normal_matrix_packed_u().matrix_packed_u_as_symmetric()).values()
  # assert the restrained L.S. problem is not too ill-conditionned
  cond = math.log10(lambdas[0]/lambdas[-1])
  if verbose:
    print("normal matrix condition: %.1f" % cond)
  assert cond < worst_condition_number_acceptable, msg

  # are esd's for x,y,z coordinates of the same order of magnitude?
  var_cart = covariance.orthogonalize_covariance_matrix(
    ls.covariance_matrix(),
    xs.unit_cell(),
    xs.parameter_map())
  var_site_cart = covariance.extract_covariance_matrix_for_sites(
      flex.size_t_range(len(xs.scatterers())),
      var_cart,
      xs.parameter_map())
  site_esds = var_site_cart.matrix_packed_u_diagonal()
  indicators = flex.double()
  for i in xrange(0, len(site_esds), 3):
    stats = scitbx.math.basic_statistics(site_esds[i:i+3])
    indicators.append(stats.bias_corrected_standard_deviation/stats.mean)
  assert indicators.all_lt(2)

  # especially troublesome structure with one heavy element
  # (contributed by Jonathan Coome)
  xs0 = xray.structure(
    crystal_symmetry=crystal.symmetry(
      unit_cell=(8.4519, 8.4632, 18.7887, 90, 96.921, 90),
      space_group_symbol="hall: P 2yb"),
    scatterers=flex.xray_scatterer([
      xray.scatterer( #0
                      label="ZN1",
                      site=(-0.736683, -0.313978, -0.246902),
                      u=(0.000302, 0.000323, 0.000054,
                         0.000011, 0.000015, -0.000004)),
      xray.scatterer( #1
                      label="N3B",
                      site=(-0.721014, -0.313583, -0.134277),
                      u=(0.000268, 0.000237, 0.000055,
                         -0.000027, 0.000005, 0.000006)),
      xray.scatterer( #2
                      label="N3A",
                      site=(-0.733619, -0.290423, -0.357921),
                      u=(0.000229, 0.000313, 0.000053,
                         0.000022, 0.000018, -0.000018)),
      xray.scatterer( #3
                      label="C9B",
                      site=(-1.101537, -0.120157, -0.138063),
                      u=(0.000315, 0.000345, 0.000103,
                         0.000050, 0.000055, -0.000017)),
    xray.scatterer( #4
                    label="N5B",
                    site=(-0.962032, -0.220345, -0.222045),
                    u=(0.000274, 0.000392, 0.000060,
                       -0.000011, -0.000001, -0.000002)),
    xray.scatterer( #5
                    label="N1B",
                    site=(-0.498153, -0.402742, -0.208698),
                    u=(0.000252, 0.000306, 0.000063,
                       0.000000, 0.000007, 0.000018)),
    xray.scatterer( #6
                    label="C3B",
                    site=(-0.322492, -0.472610, -0.114594),
                    u=(0.000302, 0.000331, 0.000085,
                       0.000016, -0.000013, 0.000037)),
    xray.scatterer( #7
                    label="C4B",
                    site=(-0.591851, -0.368163, -0.094677),
                    u=(0.000262, 0.000255, 0.000073,
                       -0.000034, 0.000027, -0.000004)),
    xray.scatterer( #8
                    label="N4B",
                    site=(-0.969383, -0.204624, -0.150014),
                    u=(0.000279, 0.000259, 0.000070,
                       -0.000009, 0.000039, 0.000000)),
    xray.scatterer( #9
                    label="N2B",
                    site=(-0.470538, -0.414572, -0.135526),
                    u=(0.000277, 0.000282, 0.000065,
                       0.000003, 0.000021, -0.000006)),
    xray.scatterer( #10
                    label="C8A",
                    site=(-0.679889, -0.158646, -0.385629),
                    u=(0.000209, 0.000290, 0.000078,
                       0.000060, 0.000006, 0.000016)),
    xray.scatterer( #11
                    label="N5A",
                    site=(-0.649210, -0.075518, -0.263412),
                    u=(0.000307, 0.000335, 0.000057,
                       -0.000002, 0.000016, -0.000012)),
    xray.scatterer( #12
                    label="C6B",
                    site=(-0.708620, -0.325965, 0.011657),
                    u=(0.000503, 0.000318, 0.000053,
                       -0.000058, 0.000032, -0.000019)),
    xray.scatterer( #13
                    label="C10B",
                    site=(-1.179332, -0.083184, -0.202815),
                    u=(0.000280, 0.000424, 0.000136,
                       0.000094, 0.000006, 0.000013)),
    xray.scatterer( #14
                    label="N1A",
                    site=(-0.838363, -0.532191, -0.293213),
                    u=(0.000312, 0.000323, 0.000060,
                       0.000018, 0.000011, -0.000008)),
    xray.scatterer( #15
                    label="C3A",
                    site=(-0.915414, -0.671031, -0.393826),
                    u=(0.000319, 0.000384, 0.000078,
                       -0.000052, -0.000001, -0.000020)),
    xray.scatterer( #16
                    label="C1A",
                    site=(-0.907466, -0.665419, -0.276011),
                    u=(0.000371, 0.000315, 0.000079,
                       0.000006, 0.000036, 0.000033)),
    xray.scatterer( #17
                    label="C1B",
                    site=(-0.365085, -0.452753, -0.231927),
                    u=(0.000321, 0.000253, 0.000087,
                       -0.000024, 0.000047, -0.000034)),
    xray.scatterer( #18
                    label="C11A",
                    site=(-0.598622, 0.053343, -0.227354),
                    u=(0.000265, 0.000409, 0.000084,
                       0.000088, -0.000018, -0.000030)),
    xray.scatterer( #19
                    label="C2A",
                    site=(-0.958694, -0.755645, -0.337016),
                    u=(0.000394, 0.000350, 0.000106,
                       -0.000057, 0.000027, -0.000005)),
    xray.scatterer( #20
                    label="C4A",
                    site=(-0.784860, -0.407601, -0.402050),
                    u=(0.000238, 0.000296, 0.000064,
                       0.000002, 0.000011, -0.000016)),
    xray.scatterer( #21
                    label="C5A",
                    site=(-0.784185, -0.399716, -0.475491),
                    u=(0.000310, 0.000364, 0.000062,
                       0.000044, -0.000011, -0.000017)),
    xray.scatterer( #22
                    label="N4A",
                    site=(-0.630284, -0.043981, -0.333143),
                    u=(0.000290, 0.000275, 0.000074,
                       0.000021, 0.000027, 0.000013)),
    xray.scatterer( #23
                    label="C10A",
                    site=(-0.545465, 0.166922, -0.272829),
                    u=(0.000369, 0.000253, 0.000117,
                       0.000015, -0.000002, -0.000008)),
    xray.scatterer( #24
                    label="C9A",
                    site=(-0.567548, 0.102272, -0.339923),
                    u=(0.000346, 0.000335, 0.000103,
                       -0.000016, 0.000037, 0.000023)),
    xray.scatterer( #25
                    label="C11B",
                    site=(-1.089943, -0.146930, -0.253779),
                    u=(0.000262, 0.000422, 0.000102,
                       -0.000018, -0.000002, 0.000029)),
    xray.scatterer( #26
                    label="N2A",
                    site=(-0.843385, -0.537780, -0.366515),
                    u=(0.000273, 0.000309, 0.000055,
                       -0.000012, -0.000005, -0.000018)),
    xray.scatterer( #27
                    label="C7A",
                    site=(-0.674021, -0.136086, -0.457790),
                    u=(0.000362, 0.000378, 0.000074,
                       0.000043, 0.000034, 0.000016)),
    xray.scatterer( #28
                    label="C8B",
                    site=(-0.843625, -0.264182, -0.102023),
                    u=(0.000264, 0.000275, 0.000072,
                       -0.000025, 0.000019, -0.000005)),
    xray.scatterer( #29
                    label="C6A",
                    site=(-0.726731, -0.261702, -0.502366),
                    u=(0.000339, 0.000472, 0.000064,
                       0.000062, -0.000003, 0.000028)),
    xray.scatterer( #30
                    label="C5B",
                    site=(-0.577197, -0.376753, -0.020800),
                    u=(0.000349, 0.000353, 0.000066,
                       -0.000082, -0.000022, 0.000014)),
    xray.scatterer( #31
                    label="C2B",
                    site=(-0.252088, -0.497338, -0.175057),
                    u=(0.000251, 0.000342, 0.000119,
                       0.000020, 0.000034, -0.000018)),
    xray.scatterer( #32
                    label="C7B",
                    site=(-0.843956, -0.268811, -0.028080),
                    u=(0.000344, 0.000377, 0.000078,
                       -0.000029, 0.000059, -0.000007)),
    xray.scatterer( #33
                    label="F4B",
                    site=(-0.680814, -0.696808, -0.115056),
                    u=(0.000670, 0.000408, 0.000109,
                       -0.000099, 0.000139, -0.000031)),
    xray.scatterer( #34
                    label="F1B",
                    site=(-0.780326, -0.921249, -0.073962),
                    u=(0.000687, 0.000357, 0.000128,
                       -0.000152, -0.000011, 0.000021)),
    xray.scatterer( #35
                    label="B1B",
                    site=(-0.795220, -0.758128, -0.075955),
                    u=(0.000413, 0.000418, 0.000075,
                       0.000054, 0.000045, 0.000023)),
    xray.scatterer( #36
                    label="F2B",
                    site=(-0.945140, -0.714626, -0.105820),
                    u=(0.000584, 0.001371, 0.000108,
                       0.000420, 0.000067, 0.000134)),
    xray.scatterer( #37
                    label="F3B",
                    site=(-0.768914, -0.701660, -0.005161),
                    u=(0.000678, 0.000544, 0.000079,
                       -0.000000, 0.000090, -0.000021)),
    xray.scatterer( #38
                    label="F1A",
                    site=(-0.109283, -0.252334, -0.429288),
                    u=(0.000427, 0.001704, 0.000125,
                       0.000407, 0.000041, 0.000035)),
    xray.scatterer( #39
                    label="F4A",
                    site=(-0.341552, -0.262864, -0.502023),
                    u=(0.000640, 0.000557, 0.000081,
                       -0.000074, 0.000042, -0.000052)),
    xray.scatterer( #40
                    label="F3A",
                    site=(-0.324533, -0.142292, -0.393215),
                    u=(0.000471, 0.001203, 0.000134,
                       0.000333, -0.000057, -0.000220)),
    xray.scatterer( #41
                    label="F2A",
                    site=(-0.312838, -0.405405, -0.400231),
                    u=(0.002822, 0.000831, 0.000092,
                       -0.000648, 0.000115, 0.000027)),
    xray.scatterer( #42
                    label="B1A",
                    site=(-0.271589, -0.268874, -0.430724),
                    u=(0.000643, 0.000443, 0.000079,
                       0.000040, 0.000052, -0.000034)),
    xray.scatterer( #43
                    label="H5B",
                    site=(-0.475808, -0.413802, 0.004402),
                    u=0.005270),
    xray.scatterer( #44
                    label="H6B",
                    site=(-0.699519, -0.326233, 0.062781),
                    u=0.019940),
    xray.scatterer( #45
                    label="H3B",
                    site=(-0.283410, -0.484757, -0.063922),
                    u=0.029990),
    xray.scatterer( #46
                    label="H1B",
                    site=(-0.357103, -0.451819, -0.284911),
                    u=0.031070),
    xray.scatterer( #47
                    label="H10A",
                    site=(-0.495517, 0.268296, -0.256187),
                    u=0.027610),
    xray.scatterer( #48
                    label="H2B",
                    site=(-0.147129, -0.535141, -0.174699),
                    u=0.017930),
    xray.scatterer( #49
                    label="H7A",
                    site=(-0.643658, -0.031387, -0.475357),
                    u=0.020200),
    xray.scatterer( #50
                    label="H1A",
                    site=(-0.912757, -0.691043, -0.227554),
                    u=0.033320),
    xray.scatterer( #51
                    label="H7B",
                    site=(-0.933670, -0.241189, -0.010263),
                    u=0.021310),
    xray.scatterer( #52
                    label="H11B",
                    site=(-1.107736, -0.155470, -0.311996),
                    u=0.041500),
    xray.scatterer( #53
                    label="H9A",
                    site=(-0.539908, 0.139753, -0.382281),
                    u=0.007130),
    xray.scatterer( #54
                    label="H10B",
                    site=(-1.265944, -0.029610, -0.212398),
                    u=0.030910),
    xray.scatterer( #55
                    label="H3A",
                    site=(-0.934728, -0.691149, -0.450551),
                    u=0.038950),
    xray.scatterer( #56
                    label="H5A",
                    site=(-0.833654, -0.487479, -0.508239),
                    u=0.031150),
    xray.scatterer( #57
                    label="H6A",
                    site=(-0.742871, -0.242269, -0.558157),
                    u=0.050490),
    xray.scatterer( #58
                    label="H9B",
                    site=(-1.120150, -0.093752, -0.090706),
                    u=0.039310),
    xray.scatterer( #59
                    label="H11A",
                    site=(-0.593074, 0.054973, -0.180370),
                    u=0.055810),
    xray.scatterer( #60
                    label="H2A",
                    site=(-0.999576, -0.842158, -0.340837),
                    u=0.057030)
    ]))
  fo_sq = xs0.structure_factors(d_min=0.8).f_calc().norm()
  fo_sq = fo_sq.customized_copy(sigmas=flex.double(fo_sq.size(), 1.))
  for hydrogen_flag in (True, False):
    xs = xs0.deep_copy_scatterers()
    if not hydrogen_flag:
      xs.select_inplace(~xs.element_selection('H'))
    xs.shake_adp()
    xs.shake_sites_in_place(rms_difference=0.1)
    for sc in xs.scatterers():
      sc.flags.set_grad_site(True).set_grad_u_aniso(False)
    ls = least_squares.crystallographic_ls(
      fo_sq.as_xray_observations(),
      constraints.reparametrisation(
        structure=xs,
        constraints=[],
        connectivity_table=smtbx.utils.connectivity_table(xs)),
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=
      origin_fixing_restraints.atomic_number_weighting)

    ls.build_up()
    lambdas = eigensystem.real_symmetric(
      ls.normal_matrix_packed_u().matrix_packed_u_as_symmetric()).values()
    # assert the restrained L.S. problem is not too ill-conditionned
    cond = math.log10(lambdas[0]/lambdas[-1])
    msg = ("one heavy element + light elements (real data) %s Hydrogens: %.1f"
           % (['without', 'with'][hydrogen_flag], cond))
    if verbose: print(msg)
    assert cond < worst_condition_number_acceptable, msg


    # are esd's for x,y,z coordinates of the same order of magnitude?
    var_cart = covariance.orthogonalize_covariance_matrix(
      ls.covariance_matrix(),
      xs.unit_cell(),
      xs.parameter_map())
    var_site_cart = covariance.extract_covariance_matrix_for_sites(
        flex.size_t_range(len(xs.scatterers())),
        var_cart,
        xs.parameter_map())
    site_esds = var_site_cart.matrix_packed_u_diagonal()
    indicators = flex.double()
    for i in xrange(0, len(site_esds), 3):
      stats = scitbx.math.basic_statistics(site_esds[i:i+3])
      indicators.append(stats.bias_corrected_standard_deviation/stats.mean)
    assert indicators.all_lt(1)
  def exercise_floating_origin_restraints(self):
    n = self.n_independent_params
    eps_zero_rhs = 1e-6
    connectivity_table = smtbx.utils.connectivity_table(self.xray_structure)
    reparametrisation = constraints.reparametrisation(
      structure=self.xray_structure,
      constraints=[],
      connectivity_table=connectivity_table)
    obs = self.fo_sq.as_xray_observations()
    ls = least_squares.crystallographic_ls(
      obs, reparametrisation,
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=oop.null())
    ls.build_up()
    unrestrained_normal_matrix = ls.normal_matrix_packed_u()
    assert len(unrestrained_normal_matrix) == n*(n+1)//2
    ev = eigensystem.real_symmetric(
      unrestrained_normal_matrix.matrix_packed_u_as_symmetric())
    unrestrained_eigenval = ev.values()
    unrestrained_eigenvec = ev.vectors()

    ls = least_squares.crystallographic_ls(
      obs,
      reparametrisation,
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=
      origin_fixing_restraints.homogeneous_weighting)
    ls.build_up()

    # Let's check that the computed singular directions span the same
    # space as the expected ones
    singular_test = flex.double()
    jac = ls.reparametrisation.jacobian_transpose_matching_grad_fc()
    m = 0
    for s in ls.origin_fixing_restraint.singular_directions:
      assert s.norm() != 0
      singular_test.extend(jac*s)
      m += 1
    for s in self.continuous_origin_shift_basis:
      singular_test.extend(flex.double(s))
      m += 1
    singular_test.reshape(flex.grid(m, n))
    assert self.rank(singular_test) == len(self.continuous_origin_shift_basis)

    assert ls.opposite_of_gradient()\
             .all_approx_equal(0, eps_zero_rhs),\
           list(ls.gradient())
    restrained_normal_matrix = ls.normal_matrix_packed_u()
    assert len(restrained_normal_matrix) == n*(n+1)//2
    ev = eigensystem.real_symmetric(
      restrained_normal_matrix.matrix_packed_u_as_symmetric())
    restrained_eigenval = ev.values()
    restrained_eigenvec = ev.vectors()

    # The eigendecomposition of the normal matrix
    # for the unrestrained problem is:
    #    A = sum_{0 <= i < n-p-1} lambda_i v_i^T v_i
    # where the eigenvalues lambda_i are sorted in decreasing order
    # and p is the dimension of the continous origin shift space.
    # In particular A v_i = 0, n-p <= i < n.
    # In the restrained case, it becomes:
    #    A' = A + sum_{n-p <= i < n} mu v_i^T v_i

    p = len(self.continuous_origin_shift_basis)
    assert approx_equal(restrained_eigenval[p:], unrestrained_eigenval[:-p],
                        eps=1e-12)
    assert unrestrained_eigenval[-p]/unrestrained_eigenval[-p-1] < 1e-12

    if p > 1:
      # eigenvectors are stored by rows
      unrestrained_null_space = unrestrained_eigenvec.matrix_copy_block(
        i_row=n-p, i_column=0,
        n_rows=p, n_columns=n)
      assert self.rank(unrestrained_null_space) == p

      restrained_space = restrained_eigenvec.matrix_copy_block(
        i_row=0, i_column=0,
        n_rows=p, n_columns=n)
      assert self.rank(restrained_space) == p

      singular = flex.double(
        self.continuous_origin_shift_basis)
      assert self.rank(singular) == p

      rank_finder = flex.double(n*3*p)
      rank_finder.resize(flex.grid(3*p, n))
      rank_finder.matrix_paste_block_in_place(unrestrained_null_space,
                                              i_row=0, i_column=0)
      rank_finder.matrix_paste_block_in_place(restrained_space,
                                              i_row=p, i_column=0)
      rank_finder.matrix_paste_block_in_place(singular,
                                              i_row=2*p, i_column=0)
      assert self.rank(rank_finder) == p
    else:
      # this branch handles the case p=1
      # it's necessary to work around a bug in the svd module
      # ( nx1 matrices crashes the code )
      assert approx_equal(
        restrained_eigenvec[0:n].angle(
          unrestrained_eigenvec[-n:]) % math.pi, 0)
      assert approx_equal(
        unrestrained_eigenvec[-n:].angle(
          flex.double(self.continuous_origin_shift_basis[0])) % math.pi, 0)

    # Do the floating origin restraints prevent the structure from floating?
    xs = self.xray_structure.deep_copy_scatterers()
    ls = least_squares.crystallographic_ls(
      obs,
      reparametrisation,
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=
      origin_fixing_restraints.atomic_number_weighting
    )
    barycentre_0 = xs.sites_frac().mean()
    while True:
      xs.shake_sites_in_place(rms_difference=0.15)
      xs.apply_symmetry_sites()
      barycentre_1 = xs.sites_frac().mean()
      delta = matrix.col(barycentre_1) - matrix.col(barycentre_0)
      moved_far_enough = 0
      for singular in self.continuous_origin_shift_basis:
        e = matrix.col(singular[:3])
        if not approx_equal(delta.dot(e), 0, eps=0.01, out=None):
          moved_far_enough += 1
      if moved_far_enough: break

    # one refinement cycle
    ls.build_up()
    ls.solve()
    shifts = ls.step()

    # That's what floating origin restraints are for!
    # Note that in the presence of special position, that's different
    # from the barycentre not moving along the continuous shift directions.
    # TODO: typeset notes about that subtlety.
    for singular in self.continuous_origin_shift_basis:
      assert approx_equal(shifts.dot(flex.double(singular)), 0, eps=1e-12)
Ejemplo n.º 22
0
    def __init__(self,
                 pdb_hierarchy,
                 chain_id_light='L',
                 chain_id_heavy='H',
                 limit_light=107,
                 limit_heavy=113):
        '''
    Get elbow angle for Fragment antigen-binding (Fab)

    - Default heavy and light chains IDs are: H : heavy,  L : light
    - Default limit (cutoff) between variable and constant parts
      are residue number 107/113 for light/heavy chains
    - Variable domain is from residue 1 to limit.
      Constant domain form limit+1 to end.

    Reference:
    ----------
    Stanfield, et al., JMB 2006

    Usage example:
    --------------
    >>>fab = fab_elbow_angle(pdb_hierarchy=ph,limit_light=114,limit_heavy=118)
    >>>fab_angle = fab.fab_elbow_angle
    '''
        # create selection strings for the heavy/light var/const part of chains
        self.select_str(chain_ID_H=chain_id_heavy,
                        limit_H=limit_heavy,
                        chain_ID_L=chain_id_light,
                        limit_L=limit_light)
        # get the hierarchy for and divide using selection strings
        self.pdb_hierarchy = pdb_hierarchy
        self.get_pdb_chains()
        # Get heavy to light reference vector before alignment !!!
        vh_end = self.pdb_var_H.atoms()[-1].xyz
        vl_end = self.pdb_var_L.atoms()[-1].xyz
        mid_H_to_L = self.norm_vec(start=vh_end, end=vl_end)
        # Get transformations objects
        tranformation_const = self.get_transformation(
            fixed_selection=self.pdb_const_H,
            moving_selection=self.pdb_const_L)
        tranformation_var = self.get_transformation(
            fixed_selection=self.pdb_var_H, moving_selection=self.pdb_var_L)
        # Get the angle and eigenvalues
        eigen_const = eigensystem.real_symmetric(
            tranformation_const.r.as_sym_mat3())
        eigen_var = eigensystem.real_symmetric(
            tranformation_var.r.as_sym_mat3())
        # c : consttant, v : variable
        eigenvectors_c = self.get_eigenvector(eigen_const)
        eigenvectors_v = self.get_eigenvector(eigen_var)
        # test eignevectors pointing in oposite directions
        if eigenvectors_c.dot(eigenvectors_v) > 0:
            eigenvectors_v = -eigenvectors_v
        # Calc Feb elbow angle
        angle = self.get_angle(vec1=eigenvectors_c, vec2=eigenvectors_v)
        # Test if elbow angle larger or smaller than 180
        zaxis = self.cross_product_as_unit_axis(eigenvectors_v, eigenvectors_c)
        xaxis = self.cross_product_as_unit_axis(eigenvectors_c, zaxis)
        if mid_H_to_L.dot(zaxis) <= 0:
            angle = 360 - angle
        self.fab_elbow_angle = angle
        # The cosine of the angles the vector from limit_heavy to limit_light
        # make with the axes x, y (eigenvectors_c), z
        # where the eigenvectors_v lies in the plane x - y
        self.cos_H_to_L_with_xaxis = mid_H_to_L.dot(xaxis)
        self.cos_H_to_L_with_yaxis = mid_H_to_L.dot(eigenvectors_c)
        self.cos_H_to_L_with_zaxis = mid_H_to_L.dot(zaxis)
Ejemplo n.º 23
0
  def __init__(self,
               miller_array,
               n_residues=None,
               n_bases=None,
               asu_contents=None,
               prot_frac = 1.0,
               nuc_frac= 0.0):
    """ Maximum likelihood anisotropic wilson scaling"""
    #Checking input
    if (n_residues is None):
      if (n_bases is None):
        assert asu_contents is not None
        assert (type(asu_contents) == type({}) )
    if asu_contents is None:
      assert ( (n_residues is not None) or (n_bases is not None) )
    assert (prot_frac+nuc_frac<=1.0)
    assert ( miller_array.is_real_array() )

    self.info = miller_array.info()
    if ( miller_array.is_xray_intensity_array() ):
      miller_array = miller_array.f_sq_as_f()

    work_array = miller_array.resolution_filter(
      d_max=1.0/math.sqrt(  scaling.get_d_star_sq_low_limit() ),
      d_min=1.0/math.sqrt( scaling.get_d_star_sq_high_limit() ))
    work_array = work_array.select(work_array.data()>0)
    self.d_star_sq = work_array.d_star_sq().data()
    self.scat_info =  None
    if asu_contents is None:
      self.scat_info= scattering_information(
                                        n_residues=n_residues,
                                        n_bases = n_bases)
    else:
      self.scat_info = scattering_information(
                                         asu_contents = asu_contents,
                                         fraction_protein = prot_frac,
                                         fraction_nucleic = nuc_frac)
    self.scat_info.scat_data(self.d_star_sq)
    self.b_cart = None
    if (work_array.size() > 0 ):
      self.hkl = work_array.indices()
      self.f_obs = work_array.data()
      self.unit_cell =  uctbx.unit_cell(
        miller_array.unit_cell().parameters() )
      ## Make sure sigma's are used when available
      if (work_array.sigmas() is not None):
        self.sigma_f_obs = work_array.sigmas()
      else:
        self.sigma_f_obs = flex.double(self.f_obs.size(),0.0)
      if (flex.min( self.sigma_f_obs ) < 0):
        self.sigma_f_obs = self.sigma_f_obs*0.0

      ## multiplicities
      self.epsilon = work_array.epsilons().data().as_double()
      ## Determine Wilson parameters
      self.gamma_prot = self.scat_info.gamma_tot
      self.sigma_prot_sq = self.scat_info.sigma_tot_sq
      ## centric flags
      self.centric = flex.bool(work_array.centric_flags().data())
      ## Symmetry stuff
      self.sg = work_array.space_group()
      self.adp_constraints = self.sg.adp_constraints()
      self.dim_u = self.adp_constraints.n_independent_params()
      ## Setup number of parameters
      assert self.dim_u <= 6
      ## Optimisation stuff
      self.x = flex.double(self.dim_u+1, 0.0) ## B-values and scale factor!
      exception_handling_params = scitbx.lbfgs.exception_handling_parameters(
        ignore_line_search_failed_step_at_lower_bound = False,
        ignore_line_search_failed_step_at_upper_bound = False,
        ignore_line_search_failed_maxfev              = False)
      term_parameters = scitbx.lbfgs.termination_parameters(
        max_iterations = 50)

      minimizer = scitbx.lbfgs.run(target_evaluator=self,
        termination_params=term_parameters,
        exception_handling_params=exception_handling_params)

      ## Done refining
      Vrwgk = math.pow(self.unit_cell.volume(),2.0/3.0)
      self.p_scale = self.x[0]
      self.u_star = self.unpack()
      self.u_star = list( flex.double(self.u_star) / Vrwgk )
      self.b_cart = adptbx.u_as_b(adptbx.u_star_as_u_cart(self.unit_cell,
                                       self.u_star))
      self.u_cif = adptbx.u_star_as_u_cif(self.unit_cell,
                                          self.u_star)
      #get eigenvalues of B-cart
      eigen = eigensystem.real_symmetric( self.b_cart )
      self.eigen_values = eigen.values()
      self.eigen_vectors = eigen.vectors()

      self.work_array  = work_array # i need this for further analyses
      self.analyze_aniso_correction()
      # FIXME see 3ihm:IOBS4,SIGIOBS4
      if (self.eigen_values[0] != 0) :
        self.anirat = (abs(self.eigen_values[0] - self.eigen_values[2]) /
                     self.eigen_values[0])
      else :
        self.anirat = None

      del self.x
      del self.f_obs
      del self.sigma_f_obs
      del self.epsilon
      del self.gamma_prot
      del self.sigma_prot_sq
      del self.centric
      del self.hkl
      del self.d_star_sq
      del self.adp_constraints
Ejemplo n.º 24
0
def exercise_floating_origin_dynamic_weighting(verbose=False):
  from cctbx import covariance
  import scitbx.math

  worst_condition_number_acceptable = 10

  # light elements only
  xs0 = random_structure.xray_structure(elements=['C', 'C', 'C', 'O', 'N'],
                                        use_u_aniso=True)
  fo_sq = xs0.structure_factors(d_min=0.8).f_calc().norm()
  fo_sq = fo_sq.customized_copy(sigmas=flex.double(fo_sq.size(), 1.))
  xs = xs0.deep_copy_scatterers()
  xs.shake_adp()
  xs.shake_sites_in_place(rms_difference=0.1)
  for sc in xs.scatterers():
    sc.flags.set_grad_site(True).set_grad_u_aniso(True)
  ls = least_squares.crystallographic_ls(
    fo_sq.as_xray_observations(),
    constraints.reparametrisation(
      structure=xs,
      constraints=[],
      connectivity_table=smtbx.utils.connectivity_table(xs)),
    weighting_scheme=least_squares.unit_weighting(),
    origin_fixing_restraints_type=
    origin_fixing_restraints.atomic_number_weighting)
  ls.build_up()
  lambdas = eigensystem.real_symmetric(
    ls.normal_matrix_packed_u().matrix_packed_u_as_symmetric()).values()
  # assert the restrained L.S. problem is not too ill-conditionned
  cond = math.log10(lambdas[0]/lambdas[-1])
  msg = "light elements: %.1f" % cond
  if verbose: print msg
  assert cond < worst_condition_number_acceptable, msg

  # one heavy element
  xs0 = random_structure.xray_structure(
    space_group_info=sgtbx.space_group_info('hall: P 2yb'),
    elements=['Zn', 'C', 'C', 'C', 'O', 'N'],
    use_u_aniso=True)
  fo_sq = xs0.structure_factors(d_min=0.8).f_calc().norm()
  fo_sq = fo_sq.customized_copy(sigmas=flex.double(fo_sq.size(), 1.))
  xs = xs0.deep_copy_scatterers()
  xs.shake_adp()
  xs.shake_sites_in_place(rms_difference=0.1)
  for sc in xs.scatterers():
    sc.flags.set_grad_site(True).set_grad_u_aniso(True)
  ls = least_squares.crystallographic_ls(
    fo_sq.as_xray_observations(),
    constraints.reparametrisation(
      structure=xs,
      constraints=[],
      connectivity_table=smtbx.utils.connectivity_table(xs)),
    weighting_scheme=least_squares.mainstream_shelx_weighting(),
    origin_fixing_restraints_type=
    origin_fixing_restraints.atomic_number_weighting)
  ls.build_up()
  lambdas = eigensystem.real_symmetric(
    ls.normal_matrix_packed_u().matrix_packed_u_as_symmetric()).values()
  # assert the restrained L.S. problem is not too ill-conditionned
  cond = math.log10(lambdas[0]/lambdas[-1])
  msg = "one heavy element + light elements (synthetic data): %.1f" % cond
  if verbose: print msg
  assert cond < worst_condition_number_acceptable, msg

  # are esd's for x,y,z coordinates of the same order of magnitude?
  var_cart = covariance.orthogonalize_covariance_matrix(
    ls.covariance_matrix(),
    xs.unit_cell(),
    xs.parameter_map())
  var_site_cart = covariance.extract_covariance_matrix_for_sites(
      flex.size_t_range(len(xs.scatterers())),
      var_cart,
      xs.parameter_map())
  site_esds = var_site_cart.matrix_packed_u_diagonal()
  indicators = flex.double()
  for i in xrange(0, len(site_esds), 3):
    stats = scitbx.math.basic_statistics(site_esds[i:i+3])
    indicators.append(stats.bias_corrected_standard_deviation/stats.mean)
  assert indicators.all_lt(1)

  # especially troublesome structure with one heavy element
  # (contributed by Jonathan Coome)
  xs0 = xray.structure(
    crystal_symmetry=crystal.symmetry(
      unit_cell=(8.4519, 8.4632, 18.7887, 90, 96.921, 90),
      space_group_symbol="hall: P 2yb"),
    scatterers=flex.xray_scatterer([
      xray.scatterer( #0
                      label="ZN1",
                      site=(-0.736683, -0.313978, -0.246902),
                      u=(0.000302, 0.000323, 0.000054,
                         0.000011, 0.000015, -0.000004)),
      xray.scatterer( #1
                      label="N3B",
                      site=(-0.721014, -0.313583, -0.134277),
                      u=(0.000268, 0.000237, 0.000055,
                         -0.000027, 0.000005, 0.000006)),
      xray.scatterer( #2
                      label="N3A",
                      site=(-0.733619, -0.290423, -0.357921),
                      u=(0.000229, 0.000313, 0.000053,
                         0.000022, 0.000018, -0.000018)),
      xray.scatterer( #3
                      label="C9B",
                      site=(-1.101537, -0.120157, -0.138063),
                      u=(0.000315, 0.000345, 0.000103,
                         0.000050, 0.000055, -0.000017)),
    xray.scatterer( #4
                    label="N5B",
                    site=(-0.962032, -0.220345, -0.222045),
                    u=(0.000274, 0.000392, 0.000060,
                       -0.000011, -0.000001, -0.000002)),
    xray.scatterer( #5
                    label="N1B",
                    site=(-0.498153, -0.402742, -0.208698),
                    u=(0.000252, 0.000306, 0.000063,
                       0.000000, 0.000007, 0.000018)),
    xray.scatterer( #6
                    label="C3B",
                    site=(-0.322492, -0.472610, -0.114594),
                    u=(0.000302, 0.000331, 0.000085,
                       0.000016, -0.000013, 0.000037)),
    xray.scatterer( #7
                    label="C4B",
                    site=(-0.591851, -0.368163, -0.094677),
                    u=(0.000262, 0.000255, 0.000073,
                       -0.000034, 0.000027, -0.000004)),
    xray.scatterer( #8
                    label="N4B",
                    site=(-0.969383, -0.204624, -0.150014),
                    u=(0.000279, 0.000259, 0.000070,
                       -0.000009, 0.000039, 0.000000)),
    xray.scatterer( #9
                    label="N2B",
                    site=(-0.470538, -0.414572, -0.135526),
                    u=(0.000277, 0.000282, 0.000065,
                       0.000003, 0.000021, -0.000006)),
    xray.scatterer( #10
                    label="C8A",
                    site=(-0.679889, -0.158646, -0.385629),
                    u=(0.000209, 0.000290, 0.000078,
                       0.000060, 0.000006, 0.000016)),
    xray.scatterer( #11
                    label="N5A",
                    site=(-0.649210, -0.075518, -0.263412),
                    u=(0.000307, 0.000335, 0.000057,
                       -0.000002, 0.000016, -0.000012)),
    xray.scatterer( #12
                    label="C6B",
                    site=(-0.708620, -0.325965, 0.011657),
                    u=(0.000503, 0.000318, 0.000053,
                       -0.000058, 0.000032, -0.000019)),
    xray.scatterer( #13
                    label="C10B",
                    site=(-1.179332, -0.083184, -0.202815),
                    u=(0.000280, 0.000424, 0.000136,
                       0.000094, 0.000006, 0.000013)),
    xray.scatterer( #14
                    label="N1A",
                    site=(-0.838363, -0.532191, -0.293213),
                    u=(0.000312, 0.000323, 0.000060,
                       0.000018, 0.000011, -0.000008)),
    xray.scatterer( #15
                    label="C3A",
                    site=(-0.915414, -0.671031, -0.393826),
                    u=(0.000319, 0.000384, 0.000078,
                       -0.000052, -0.000001, -0.000020)),
    xray.scatterer( #16
                    label="C1A",
                    site=(-0.907466, -0.665419, -0.276011),
                    u=(0.000371, 0.000315, 0.000079,
                       0.000006, 0.000036, 0.000033)),
    xray.scatterer( #17
                    label="C1B",
                    site=(-0.365085, -0.452753, -0.231927),
                    u=(0.000321, 0.000253, 0.000087,
                       -0.000024, 0.000047, -0.000034)),
    xray.scatterer( #18
                    label="C11A",
                    site=(-0.598622, 0.053343, -0.227354),
                    u=(0.000265, 0.000409, 0.000084,
                       0.000088, -0.000018, -0.000030)),
    xray.scatterer( #19
                    label="C2A",
                    site=(-0.958694, -0.755645, -0.337016),
                    u=(0.000394, 0.000350, 0.000106,
                       -0.000057, 0.000027, -0.000005)),
    xray.scatterer( #20
                    label="C4A",
                    site=(-0.784860, -0.407601, -0.402050),
                    u=(0.000238, 0.000296, 0.000064,
                       0.000002, 0.000011, -0.000016)),
    xray.scatterer( #21
                    label="C5A",
                    site=(-0.784185, -0.399716, -0.475491),
                    u=(0.000310, 0.000364, 0.000062,
                       0.000044, -0.000011, -0.000017)),
    xray.scatterer( #22
                    label="N4A",
                    site=(-0.630284, -0.043981, -0.333143),
                    u=(0.000290, 0.000275, 0.000074,
                       0.000021, 0.000027, 0.000013)),
    xray.scatterer( #23
                    label="C10A",
                    site=(-0.545465, 0.166922, -0.272829),
                    u=(0.000369, 0.000253, 0.000117,
                       0.000015, -0.000002, -0.000008)),
    xray.scatterer( #24
                    label="C9A",
                    site=(-0.567548, 0.102272, -0.339923),
                    u=(0.000346, 0.000335, 0.000103,
                       -0.000016, 0.000037, 0.000023)),
    xray.scatterer( #25
                    label="C11B",
                    site=(-1.089943, -0.146930, -0.253779),
                    u=(0.000262, 0.000422, 0.000102,
                       -0.000018, -0.000002, 0.000029)),
    xray.scatterer( #26
                    label="N2A",
                    site=(-0.843385, -0.537780, -0.366515),
                    u=(0.000273, 0.000309, 0.000055,
                       -0.000012, -0.000005, -0.000018)),
    xray.scatterer( #27
                    label="C7A",
                    site=(-0.674021, -0.136086, -0.457790),
                    u=(0.000362, 0.000378, 0.000074,
                       0.000043, 0.000034, 0.000016)),
    xray.scatterer( #28
                    label="C8B",
                    site=(-0.843625, -0.264182, -0.102023),
                    u=(0.000264, 0.000275, 0.000072,
                       -0.000025, 0.000019, -0.000005)),
    xray.scatterer( #29
                    label="C6A",
                    site=(-0.726731, -0.261702, -0.502366),
                    u=(0.000339, 0.000472, 0.000064,
                       0.000062, -0.000003, 0.000028)),
    xray.scatterer( #30
                    label="C5B",
                    site=(-0.577197, -0.376753, -0.020800),
                    u=(0.000349, 0.000353, 0.000066,
                       -0.000082, -0.000022, 0.000014)),
    xray.scatterer( #31
                    label="C2B",
                    site=(-0.252088, -0.497338, -0.175057),
                    u=(0.000251, 0.000342, 0.000119,
                       0.000020, 0.000034, -0.000018)),
    xray.scatterer( #32
                    label="C7B",
                    site=(-0.843956, -0.268811, -0.028080),
                    u=(0.000344, 0.000377, 0.000078,
                       -0.000029, 0.000059, -0.000007)),
    xray.scatterer( #33
                    label="F4B",
                    site=(-0.680814, -0.696808, -0.115056),
                    u=(0.000670, 0.000408, 0.000109,
                       -0.000099, 0.000139, -0.000031)),
    xray.scatterer( #34
                    label="F1B",
                    site=(-0.780326, -0.921249, -0.073962),
                    u=(0.000687, 0.000357, 0.000128,
                       -0.000152, -0.000011, 0.000021)),
    xray.scatterer( #35
                    label="B1B",
                    site=(-0.795220, -0.758128, -0.075955),
                    u=(0.000413, 0.000418, 0.000075,
                       0.000054, 0.000045, 0.000023)),
    xray.scatterer( #36
                    label="F2B",
                    site=(-0.945140, -0.714626, -0.105820),
                    u=(0.000584, 0.001371, 0.000108,
                       0.000420, 0.000067, 0.000134)),
    xray.scatterer( #37
                    label="F3B",
                    site=(-0.768914, -0.701660, -0.005161),
                    u=(0.000678, 0.000544, 0.000079,
                       -0.000000, 0.000090, -0.000021)),
    xray.scatterer( #38
                    label="F1A",
                    site=(-0.109283, -0.252334, -0.429288),
                    u=(0.000427, 0.001704, 0.000125,
                       0.000407, 0.000041, 0.000035)),
    xray.scatterer( #39
                    label="F4A",
                    site=(-0.341552, -0.262864, -0.502023),
                    u=(0.000640, 0.000557, 0.000081,
                       -0.000074, 0.000042, -0.000052)),
    xray.scatterer( #40
                    label="F3A",
                    site=(-0.324533, -0.142292, -0.393215),
                    u=(0.000471, 0.001203, 0.000134,
                       0.000333, -0.000057, -0.000220)),
    xray.scatterer( #41
                    label="F2A",
                    site=(-0.312838, -0.405405, -0.400231),
                    u=(0.002822, 0.000831, 0.000092,
                       -0.000648, 0.000115, 0.000027)),
    xray.scatterer( #42
                    label="B1A",
                    site=(-0.271589, -0.268874, -0.430724),
                    u=(0.000643, 0.000443, 0.000079,
                       0.000040, 0.000052, -0.000034)),
    xray.scatterer( #43
                    label="H5B",
                    site=(-0.475808, -0.413802, 0.004402),
                    u=0.005270),
    xray.scatterer( #44
                    label="H6B",
                    site=(-0.699519, -0.326233, 0.062781),
                    u=0.019940),
    xray.scatterer( #45
                    label="H3B",
                    site=(-0.283410, -0.484757, -0.063922),
                    u=0.029990),
    xray.scatterer( #46
                    label="H1B",
                    site=(-0.357103, -0.451819, -0.284911),
                    u=0.031070),
    xray.scatterer( #47
                    label="H10A",
                    site=(-0.495517, 0.268296, -0.256187),
                    u=0.027610),
    xray.scatterer( #48
                    label="H2B",
                    site=(-0.147129, -0.535141, -0.174699),
                    u=0.017930),
    xray.scatterer( #49
                    label="H7A",
                    site=(-0.643658, -0.031387, -0.475357),
                    u=0.020200),
    xray.scatterer( #50
                    label="H1A",
                    site=(-0.912757, -0.691043, -0.227554),
                    u=0.033320),
    xray.scatterer( #51
                    label="H7B",
                    site=(-0.933670, -0.241189, -0.010263),
                    u=0.021310),
    xray.scatterer( #52
                    label="H11B",
                    site=(-1.107736, -0.155470, -0.311996),
                    u=0.041500),
    xray.scatterer( #53
                    label="H9A",
                    site=(-0.539908, 0.139753, -0.382281),
                    u=0.007130),
    xray.scatterer( #54
                    label="H10B",
                    site=(-1.265944, -0.029610, -0.212398),
                    u=0.030910),
    xray.scatterer( #55
                    label="H3A",
                    site=(-0.934728, -0.691149, -0.450551),
                    u=0.038950),
    xray.scatterer( #56
                    label="H5A",
                    site=(-0.833654, -0.487479, -0.508239),
                    u=0.031150),
    xray.scatterer( #57
                    label="H6A",
                    site=(-0.742871, -0.242269, -0.558157),
                    u=0.050490),
    xray.scatterer( #58
                    label="H9B",
                    site=(-1.120150, -0.093752, -0.090706),
                    u=0.039310),
    xray.scatterer( #59
                    label="H11A",
                    site=(-0.593074, 0.054973, -0.180370),
                    u=0.055810),
    xray.scatterer( #60
                    label="H2A",
                    site=(-0.999576, -0.842158, -0.340837),
                    u=0.057030)
    ]))
  fo_sq = xs0.structure_factors(d_min=0.8).f_calc().norm()
  fo_sq = fo_sq.customized_copy(sigmas=flex.double(fo_sq.size(), 1.))
  for hydrogen_flag in (True, False):
    xs = xs0.deep_copy_scatterers()
    if not hydrogen_flag:
      xs.select_inplace(~xs.element_selection('H'))
    xs.shake_adp()
    xs.shake_sites_in_place(rms_difference=0.1)
    for sc in xs.scatterers():
      sc.flags.set_grad_site(True).set_grad_u_aniso(False)
    ls = least_squares.crystallographic_ls(
      fo_sq.as_xray_observations(),
      constraints.reparametrisation(
        structure=xs,
        constraints=[],
        connectivity_table=smtbx.utils.connectivity_table(xs)),
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=
      origin_fixing_restraints.atomic_number_weighting)

    ls.build_up()
    lambdas = eigensystem.real_symmetric(
      ls.normal_matrix_packed_u().matrix_packed_u_as_symmetric()).values()
    # assert the restrained L.S. problem is not too ill-conditionned
    cond = math.log10(lambdas[0]/lambdas[-1])
    msg = ("one heavy element + light elements (real data) %s Hydrogens: %.1f"
           % (['without', 'with'][hydrogen_flag], cond))
    if verbose: print msg
    assert cond < worst_condition_number_acceptable, msg


    # are esd's for x,y,z coordinates of the same order of magnitude?
    var_cart = covariance.orthogonalize_covariance_matrix(
      ls.covariance_matrix(),
      xs.unit_cell(),
      xs.parameter_map())
    var_site_cart = covariance.extract_covariance_matrix_for_sites(
        flex.size_t_range(len(xs.scatterers())),
        var_cart,
        xs.parameter_map())
    site_esds = var_site_cart.matrix_packed_u_diagonal()
    indicators = flex.double()
    for i in xrange(0, len(site_esds), 3):
      stats = scitbx.math.basic_statistics(site_esds[i:i+3])
      indicators.append(stats.bias_corrected_standard_deviation/stats.mean)
    assert indicators.all_lt(1)
Ejemplo n.º 25
0
def exercise_eigensystem():
    s = eigensystem.real_symmetric(m=flex.double(flex.grid(0, 0)),
                                   relative_epsilon=1e-6,
                                   absolute_epsilon=1e-6)
    s.values().all() == (0, )
    assert s.vectors().all() == (0, 0)
    u = s.generalized_inverse_as_packed_u()
    assert u.all() == (0, )
    m = u.matrix_packed_u_as_symmetric()
    assert m.all() == (0, 0)
    #
    for n in xrange(1, 10):
        m = flex.double(flex.grid(n, n))
        s = eigensystem.real_symmetric(m)
        assert approx_equal(tuple(s.values()), [0] * n)
        v = s.vectors()
        for i in xrange(n):
            for j in xrange(n):
                x = 0
                if (i == j): x = 1
                assert approx_equal(v[(i, j)], x)
        v = []
        for i in xrange(n):
            j = (i * 13 + 17) % n
            v.append(j)
            m[i * (n + 1)] = j
        s = eigensystem.real_symmetric(m)
        if (n == 3):
            ss = eigensystem.real_symmetric(
                (m[0], m[4], m[8], m[1], m[2], m[5]))
            assert approx_equal(s.values(), ss.values())
            assert approx_equal(s.vectors(), ss.vectors())
        v.sort()
        v.reverse()
        assert approx_equal(s.values(), v)
        if (n > 1):
            assert approx_equal(flex.min(s.vectors()), 0)
        assert approx_equal(flex.max(s.vectors()), 1)
        assert approx_equal(flex.sum(s.vectors()), n)
        for t in xrange(10):
            for i in xrange(n):
                for j in xrange(i, n):
                    m[i * n + j] = random.random() - 0.5
                    if (i != j):
                        m[j * n + i] = m[i * n + j]
            s = eigensystem.real_symmetric(m)
            if (n == 3):
                ss = eigensystem.real_symmetric(
                    (m[0], m[4], m[8], m[1], m[2], m[5]))
                assert approx_equal(s.values(), ss.values())
                assert approx_equal(s.vectors(), ss.vectors())
            v = list(s.values())
            v.sort()
            v.reverse()
            assert list(s.values()) == v
            for i in xrange(n):
                l = s.values()[i]
                x = s.vectors()[i * n:i * n + n]
                mx = matrix_mul(m, n, n, x, n, 1)
                lx = [e * l for e in x]
                assert approx_equal(mx, lx)
    #
    m = (1.4573362052597449, 1.7361052947659894, 2.8065584999742659,
         -0.5387293498219814, -0.018204949672480729, 0.44956507395617257)
    n_repetitions = 10000
    t0 = time.time()
    v = time_eigensystem_real_symmetric(m, n_repetitions)
    assert v == (0, 0, 0)
    print "time_eigensystem_real_symmetric: %.3f micro seconds" % (
        (time.time() - t0) / n_repetitions * 1.e6)
    from scitbx.linalg import time_lapack_dsyev
    for use_fortran in [False, True]:
        if (not use_fortran):
            if (not scitbx.linalg.fem_is_available()): continue
            impl_id = "fem"
        else:
            if (not scitbx.linalg.for_is_available()): continue
            impl_id = "for"
        v = time_lapack_dsyev(m, 2, use_fortran)
        # to trigger one-time initialization of SAVE variables
        t0 = time.time()
        v = time_lapack_dsyev(m, n_repetitions, use_fortran)
        assert v == (0, 0, 0)
        print "time_lapack_dsyev %s: %.3f micro seconds" % (
            impl_id, (time.time() - t0) / n_repetitions * 1.e6)
    #
    s = eigensystem.real_symmetric(m=m)
    assert s.min_abs_pivot() > 0
    assert s.min_abs_pivot() < 1.e-10
    assert approx_equal(s.generalized_inverse_as_packed_u(), [
        0.77839538602575065, 0.25063185439711611, -0.03509803174624003,
        0.68162798233326816, -0.10755998636596431, 0.37330996497431423
    ])
    s = eigensystem.real_symmetric(m=m, absolute_epsilon=10)
    assert s.min_abs_pivot() == 10
    assert approx_equal(s.vectors(), [0, 0, 1, 0, 1, 0, 1, 0, 0])
    assert approx_equal(
        s.values(),
        [2.8065584999742659, 1.7361052947659894, 1.4573362052597449])
    s = eigensystem.real_symmetric(m=m, relative_epsilon=0)
    assert s.min_abs_pivot() == 0
    assert approx_equal(s.values(), [3, 2, 1])
Ejemplo n.º 26
0
  def __init__(self,
               pdb_file_name,
               chain_ID_light='L',
               chain_ID_heavy='H',
               limit_light=107,
               limit_heavy=113):
    '''
    Get elbow angle for Fragment antigen-binding (Fab)

    - Default heavy and light chains IDs are: H : heavy,  L : light
    - Default limit (cutoff) between variable and constant parts
      is residue number 107/113 for light/heavy chains
    - Variable domain si from residue 1 to limit.
      Constant domain form limit+1 to end.
    - Method of calculating angle is based on Stanfield, et al., JMB 2006

    Argument:
    ---------
    pdb_file_name : 4 characters string, a PDB name
    chain_ID_heavy : The heavy protion of the protein, chain ID
    chain_ID_light : The light protion of the protein, chain ID
    limit_heavy : the number of the cutoff residue, between
                  the variable and constant portions in the heavy chian
    limit_light : the number of the cutoff residue, between
                  the variable and constant portions in the light chian

    Main attributes:
    ----------------
    self.FAB_elbow_angle : the elbow angle calculated as the dot product of
                           the VL-VH pseudodyade axie and the CL-CH pseudodyade axie
                           The angle always computes between 90 and 180

    Test program at:
    cctbx_project\mmtbx\regression\tst_FAB_elbow_angle.py

    Example:
    --------
    >>>fab = FAB_elbow_angle(
         pdb_file_name='1bbd',
         chain_ID_light='L',
         chain_ID_heavy='H',
         limit_light=114,
         limit_heavy=118)
    >>> print fab.FAB_elbow_angle
    133
    >>>fab = FAB_elbow_angle(pdb_file_name='1bbd')
    >>> print fab.FAB_elbow_angle
    126 (127 in Stanfield, et al., JMB 2006)
    >>> print fab.var_L
    'VL from  N   ASP L   1  to  O   GLY L 107 '
    >>> print fab.var_L_nAtoms
    826

    @author Youval Dar (LBL 2014)
    '''
    # abolute path and test that file exist
    pdb_file_name = self.get_pdb_file_name_and_path(pdb_file_name)
    # Devide to variable and constant part, and get the hirarchy for
    # H : heavy,  L : light
    # start_to_limit : Constant
    # limit_to_end : Variable
    pdb_var_H,pdb_const_H = self.get_pdb_protions(
      pdb_file_name=pdb_file_name,
      chain_ID=chain_ID_heavy,
      limit=limit_heavy)
    pdb_var_L,pdb_const_L = self.get_pdb_protions(
      pdb_file_name=pdb_file_name,
      chain_ID=chain_ID_light,
      limit=limit_light)
    # Collect info about FAB segments
    self.var_L,self.var_L_nAtoms = self.get_segment_info(pdb_var_L,'VL')
    self.var_H,self.var_H_nAtoms = self.get_segment_info(pdb_var_H,'VH')
    self.const_L,self.const_L_nAtoms = self.get_segment_info(pdb_const_L,'CL')
    self.const_H,self.const_H_nAtoms = self.get_segment_info(pdb_const_H,'CH')
    # get 1bbd
    currnet_dir = os.getcwd()
    tempdir = tempfile.mkdtemp('tempdir')
    os.chdir(tempdir)
    fetch.get_pdb ('1bbd',data_type='pdb',mirror='rcsb',log=null_out())
    # seperate chains for testing and referance
    test_var_H,test_const_H = self.get_pdb_protions(
      pdb_file_name=pdb_file_name,
      chain_ID=chain_ID_heavy,
      limit=limit_heavy)
    pdb_ref_var_H,pdb_ref_const_H = self.get_pdb_protions(
      pdb_file_name='1bbd.pdb',
      chain_ID=chain_ID_heavy,
      limit=limit_heavy)
    # clean temp folder
    os.chdir(currnet_dir)
    shutil.rmtree(tempdir)
    # get rotation and translation
    tranformation_const = self.get_transformation(
      pdb_hierarchy_fixed=pdb_const_H,
      pdb_hierarchy_moving=pdb_const_L)

    tranformation_var = self.get_transformation(
      pdb_hierarchy_fixed=pdb_var_H,
      pdb_hierarchy_moving=pdb_var_L)

    tranformation_ref_const = self.get_transformation(
      pdb_hierarchy_fixed=pdb_ref_const_H,
      pdb_hierarchy_moving=test_const_H)

    # Apply transformation on the variable portion of the tesed protein
    new_sites = tranformation_ref_const.r.elems*test_var_H.atoms().extract_xyz() + tranformation_ref_const.t
    test_var_H.atoms().set_xyz(new_sites)

    # get rotation and translation
    tranformation_ref_var = self.get_transformation(
      pdb_hierarchy_fixed=pdb_ref_var_H,
      pdb_hierarchy_moving=test_var_H)

    # Get the angle and eigenvalues
    eigen_const = eigensystem.real_symmetric(tranformation_const.r.as_sym_mat3())
    eigen_var = eigensystem.real_symmetric(tranformation_var.r.as_sym_mat3())
    eigen_ref = eigensystem.real_symmetric(tranformation_ref_var.r.as_sym_mat3())
    #
    eigen_vectors_const = self.get_eigenvector(eigen_const)
    eigen_vectors_var = self.get_eigenvector(eigen_var)
    eigen_vectors_var_ref = self.get_eigenvector(eigen_ref)
    #
    angle = self.get_angle(vec1=eigen_vectors_const, vec2=eigen_vectors_var)
    print '+'*30
    ref_angle = self.get_angle(vec1=eigen_vectors_var_ref, vec2=eigen_vectors_var,larger=False)
    # Resolve ambiguity with angle
    if ref_angle > 90: ref_angle = 180 - ref_angle
    if angle + ref_angle > 180:
      # Choose angle smaller than 180
      angle = 360 - angle
    self.FAB_elbow_angle = angle
Ejemplo n.º 27
0
    def compute(self, reflections):

        print("Computing bbox for %d reflections" % len(reflections))

        # Compute quantile
        quantile = chisq_quantile(2, 0.997)
        D = sqrt(quantile) * 2
        bbox = flex.int6()
        print("ML: %f" % D)
        for i in range(len(reflections)):
            s1 = matrix.col(reflections[i]["s1"])
            s2 = matrix.col(reflections[i]["s2"])

            s0 = matrix.col(self.experiment.beam.get_s0())

            # Ensure our values are ok
            assert s1.length() > 0

            sigma = MosaicityParameterisation(self.parameters).sigma()
            R = compute_change_of_basis_operation(s0, s2)
            S = R * sigma * R.transpose()
            mu = R * s2
            assert abs(1 - mu.normalize().dot(matrix.col((0, 0, 1)))) < 1e-7

            S11 = matrix.sqr((S[0], S[1], S[3], S[4]))
            S12 = matrix.col((S[2], S[5]))
            S21 = matrix.col((S[6], S[7])).transpose()
            S22 = S[8]

            mu1 = matrix.col((mu[0], mu[1]))
            mu2 = mu[2]

            mubar = mu1 + S12 * (1 / S22) * (s0.length() - mu2)
            Sbar = S11 - S12 * (1 / S22) * S21

            eigen_decomposition = eigensystem.real_symmetric(
                Sbar.as_flex_double_matrix())
            Q = matrix.sqr(eigen_decomposition.vectors())
            L = matrix.diag(eigen_decomposition.values())
            max_L = max(L)

            delta = sqrt(max_L) * D

            p1 = mubar + matrix.col((-delta, -delta))
            p2 = mubar + matrix.col((-delta, +delta))
            p3 = mubar + matrix.col((+delta, -delta))
            p4 = mubar + matrix.col((+delta, +delta))

            p1 = matrix.col((p1[0], p1[1], s0.length())).normalize()
            p2 = matrix.col((p2[0], p2[1], s0.length())).normalize()
            p3 = matrix.col((p3[0], p3[1], s0.length())).normalize()
            p4 = matrix.col((p4[0], p4[1], s0.length())).normalize()

            x1 = R.transpose() * p1
            x2 = R.transpose() * p2
            x3 = R.transpose() * p3
            x4 = R.transpose() * p4

            xy1 = self.experiment.detector[0].get_ray_intersection_px(x1)
            xy2 = self.experiment.detector[0].get_ray_intersection_px(x2)
            xy3 = self.experiment.detector[0].get_ray_intersection_px(x3)
            xy4 = self.experiment.detector[0].get_ray_intersection_px(x4)

            xx = (xy1[0], xy2[0], xy3[0], xy4[0])
            yy = (xy1[1], xy2[1], xy3[1], xy4[1])
            x0, x1 = int(floor(min(xx))) - 1, int(ceil(max(xx))) + 1
            y0, y1 = int(floor(min(yy))) - 1, int(ceil(max(yy))) + 1
            assert x1 > x0
            assert y1 > y0
            bbox.append((x0, x1, y0, y1, 0, 1))

        reflections["bbox"] = bbox

        x0, x1, y0, y1, _, _ = bbox.parts()
        xsize, ysize = self.experiment.detector[0].get_image_size()
        selection = (x1 > 0) & (y1 > 0) & (x0 < xsize) & (y0 < ysize)

        reflections = reflections.select(selection)
        print("Filtered reflecions with bbox outside image range")
        print("Kept %d reflections" % len(reflections))
        return reflections
Ejemplo n.º 28
0
    def step_C(self):
        """
    Determination of screw components.
    """
        print_step("Step C:", self.log)

        if (self.force_t_S is not None):
            self.t_S = self.force_t_S
        else:  # HUGE CLOSE BEGIN
            T_ = self.T_CL.as_sym_mat3()
            self.T_CLxx, self.T_CLyy, self.T_CLzz = T_[0], T_[1], T_[2]
            #
            # Left branch
            #
            if (not (self.is_zero(self.Lxx) or self.is_zero(self.Lyy)
                     or self.is_zero(self.Lzz))):
                tlxx = self.T_CLxx * self.Lxx
                tlyy = self.T_CLyy * self.Lyy
                tlzz = self.T_CLzz * self.Lzz
                t11, t22, t33 = tlxx, tlyy, tlzz  # the rest is below
                rx, ry, rz = math.sqrt(tlxx), math.sqrt(tlyy), math.sqrt(tlzz)
                t12 = self.T_CL[1] * math.sqrt(self.Lxx * self.Lyy)
                t13 = self.T_CL[2] * math.sqrt(self.Lxx * self.Lzz)
                t23 = self.T_CL[5] * math.sqrt(self.Lyy * self.Lzz)
                t_min_C = max(self.Sxx - rx, self.Syy - ry, self.Szz - rz)
                t_max_C = min(self.Sxx + rx, self.Syy + ry, self.Szz + rz)
                show_number(x=[t_min_C, t_max_C],
                            title="t_min_C,t_max_C eq.(24):",
                            log=self.log)
                if (t_min_C > t_max_C):
                    raise Sorry(
                        "Step C (left branch): Empty (tmin_c,tmax_c) interval."
                    )
                # Compute t_S using formula 10 or 11 (from 2016/17 paper II).
                if (self.find_t_S_using_formula == "10"):
                    t_0 = self.S_L.trace() / 3.
                elif (self.find_t_S_using_formula == "11"):
                    num = self.Sxx*self.Lyy**2*self.Lzz**2 +\
                          self.Syy*self.Lzz**2*self.Lxx**2 +\
                          self.Szz*self.Lxx**2*self.Lyy**2
                    den = self.Lyy**2*self.Lzz**2 + \
                          self.Lzz**2*self.Lxx**2 + \
                          self.Lxx**2*self.Lyy**2
                    t_0 = num / den
                else:
                    assert 0
                #
                show_number(x=t_0, title="t_0 eq.(20):", log=self.log)
                # compose T_lambda and find tau_max (30)
                T_lambda = matrix.sqr(
                    [t11, t12, t13, t12, t22, t23, t13, t23, t33])
                show_matrix(x=T_lambda, title="T_lambda eq.(29)", log=self.log)
                es = eigensystem.real_symmetric(T_lambda.as_sym_mat3())
                vals = es.values()  # TODO: am I a dict values method ?
                assert vals[0] >= vals[1] >= vals[2]
                tau_max = vals[0]
                #
                if (tau_max < 0):
                    raise Sorry("Step C (left branch): Eq.(32): tau_max<0.")
                t_min_tau = max(self.Sxx, self.Syy,
                                self.Szz) - math.sqrt(tau_max)
                t_max_tau = min(self.Sxx, self.Syy,
                                self.Szz) + math.sqrt(tau_max)
                show_number(x=[t_min_tau, t_max_tau],
                            title="t_min_tau, t_max_tau eq.(31):",
                            log=self.log)
                if (t_min_tau > t_max_tau):
                    raise Sorry(
                        "Step C (left branch): Empty (tmin_t,tmax_t) interval."
                    )
                # (38):
                arg = t_0**2 + (t11 + t22 + t33) / 3. - (
                    self.Sxx**2 + self.Syy**2 + self.Szz**2) / 3.
                if (arg < 0):
                    raise Sorry(
                        "Step C (left branch): Negative argument when estimating tmin_a."
                    )
                t_a = math.sqrt(arg)
                show_number(x=t_a, title="t_a eq.(38):", log=self.log)
                t_min_a = t_0 - t_a
                t_max_a = t_0 + t_a
                show_number(x=[t_min_a, t_max_a],
                            title="t_min_a, t_max_a eq.(37):",
                            log=self.log)
                # compute t_min, t_max - this is step b)
                t_min = max(t_min_C, t_min_tau, t_min_a)
                t_max = min(t_max_C, t_max_tau, t_max_a)
                if (t_min > t_max):
                    raise Sorry(
                        "Step C (left branch): Intersection of the intervals for t_S is empty."
                    )
                elif (self.is_zero(t_min - t_max)):
                    _, b_s, c_s = self.as_bs_cs(t=t_min,
                                                txx=t11,
                                                tyy=t22,
                                                tzz=t33,
                                                txy=t12,
                                                tyz=t23,
                                                tzx=t13)
                    if ((self.is_zero(b_s) or bs > 0)
                            and (c_s < 0 or self.is_zero(c_s))):
                        self.t_S = t_min
                    else:
                        raise Sorry(
                            "Step C (left branch): t_min=t_max gives non positive semidefinite V_lambda."
                        )
                elif (t_min < t_max):
                    step = (t_max - t_min) / 100000.
                    target = 1.e+9
                    t_S_best = t_min
                    while t_S_best <= t_max:
                        _, b_s, c_s = self.as_bs_cs(t=t_S_best,
                                                    txx=t11,
                                                    tyy=t22,
                                                    tzz=t33,
                                                    txy=t12,
                                                    tyz=t23,
                                                    tzx=t13)
                        if (b_s >= 0 and c_s <= 0):
                            target_ = abs(t_0 - t_S_best)
                            if (target_ < target):
                                target = target_
                                self.t_S = t_S_best
                        t_S_best += step
                    assert self.t_S <= t_max
                    if (self.t_S is None):
                        raise Sorry(
                            "Step C (left branch): Interval (t_min,t_max) has no t giving positive semidefinite V."
                        )
                    self.t_S = self.t_S
            #
            # Right branch, Section 4.4
            #
            else:
                Lxx, Lyy, Lzz = self.Lxx, self.Lyy, self.Lzz
                if (self.is_zero(self.Lxx)): Lxx = 0
                if (self.is_zero(self.Lyy)): Lyy = 0
                if (self.is_zero(self.Lzz)): Lzz = 0
                tlxx = self.T_CLxx * Lxx
                tlyy = self.T_CLyy * Lyy
                tlzz = self.T_CLzz * Lzz
                t11, t22, t33 = tlxx, tlyy, tlzz  # the rest is below
                rx, ry, rz = math.sqrt(tlxx), math.sqrt(tlyy), math.sqrt(tlzz)
                t12 = self.T_CL[1] * math.sqrt(Lxx * Lyy)
                t13 = self.T_CL[2] * math.sqrt(Lxx * Lzz)
                t23 = self.T_CL[5] * math.sqrt(Lyy * Lzz)

                # helper-function to check Cauchy conditions
                def cauchy_conditions(i, j, k,
                                      tSs):  # diagonals: 0,4,8; 4,0,8; 8,0,4
                    if (self.is_zero(self.L_L[i])):
                        t_S = self.S_L[i]
                        cp1 = (self.S_L[j] -
                               t_S)**2 - self.T_CL[j] * self.L_L[j]
                        cp2 = (self.S_L[k] -
                               t_S)**2 - self.T_CL[k] * self.L_L[k]
                        if (not ((cp1 < 0 or self.is_zero(cp1)) and
                                 (cp2 < 0 or self.is_zero(cp2)))):
                            raise Sorry(
                                "Step C (right branch): Cauchy condition failed (23)."
                            )
                        a_s, b_s, c_s = self.as_bs_cs(t=t_S,
                                                      txx=t11,
                                                      tyy=t22,
                                                      tzz=t33,
                                                      txy=t12,
                                                      tyz=t23,
                                                      tzx=t13)
                        self.check_33_34_35(a_s=a_s, b_s=b_s, c_s=c_s)
                        tSs.append(t_S)

                #
                tSs = []
                cauchy_conditions(i=0, j=4, k=8, tSs=tSs)
                cauchy_conditions(i=4, j=0, k=8, tSs=tSs)
                cauchy_conditions(i=8, j=0, k=4, tSs=tSs)
                if (len(tSs) == 1): self.t_S = tSs[0]
                elif (len(tSs) == 0): raise RuntimeError
                else:
                    self.t_S = tSs[0]
                    for tSs_ in tSs[1:]:
                        if (not self.is_zero(x=self.t_S - tSs_)):
                            assert 0
            # end-of-procedure check, then truncate
            if (self.t_S is None):
                raise RuntimeError
        # HUGE CLOSE END
        ####
        #
        # At this point t_S is found or procedure terminated earlier.
        #
        show_number(x=self.t_S, title="t_S:", log=self.log)
        # compute S_C(t_S_), (19)
        self.S_C = self.S_L - matrix.sqr(
            [self.t_S, 0, 0, 0, self.t_S, 0, 0, 0, self.t_S])
        self.S_C = matrix.sqr(self.S_C)
        show_matrix(x=self.S_C, title="S_C, (26)", log=self.log)
        # find sx, sy, sz
        if (self.is_zero(self.Lxx)):
            if (not self.is_zero(self.S_C[0])):
                raise Sorry("Step C: incompatible L_L and S_C matrices.")
        else:
            self.sx = self.S_C[0] / self.Lxx
        if (self.is_zero(self.Lyy)):
            if (not self.is_zero(self.S_C[4])):
                raise Sorry("Step C: incompatible L_L and S_C matrices.")
        else:
            self.sy = self.S_C[4] / self.Lyy
        if (self.is_zero(self.Lzz)):
            if (not self.is_zero(self.S_C[8])):
                raise Sorry("Step C: incompatible L_L and S_C matrices.")
        else:
            self.sz = self.S_C[8] / self.Lzz
        show_number(x=[self.sx, self.sy, self.sz],
                    title="Screw parameters (section 4.5): sx,sy,sz:",
                    log=self.log)
        # compose C_L_t_S (26), and V_L (27)
        self.C_L_t_S = matrix.sqr([
            self.sx * self.S_C[0], 0, 0, 0, self.sy * self.S_C[4], 0, 0, 0,
            self.sz * self.S_C[8]
        ])
        self.C_L_t_S = self.C_L_t_S
        show_matrix(x=self.C_L_t_S, title="C_L(t_S) (26)", log=self.log)
        self.V_L = matrix.sqr(self.T_CL - self.C_L_t_S)
        show_matrix(x=self.V_L, title="V_L (26-27)", log=self.log)
        if (not self.is_pd(self.V_L.as_sym_mat3())):
            raise Sorry("Step C: Matrix V[L] is not positive semidefinite.")
def top_quaternion(p):

  eigen = eigensystem.real_symmetric( p.as_flex_double_matrix() )
  return eigen.vectors()[0:4]
Ejemplo n.º 30
0
  def exercise_floating_origin_restraints(self):
    n = self.n_independent_params
    eps_zero_rhs = 1e-6
    connectivity_table = smtbx.utils.connectivity_table(self.xray_structure)
    reparametrisation = constraints.reparametrisation(
      structure=self.xray_structure,
      constraints=[],
      connectivity_table=connectivity_table)
    obs = self.fo_sq.as_xray_observations()
    ls = least_squares.crystallographic_ls(
      obs, reparametrisation,
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=oop.null())
    ls.build_up()
    unrestrained_normal_matrix = ls.normal_matrix_packed_u()
    assert len(unrestrained_normal_matrix) == n*(n+1)//2
    ev = eigensystem.real_symmetric(
      unrestrained_normal_matrix.matrix_packed_u_as_symmetric())
    unrestrained_eigenval = ev.values()
    unrestrained_eigenvec = ev.vectors()

    ls = least_squares.crystallographic_ls(
      obs,
      reparametrisation,
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=
      origin_fixing_restraints.homogeneous_weighting)
    ls.build_up()

    # Let's check that the computed singular directions span the same
    # space as the expected ones
    singular_test = flex.double()
    jac = ls.reparametrisation.jacobian_transpose_matching_grad_fc()
    m = 0
    for s in ls.origin_fixing_restraint.singular_directions:
      assert s.norm() != 0
      singular_test.extend(jac*s)
      m += 1
    for s in self.continuous_origin_shift_basis:
      singular_test.extend(flex.double(s))
      m += 1
    singular_test.reshape(flex.grid(m, n))
    assert self.rank(singular_test) == len(self.continuous_origin_shift_basis)

    assert ls.opposite_of_gradient()\
             .all_approx_equal(0, eps_zero_rhs),\
           list(ls.gradient())
    restrained_normal_matrix = ls.normal_matrix_packed_u()
    assert len(restrained_normal_matrix) == n*(n+1)//2
    ev = eigensystem.real_symmetric(
      restrained_normal_matrix.matrix_packed_u_as_symmetric())
    restrained_eigenval = ev.values()
    restrained_eigenvec = ev.vectors()

    # The eigendecomposition of the normal matrix
    # for the unrestrained problem is:
    #    A = sum_{0 <= i < n-p-1} lambda_i v_i^T v_i
    # where the eigenvalues lambda_i are sorted in decreasing order
    # and p is the dimension of the continous origin shift space.
    # In particular A v_i = 0, n-p <= i < n.
    # In the restrained case, it becomes:
    #    A' = A + sum_{n-p <= i < n} mu v_i^T v_i

    p = len(self.continuous_origin_shift_basis)
    assert approx_equal(restrained_eigenval[p:], unrestrained_eigenval[:-p],
                        eps=1e-12)
    assert unrestrained_eigenval[-p]/unrestrained_eigenval[-p-1] < 1e-12

    if p > 1:
      # eigenvectors are stored by rows
      unrestrained_null_space = unrestrained_eigenvec.matrix_copy_block(
        i_row=n-p, i_column=0,
        n_rows=p, n_columns=n)
      assert self.rank(unrestrained_null_space) == p

      restrained_space = restrained_eigenvec.matrix_copy_block(
        i_row=0, i_column=0,
        n_rows=p, n_columns=n)
      assert self.rank(restrained_space) == p

      singular = flex.double(
        self.continuous_origin_shift_basis)
      assert self.rank(singular) == p

      rank_finder = flex.double(n*3*p)
      rank_finder.resize(flex.grid(3*p, n))
      rank_finder.matrix_paste_block_in_place(unrestrained_null_space,
                                              i_row=0, i_column=0)
      rank_finder.matrix_paste_block_in_place(restrained_space,
                                              i_row=p, i_column=0)
      rank_finder.matrix_paste_block_in_place(singular,
                                              i_row=2*p, i_column=0)
      assert self.rank(rank_finder) == p
    else:
      # this branch handles the case p=1
      # it's necessary to work around a bug in the svd module
      # ( nx1 matrices crashes the code )
      assert approx_equal(
        restrained_eigenvec[0:n].angle(
          unrestrained_eigenvec[-n:]) % math.pi, 0)
      assert approx_equal(
        unrestrained_eigenvec[-n:].angle(
          flex.double(self.continuous_origin_shift_basis[0])) % math.pi, 0)

    # Do the floating origin restraints prevent the structure from floating?
    xs = self.xray_structure.deep_copy_scatterers()
    ls = least_squares.crystallographic_ls(
      obs,
      reparametrisation,
      weighting_scheme=least_squares.unit_weighting(),
      origin_fixing_restraints_type=
      origin_fixing_restraints.atomic_number_weighting
    )
    barycentre_0 = xs.sites_frac().mean()
    while 1:
      xs.shake_sites_in_place(rms_difference=0.15)
      xs.apply_symmetry_sites()
      barycentre_1 = xs.sites_frac().mean()
      delta = matrix.col(barycentre_1) - matrix.col(barycentre_0)
      moved_far_enough = 0
      for singular in self.continuous_origin_shift_basis:
        e = matrix.col(singular[:3])
        if not approx_equal(delta.dot(e), 0, eps=0.01, out=None):
          moved_far_enough += 1
      if moved_far_enough: break

    # one refinement cycle
    ls.build_up()
    ls.solve()
    shifts = ls.step()

    # That's what floating origin restraints are for!
    # Note that in the presence of special position, that's different
    # from the barycentre not moving along the continuous shift directions.
    # TODO: typeset notes about that subtlety.
    for singular in self.continuous_origin_shift_basis:
      assert approx_equal(shifts.dot(flex.double(singular)), 0, eps=1e-12)
Ejemplo n.º 31
0
  def __init__(self,
               pdb_hierarchy,
               chain_id_light='L',
               chain_id_heavy='H',
               limit_light=107,
               limit_heavy=113):
    '''
    Get elbow angle for Fragment antigen-binding (Fab)

    - Default heavy and light chains IDs are: H : heavy,  L : light
    - Default limit (cutoff) between variable and constant parts
      are residue number 107/113 for light/heavy chains
    - Variable domain is from residue 1 to limit.
      Constant domain form limit+1 to end.

    Reference:
    ----------
    Stanfield, et al., JMB 2006

    Usage example:
    --------------
    >>>fab = fab_elbow_angle(pdb_hierarchy=ph,limit_light=114,limit_heavy=118)
    >>>fab_angle = fab.fab_elbow_angle
    '''
    # create selection strings for the heavy/light var/const part of chains
    self.select_str(
      chain_ID_H=chain_id_heavy,
      limit_H=limit_heavy,
      chain_ID_L=chain_id_light,
      limit_L=limit_light)
    # get the hierarchy for and divide using selection strings
    self.pdb_hierarchy = pdb_hierarchy
    self.get_pdb_chains()
    # Get heavy to light reference vector before alignment !!!
    vh_end = self.pdb_var_H.atoms()[-1].xyz
    vl_end = self.pdb_var_L.atoms()[-1].xyz
    mid_H_to_L = self.norm_vec(start=vh_end,end=vl_end)
    # Get transformations objects
    tranformation_const= self.get_transformation(
      fixed_selection=self.pdb_const_H,
      moving_selection=self.pdb_const_L)
    tranformation_var = self.get_transformation(
      fixed_selection=self.pdb_var_H,
      moving_selection=self.pdb_var_L)
    # Get the angle and eigenvalues
    eigen_const = eigensystem.real_symmetric(tranformation_const.r.as_sym_mat3())
    eigen_var = eigensystem.real_symmetric(tranformation_var.r.as_sym_mat3())
    # c : consttant, v : variable
    eigenvectors_c = self.get_eigenvector(eigen_const)
    eigenvectors_v = self.get_eigenvector(eigen_var)
    # test eignevectors pointing in oposite directions
    if eigenvectors_c.dot(eigenvectors_v) > 0:
      eigenvectors_v = - eigenvectors_v
    # Calc Feb elbow angle
    angle = self.get_angle(vec1=eigenvectors_c, vec2=eigenvectors_v)
    # Test if elbow angle larger or smaller than 180
    zaxis = self.cross_product_as_unit_axis(eigenvectors_v, eigenvectors_c)
    xaxis = self.cross_product_as_unit_axis(eigenvectors_c, zaxis)
    if mid_H_to_L.dot(zaxis) <= 0:
        angle = 360 - angle
    self.fab_elbow_angle = angle
    # The cosine of the angles the vector from limit_heavy to limit_light
    # make with the axes x, y (eigenvectors_c), z
    # where the eigenvectors_v lies in the plane x - y
    self.cos_H_to_L_with_xaxis = mid_H_to_L.dot(xaxis)
    self.cos_H_to_L_with_yaxis = mid_H_to_L.dot(eigenvectors_c)
    self.cos_H_to_L_with_zaxis = mid_H_to_L.dot(zaxis)
Ejemplo n.º 32
0
  def __init__(self,
               pdb_hierarchy,
               chain_ID_light='L',
               chain_ID_heavy='H',
               limit_light=107,
               limit_heavy=113):
    '''
    Get elbow angle for Fragment antigen-binding (Fab)

    - Default heavy and light chains IDs are: H : heavy,  L : light
    - Default limit (cutoff) between variable and constant parts
      is residue number 107/113 for light/heavy chains
    - Variable domain si from residue 1 to limit.
      Constant domain form limit+1 to end.
    - Method of calculating angle is based on Stanfield, et al., JMB 2006

    Argument:
    ---------
    pdb_file_name : 4 characters string, a PDB name
    chain_ID_heavy : The heavy protion of the protein, chain ID
    chain_ID_light : The light protion of the protein, chain ID
    limit_heavy : the number of the cutoff residue, between
                  the variable and constant portions in the heavy chian
    limit_light : the number of the cutoff residue, between
                  the variable and constant portions in the light chian

    Main attributes:
    ----------------
    self.fab_elbow_angle : the elbow angle calculated as the dot product of
                           the VL-VH pseudodyade axie and the CL-CH
                           pseudodyade axie

    Test program at:
    cctbx_project\mmtbx\regression\tst_fab_elbow_angle.py

    Example:
    --------
    >>>fab = fab_elbow_angle(
         pdb_file_name='1bbd',
         chain_ID_light='L',
         chain_ID_heavy='H',
         limit_light=114,
         limit_heavy=118)
    >>> print fab.fab_elbow_angle
    133
    >>>fab = fab_elbow_angle(pdb_file_name='1bbd')
    >>> print fab.fab_elbow_angle
    126 (127 in Stanfield, et al., JMB 2006)

    @author Youval Dar (LBL 2014)
    '''
    # create selection strings for the heavy/light var/const part of chains
    self.select_str(
      chain_ID_H=chain_ID_heavy,
      limit_H=limit_heavy,
      chain_ID_L=chain_ID_light,
      limit_L=limit_light)
    # get the hirarchy for and divide using selection strings
    self.pdb_hierarchy = pdb_hierarchy
    self.get_pdb_chains()
    # Get heavy to light reference vector before alignment !!!
    vh_end = self.pdb_var_H.atoms()[-1].xyz
    vl_end = self.pdb_var_L.atoms()[-1].xyz
    mid_H_to_L = self.norm_vec(start=vh_end,end=vl_end)
    #mid_H_to_L = self.H_to_L_vec()

    # Get transformations objects
    tranformation_const= self.get_transformation(
      fixed_selection=self.pdb_const_H,
      moving_selection=self.pdb_const_L)
    tranformation_var = self.get_transformation(
      fixed_selection=self.pdb_var_H,
      moving_selection=self.pdb_var_L)
    # Get the angle and eigenvalues
    eigen_const = eigensystem.real_symmetric(tranformation_const.r.as_sym_mat3())
    eigen_var = eigensystem.real_symmetric(tranformation_var.r.as_sym_mat3())
    # c : consttant, v : variable
    eigenvectors_c = self.get_eigenvector(eigen_const)
    eigenvectors_v = self.get_eigenvector(eigen_var)

    # c: res 171    v: res 44
    c = 20*eigenvectors_c + flex.double(self.pdb_const_H.atoms()[135].xyz)
    v = 20*eigenvectors_v + flex.double(self.pdb_var_H.atoms()[130].xyz)
    r = 20*mid_H_to_L + flex.double(self.pdb_var_H.atoms()[-1].xyz)
    rs = flex.double(self.pdb_var_H.atoms()[-1].xyz)
    re = flex.double(self.pdb_var_L.atoms()[-1].xyz)
    print
    print('c')
    print list(flex.double(self.pdb_const_H.atoms()[135].xyz))
    print list(c)
    print 'v'
    print list(flex.double(self.pdb_var_H.atoms()[130].xyz))
    print list(v)
    print 'r'
    print list(flex.double(self.pdb_var_H.atoms()[-1].xyz))
    print list(r)
    print 'f'
    print self.pdb_var_H.atoms()[-1].id_str()
    print list(rs)
    print self.pdb_var_L.atoms()[-1].id_str()
    print list(re)



    #


    # test eignevectors pointing in oposite directions
    if eigenvectors_c.dot(eigenvectors_v) > 0:
      print 'reversing direction of variable rotation eigenvector!!!!'
      eigenvectors_v = - eigenvectors_v
    # Calc Feb elbow angle
    angle = self.get_angle(vec1=eigenvectors_c, vec2=eigenvectors_v)
    # Test if elbow angle larger or smaller than 180
    zaxis = self.cross(eigenvectors_v, eigenvectors_c)
    xaxis = self.cross(eigenvectors_c,zaxis)

    x = 20*xaxis + flex.double(self.pdb_const_H.atoms()[135].xyz)
    print 'x'
    print list(flex.double(self.pdb_const_H.atoms()[135].xyz))
    print list(x)

    print mid_H_to_L.dot(xaxis)
    print mid_H_to_L.dot(zaxis)

    #m = matrix.sqr(list(xaxis)+list(eigenvectors_c)+list(zaxis))
    #A = m.transpose()
    #Ainv = A.inverse(0
    # choose ref axis
    ref_axis = zaxis
    #if abs(mid_H_to_L.dot(xaxis)) > abs(mid_H_to_L.dot(zaxis)):
      #ref_axis = xaxis
    if mid_H_to_L.dot(ref_axis) < 0:
      angle = 360 - angle
    self.fab_elbow_angle = angle
Ejemplo n.º 33
0
 def is_pd(self, m):
     es = eigensystem.real_symmetric(deepcopy(m))
     r = flex.min(es.values())
     if (r > 0 or self.is_zero(r)): return True
     else: return False
Ejemplo n.º 34
0
 def eigen_system_default_handler(self, m):
   es = eigensystem.real_symmetric(m.as_sym_mat3())
   vals, vecs = es.values(), es.vectors()
   print >> self.log, "  eigen values :", " ".join([self.ff%i for i in vals])
   print >> self.log, "  eigen vectors:", " ".join([self.ff%i for i in vecs])
   assert vals[0]>=vals[1]>=vals[2]
   # case 1: all different
   if(abs(vals[0]-vals[1])>=self.eps and
      abs(vals[1]-vals[2])>=self.eps and
      abs(vals[0]-vals[2])>=self.eps):
     l_1 = matrix.col((vecs[0], vecs[1], vecs[2]))
     l_2 = matrix.col((vecs[3], vecs[4], vecs[5]))
     l_3 = matrix.col((vecs[6], vecs[7], vecs[8]))
     l_x, l_y, l_z = l_3, l_2, l_1
     vals = [vals[2], vals[1], vals[0]]
     print >> self.log, "re-assign: x, y, z = 3, 2, 1"
     tmp = l_x.cross(l_y) - l_z
     if(abs(tmp[0])>self.eps or abs(tmp[1])>self.eps or abs(tmp[2])>self.eps):
       print >> self.log, "  convert to right-handed"
       l_z = -1. * l_z
   # case 2: all three coincide
   elif(abs(vals[0]-vals[1])<self.eps and
        abs(vals[1]-vals[2])<self.eps and
        abs(vals[0]-vals[2])<self.eps):
     l_x = matrix.col((1, 0, 0))
     l_y = matrix.col((0, 1, 0))
     l_z = matrix.col((0, 0, 1))
   elif([abs(vals[0]-vals[1])<self.eps,
         abs(vals[1]-vals[2])<self.eps,
         abs(vals[0]-vals[2])<self.eps].count(True)==1):
     l_x = matrix.col((1, 0, 0))
     l_y = matrix.col((0, 1, 0))
     l_z = matrix.col((0, 0, 1))
     #print "LOOK"
     #l_1 = matrix.col((vecs[0], vecs[1], vecs[2]))
     #l_2 = matrix.col((vecs[3], vecs[4], vecs[5]))
     #l_3 = matrix.col((vecs[6], vecs[7], vecs[8]))
     #l_x, l_y, l_z = l_3, l_2, l_1
     ##
     #from scitbx.array_family import flex
     #tmp = flex.double([l_z[0], l_z[1], l_z[2]])
     #ma = flex.min(flex.abs(tmp))
     #zz = 999
     #ib = None
     #for i in xrange(3):
     #  zz_ = abs(l_z[i]-ma)
     #  if(zz_<zz):
     #    zz = zz_
     #    ib = i
     #l_y =  matrix.col((l_z[0], l_z[1], l_z[2]))
     #l_y = [l_y[0], l_y[1], l_y[2]]
     #l_y[ib]=0
     #l_y = matrix.col(l_y)
     #l_y = l_y/math.sqrt(l_y[0]**2+l_y[1]**2+l_y[2]**2)
     #l_x = l_y.cross(l_z)
   #
   print >> self.log, "  eigen values :", " ".join([self.ff%i for i in vals])
   print >> self.log, "  eigen vectors:"
   self.show_vector(x=l_x, title="vector x")
   self.show_vector(x=l_y, title="vector y")
   self.show_vector(x=l_z, title="vector z")
   return group_args(x=l_x, y=l_y, z=l_z, vals=vals)
Ejemplo n.º 35
0
def exercise_eigensystem():
  s = eigensystem.real_symmetric(
    m=flex.double(flex.grid(0,0)),
    relative_epsilon=1e-6,
    absolute_epsilon=1e-6)
  s.values().all() == (0,)
  assert s.vectors().all() == (0,0)
  u = s.generalized_inverse_as_packed_u()
  assert u.all() == (0,)
  m = u.matrix_packed_u_as_symmetric()
  assert m.all() == (0,0)
  #
  for n in xrange(1,10):
    m = flex.double(flex.grid(n,n))
    s = eigensystem.real_symmetric(m)
    assert approx_equal(tuple(s.values()), [0]*n)
    v = s.vectors()
    for i in xrange(n):
      for j in xrange(n):
        x = 0
        if (i == j): x = 1
        assert approx_equal(v[(i,j)], x)
    v = []
    for i in xrange(n):
      j = (i*13+17) % n
      v.append(j)
      m[i*(n+1)] = j
    s = eigensystem.real_symmetric(m)
    if (n == 3):
      ss = eigensystem.real_symmetric((m[0],m[4],m[8],m[1],m[2],m[5]))
      assert approx_equal(s.values(), ss.values())
      assert approx_equal(s.vectors(), ss.vectors())
    v.sort()
    v.reverse()
    assert approx_equal(s.values(), v)
    if (n > 1):
      assert approx_equal(flex.min(s.vectors()), 0)
    assert approx_equal(flex.max(s.vectors()), 1)
    assert approx_equal(flex.sum(s.vectors()), n)
    for t in xrange(10):
      for i in xrange(n):
        for j in xrange(i,n):
          m[i*n+j] = random.random() - 0.5
          if (i != j):
            m[j*n+i] = m[i*n+j]
      s = eigensystem.real_symmetric(m)
      if (n == 3):
        ss = eigensystem.real_symmetric((m[0],m[4],m[8],m[1],m[2],m[5]))
        assert approx_equal(s.values(), ss.values())
        assert approx_equal(s.vectors(), ss.vectors())
      v = list(s.values())
      v.sort()
      v.reverse()
      assert list(s.values()) == v
      for i in xrange(n):
        l = s.values()[i]
        x = s.vectors()[i*n:i*n+n]
        mx = matrix_mul(m, n, n, x, n, 1)
        lx = [e*l for e in x]
        assert approx_equal(mx, lx)
  #
  m = (1.4573362052597449, 1.7361052947659894, 2.8065584999742659,
       -0.5387293498219814, -0.018204949672480729, 0.44956507395617257)
  n_repetitions = 10000
  t0 = time.time()
  v = time_eigensystem_real_symmetric(m, n_repetitions)
  assert v == (0,0,0)
  print "time_eigensystem_real_symmetric: %.3f micro seconds" % (
    (time.time() - t0)/n_repetitions*1.e6)
  from scitbx.linalg import time_lapack_dsyev
  for use_fortran in [False, True]:
    if (not use_fortran):
      if (not scitbx.linalg.fem_is_available()): continue
      impl_id = "fem"
    else:
      if (not scitbx.linalg.for_is_available()): continue
      impl_id = "for"
    v = time_lapack_dsyev(m, 2, use_fortran)
      # to trigger one-time initialization of SAVE variables
    t0 = time.time()
    v = time_lapack_dsyev(m, n_repetitions, use_fortran)
    assert v == (0,0,0)
    print "time_lapack_dsyev %s: %.3f micro seconds" % (
      impl_id, (time.time() - t0)/n_repetitions*1.e6)
  #
  s = eigensystem.real_symmetric(m=m)
  assert s.min_abs_pivot() > 0
  assert s.min_abs_pivot() < 1.e-10
  assert approx_equal(s.generalized_inverse_as_packed_u(), [
    0.77839538602575065, 0.25063185439711611, -0.03509803174624003,
    0.68162798233326816, -0.10755998636596431, 0.37330996497431423])
  s = eigensystem.real_symmetric(m=m, absolute_epsilon=10)
  assert s.min_abs_pivot() == 10
  assert approx_equal(s.vectors(), [0, 0, 1, 0, 1, 0, 1, 0, 0])
  assert approx_equal(s.values(),
    [2.8065584999742659, 1.7361052947659894, 1.4573362052597449])
  s = eigensystem.real_symmetric(m=m, relative_epsilon=0)
  assert s.min_abs_pivot() == 0
  assert approx_equal(s.values(), [3,2,1])
Ejemplo n.º 36
0
    def __init__(self,
                 miller_array,
                 n_residues=None,
                 n_bases=None,
                 asu_contents=None,
                 prot_frac=1.0,
                 nuc_frac=0.0):
        """ Maximum likelihood anisotropic wilson scaling"""
        #Checking input
        if (n_residues is None):
            if (n_bases is None):
                assert asu_contents is not None
                assert (type(asu_contents) == type({}))
        if asu_contents is None:
            assert ((n_residues is not None) or (n_bases is not None))
        assert (prot_frac + nuc_frac <= 1.0)
        assert (miller_array.is_real_array())

        self.info = miller_array.info()
        if (miller_array.is_xray_intensity_array()):
            miller_array = miller_array.f_sq_as_f()

        work_array = miller_array.resolution_filter(
            d_max=1.0 / math.sqrt(scaling.get_d_star_sq_low_limit()),
            d_min=1.0 / math.sqrt(scaling.get_d_star_sq_high_limit()))
        work_array = work_array.select(work_array.data() > 0)
        self.d_star_sq = work_array.d_star_sq().data()
        self.scat_info = None
        if asu_contents is None:
            self.scat_info = scattering_information(n_residues=n_residues,
                                                    n_bases=n_bases)
        else:
            self.scat_info = scattering_information(asu_contents=asu_contents,
                                                    fraction_protein=prot_frac,
                                                    fraction_nucleic=nuc_frac)
        self.scat_info.scat_data(self.d_star_sq)
        self.b_cart = None
        if (work_array.size() > 0):
            self.hkl = work_array.indices()
            self.f_obs = work_array.data()
            self.unit_cell = uctbx.unit_cell(
                miller_array.unit_cell().parameters())
            ## Make sure sigma's are used when available
            if (work_array.sigmas() is not None):
                self.sigma_f_obs = work_array.sigmas()
            else:
                self.sigma_f_obs = flex.double(self.f_obs.size(), 0.0)
            if (flex.min(self.sigma_f_obs) < 0):
                self.sigma_f_obs = self.sigma_f_obs * 0.0

            ## multiplicities
            self.epsilon = work_array.epsilons().data().as_double()
            ## Determine Wilson parameters
            self.gamma_prot = self.scat_info.gamma_tot
            self.sigma_prot_sq = self.scat_info.sigma_tot_sq
            ## centric flags
            self.centric = flex.bool(work_array.centric_flags().data())
            ## Symmetry stuff
            self.sg = work_array.space_group()
            self.adp_constraints = self.sg.adp_constraints()
            self.dim_u = self.adp_constraints.n_independent_params()
            ## Setup number of parameters
            assert self.dim_u <= 6
            ## Optimisation stuff
            self.x = flex.double(self.dim_u + 1,
                                 0.0)  ## B-values and scale factor!
            exception_handling_params = scitbx.lbfgs.exception_handling_parameters(
                ignore_line_search_failed_step_at_lower_bound=False,
                ignore_line_search_failed_step_at_upper_bound=False,
                ignore_line_search_failed_maxfev=False)
            term_parameters = scitbx.lbfgs.termination_parameters(
                max_iterations=50)

            minimizer = scitbx.lbfgs.run(
                target_evaluator=self,
                termination_params=term_parameters,
                exception_handling_params=exception_handling_params)

            ## Done refining
            Vrwgk = math.pow(self.unit_cell.volume(), 2.0 / 3.0)
            self.p_scale = self.x[0]
            self.u_star = self.unpack()
            self.u_star = list(flex.double(self.u_star) / Vrwgk)
            self.b_cart = adptbx.u_as_b(
                adptbx.u_star_as_u_cart(self.unit_cell, self.u_star))
            self.u_cif = adptbx.u_star_as_u_cif(self.unit_cell, self.u_star)
            #get eigenvalues of B-cart
            eigen = eigensystem.real_symmetric(self.b_cart)
            self.eigen_values = eigen.values()
            self.eigen_vectors = eigen.vectors()

            self.work_array = work_array  # i need this for further analyses
            self.analyze_aniso_correction()
            # FIXME see 3ihm:IOBS4,SIGIOBS4
            if (self.eigen_values[0] != 0):
                self.anirat = (
                    abs(self.eigen_values[0] - self.eigen_values[2]) /
                    self.eigen_values[0])
            else:
                self.anirat = None

            del self.x
            del self.f_obs
            del self.sigma_f_obs
            del self.epsilon
            del self.gamma_prot
            del self.sigma_prot_sq
            del self.centric
            del self.hkl
            del self.d_star_sq
            del self.adp_constraints