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
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))
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
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)
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)
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()
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
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)]
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)
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)
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)
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()
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)
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)
# 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());
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
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)
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)
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
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)
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])
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
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
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]
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)
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)
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
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
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)
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])
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