def test_rotaion_translation_input(self): """ Verify correct processing """ r1 = matrix.sqr([-0.955168,0.257340,-0.146391, 0.248227,0.426599,-0.869711, -0.161362,-0.867058,-0.471352]) r2 = matrix.sqr([-0.994267,-0.046533,-0.096268, -0.065414,-0.447478,0.89189, -0.084580,0.893083,0.441869]) t1 = matrix.col([167.54320,-4.09250,41.98070]) t2 = matrix.col([176.73730,27.41760,-5.85930]) trans_obj = ncs.input( hierarchy=iotbx.pdb.input(source_info=None, lines=pdb_str2).construct_hierarchy(), rotations=[r1,r2], translations=[t1,t2]) nrg = trans_obj.get_ncs_restraints_group_list()[0] self.assertEqual(list(nrg.master_iselection),[0, 1, 2, 3, 4, 5, 6, 7, 8]) c1 = nrg.copies[0] self.assertEqual(list(c1.iselection),[9,10,11,12,13,14,15,16,17]) c2 = nrg.copies[1] self.assertEqual(list(c2.iselection),[18,19,20,21,22,23,24,25,26]) # self.assertEqual(r1,c1.r) self.assertEqual(r2,c2.r) self.assertEqual(t1,c1.t) self.assertEqual(t2,c2.t)
def get_detector_2theta (self) : from scitbx.matrix import col n = col(self._raw.get_detector()[0].get_normal()) s0 = col(self._raw.get_beam().get_unit_s0()) return s0.angle(n, deg=False)
def exercise_similarity(): model_1 = crystal_model(real_space_a=(10,0,0), real_space_b=(0,11,0), real_space_c=(0,0,12), space_group_symbol="P 1", mosaicity=0.5) model_2 = crystal_model(real_space_a=(10,0,0), real_space_b=(0,11,0), real_space_c=(0,0,12), space_group_symbol="P 1", mosaicity=0.5) assert model_1.is_similar_to(model_2) # mosaicity tests model_1.set_mosaicity(-1) model_2.set_mosaicity(-0.5) assert model_1.is_similar_to(model_2) # test ignores negative mosaicity model_1.set_mosaicity(0.5) model_2.set_mosaicity(0.63) # outside tolerance assert not model_1.is_similar_to(model_2) model_2.set_mosaicity(0.625) #just inside tolerance assert model_1.is_similar_to(model_2) # orientation tests R = model_2.get_U() dr1 = matrix.col((1, 0, 0)).axis_and_angle_as_r3_rotation_matrix(0.0101, deg=True) dr2 = matrix.col((1, 0, 0)).axis_and_angle_as_r3_rotation_matrix(0.0099, deg=True) model_2.set_U(dr1 * R) assert not model_1.is_similar_to(model_2) # outside tolerance model_2.set_U(dr2 * R) assert model_1.is_similar_to(model_2) # inside tolerance # unit_cell.is_similar_to is tested elsewhere return
def reeke_model_for_use_case(phi_beg, phi_end, margin): """Construct a reeke_model for the geometry of the Use Case Thaumatin dataset, taken from the XDS XPARM. The values are hard- coded here so that this module does not rely on the location of that file.""" axis = matrix.col([0.0, 1.0, 0.0]) # original (unrotated) setting ub = matrix.sqr( [ -0.0133393674072, -0.00541609051856, -0.00367748834997, 0.00989309470346, 0.000574825936669, -0.0054505379664, 0.00475395109417, -0.0163935257377, 0.00102384915696, ] ) r_beg = matrix.sqr(scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=self._axis, angle=phi_beg, deg=True)) r_osc = matrix.sqr( scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=self._axis, angle=(phi_end - phi_beg), deg=True) ) ub_beg = r_beg * ub ub_end = self._r_osc * ub_mid s0 = matrix.col([0.00237878589035, 1.55544539299e-16, -1.09015329696]) dmin = 1.20117776325 return reeke_model(ub_beg, ub_end, axis, s0, dmin, margin)
def _bipyramid(base): """ Returns ------- list of scitbx.matrix.col """ return _concatenate(base, col([0, 0, 1]), col([0, 0, -1]))
def radial_transverse_analysis(self): # very time consuming; should be recoded (C++?) SIGN = -1. PIXEL_SZ = 0.11 # mm/pixel zunit = col([0.,0.,1.]) self.frame_del_radial = {} self.frame_del_azimuthal = {} for x in xrange(len(self.frame_id)): frame_id = self.frame_id[x] frame_param_no = self.frame_id_to_param_no[frame_id] if frame_param_no >= self.n_refined_frames: continue if not self.frame_del_radial.has_key(frame_id): self.frame_del_radial[frame_id] = flex.double() self.frame_del_azimuthal[frame_id] = flex.double() correction_vector = col([self.correction_vector_x[x],self.correction_vector_y[x],0.]) position_vector = col([self.spotfx[x] - SIGN * self.FRAMES["detector_origin_x_refined"][frame_param_no]/PIXEL_SZ, self.spotfy[x] - SIGN * self.FRAMES["detector_origin_y_refined"][frame_param_no]/PIXEL_SZ, 0.]) position_unit = position_vector.normalize() transverse_unit = position_unit.cross(zunit) self.frame_del_radial[frame_id].append(correction_vector.dot(position_unit)) self.frame_del_azimuthal[frame_id].append(correction_vector.dot(transverse_unit))
def water_bond_angle(o,h1,h2): result = None a = h1[0]-o[0], h1[1]-o[1], h1[2]-o[2] b = h2[0]-o[0], h2[1]-o[1], h2[2]-o[2] a = matrix.col(a) b = matrix.col(b) return a.angle(b, deg=True)
def _goniometer(self): """Return a model for a simple single-axis goniometer. This should probably be checked against the image header, though for miniCBF there are limited options for this.""" if "Phi" in self._cif_header_dictionary: phi_value = float(self._cif_header_dictionary["Phi"].split()[0]) else: phi_value = 0.0 if "Kappa" in self._cif_header_dictionary: kappa_value = float(self._cif_header_dictionary["Kappa"].split()[0]) else: kappa_value = 0.0 from scitbx import matrix axis = matrix.col((1, 0, 0)) phi = matrix.col((1, 0, 0)) kappa = matrix.col((0.914, 0.279, -0.297)) Rphi = phi.axis_and_angle_as_r3_rotation_matrix(phi_value, deg=True) Rkappa = kappa.axis_and_angle_as_r3_rotation_matrix(kappa_value, deg=True) fixed = Rkappa * Rphi return self._goniometer_factory.make_goniometer(axis, fixed)
def jacobian_callable(self,values): PB = self.get_partiality_array(values) EXP = flex.exp(-2.*values.BFACTOR*self.DSSQ) G_terms = (EXP * PB * self.ICALCVEC) B_terms = (values.G * EXP * PB * self.ICALCVEC)*(-2.*self.DSSQ) P_terms = (values.G * EXP * self.ICALCVEC) thetax = values.thetax; thetay = values.thetay; Rx = matrix.col((1,0,0)).axis_and_angle_as_r3_rotation_matrix(thetax) dRx_dthetax = matrix.col((1,0,0)).axis_and_angle_as_r3_derivative_wrt_angle(thetax) Ry = matrix.col((0,1,0)).axis_and_angle_as_r3_rotation_matrix(thetay) dRy_dthetay = matrix.col((0,1,0)).axis_and_angle_as_r3_derivative_wrt_angle(thetay) ref_ori = matrix.sqr(self.ORI.reciprocal_matrix()) miller_vec = self.MILLER.as_vec3_double() ds1_dthetax = flex.mat3_double(len(self.MILLER),Ry * dRx_dthetax * ref_ori) * miller_vec ds1_dthetay = flex.mat3_double(len(self.MILLER),dRy_dthetay * Rx * ref_ori) * miller_vec s1vec = self.get_s1_array(values) s1lenvec = flex.sqrt(s1vec.dot(s1vec)) dRh_dthetax = s1vec.dot(ds1_dthetax)/s1lenvec dRh_dthetay = s1vec.dot(ds1_dthetay)/s1lenvec rs = values.RS Rh = self.get_Rh_array(values) rs_sq = rs*rs denomin = (2. * Rh * Rh + rs_sq) dPB_dRh = -PB * 4. * Rh / denomin dPB_dthetax = dPB_dRh * dRh_dthetax dPB_dthetay = dPB_dRh * dRh_dthetay Px_terms = P_terms * dPB_dthetax; Py_terms = P_terms * dPB_dthetay dPB_drs = 4 * rs * Rh * Rh / (denomin * denomin) Prs_terms = P_terms * dPB_drs return [G_terms,B_terms,Prs_terms,Px_terms,Py_terms]
def LP_calculations(self, experiment, s1): '''See Kabsch, J. Appl. Cryst 1988 21 916-924.''' tpl_n = experiment.beam.get_polarization_normal() tpl_s0 = experiment.beam.get_s0() tpl_m2 = experiment.goniometer.get_rotation_axis() tpl_s1 = s1 p = experiment.beam.get_polarization_fraction() # FIXME hack for testing # p = 0.5 from scitbx import matrix n = matrix.col(tpl_n) s0 = matrix.col(tpl_s0) u = matrix.col(tpl_m2) s = matrix.col(tpl_s1) L_f = abs(s.dot(u.cross(s0))) / (s.length() * s0.length()) P_f = (1 - 2 * p) * (1 - (n.dot(s) / s.length()) ** 2.0) + \ p * (1 + (s.dot(s0) / (s.length() * s0.length())) ** 2.0) return L_f / P_f
def as_g_alpha(self, hkl, d_star_sq): return g_exp_i_alpha_derivatives.parameters( g=self.w * math.exp(-2 * math.pi ** 2 * self.u * d_star_sq), ffp=1 + self.fp, fdp=self.fdp, alpha=2 * math.pi * matrix.col(self.xyz).dot(matrix.col(hkl)), )
def test_axis_orthogonal(self): """Ensure that the following are true: e1.s0 = 0, e1.s1 = 0 e2.s1 = 0, e2.e1 = 0 e3.e1 = 0, e3.p* = 0 """ from scitbx import matrix # Get as matrices e1 = matrix.col(self.cs.e1_axis()) e2 = matrix.col(self.cs.e2_axis()) e3 = matrix.col(self.cs.e3_axis()) s0 = matrix.col(self.s0) s1 = matrix.col(self.s1) eps = 1e-7 # Check that e1 is orthogonal to s0 and s1 assert(abs(e1.dot(s0) - 0.0) <= eps) assert(abs(e1.dot(s1) - 0.0) <= eps) # Check that e2 is orthogonal to s1 and e1 assert(abs(e2.dot(s1) - 0.0) <= eps) assert(abs(e2.dot(e1) - 0.0) <= eps) # Check that e3 is orthogonal to e1 and p* = s1 - s0 assert(abs(e3.dot(e1) - 0.0) <= eps) assert(abs(e3.dot(s1 - s0) - 0.0) <= eps) # Test passed print "OK"
def __init__(self, phi0, misset0, phi1, misset1): """Initialise the rotation axis and what have you from some experimental results. N.B. all input values in DEGREES.""" # canonical: X = X-ray beam # Z = rotation axis # Y = Z ^ X z = matrix.col([0, 0, 1]) # then calculate the rotation axis R = ( ( z.axis_and_angle_as_r3_rotation_matrix(phi1, deg=True) * matrix.sqr(xyz_matrix(misset1[0], misset1[1], misset1[2])) ) * ( z.axis_and_angle_as_r3_rotation_matrix(phi0, deg=True) * matrix.sqr(xyz_matrix(misset0[0], misset0[1], misset0[2])) ).inverse() ) self._z = z self._r = matrix.col(r3_rotation_axis_and_angle_from_matrix(R).axis) self._M0 = matrix.sqr(xyz_matrix(misset0[0], misset0[1], misset0[2])) return
def __init__(self,detector=None,camera=None,structure=None,simulation=None): ext.xfel1.__init__(self) self.detector=detector self.camera=camera self.structure=structure self.sim=simulation self.uc = self.structure.p1_cell() self.bmat = matrix.sqr(self.uc.orthogonalization_matrix()).inverse().transpose() self.Ori = crystal_orientation.crystal_orientation( self.bmat, crystal_orientation.basis_type.reciprocal ) energy_in_eV = eV_per_inv_meter / (self.camera.lambda0) # lambda in meters # top hat function for dispersion self.full_pass_eV = energy_in_eV * matrix.col([1.-(self.sim.bandpass/2.), 1.+(self.sim.bandpass/2.)]) self.full_pass_lambda = eV_per_inv_meter * matrix.col((1./self.full_pass_eV[0], 1./self.full_pass_eV[1])) intensities = self.structure.p1_intensities() self.set_indices(intensities.indices()) self.set_intensities(intensities.data())
def test_limit(self): """ Calculate the coordinate at the limits. Ensure that coordinate where s1' is orthogonal to s1 is at limit. """ from scitbx import matrix from math import sqrt from random import uniform eps = 1e-7 # Get the limit of s1' s_dash = matrix.col(self.s1).cross(matrix.col(self.s0)) s_dash = s_dash.normalize() * matrix.col(self.s1).length() # Rotate arbitrarily s_dash = s_dash.rotate(matrix.col(self.s1), uniform(0, 360), deg=True) # Get the c1, c2 coordinate c1, c2 = self.cs.from_beam_vector(s_dash) # Check the point is equal to the limit in rs assert(abs(sqrt(c1**2 + c2**2) - abs(self.cs.limits()[0])) <= eps) # Test passed print 'OK'
def __init__(self, crystal, experiment_ids=[0]): # The state of a crystal orientation parameterisation is an orientation # matrix '[U]'. The initial state is a snapshot of the crystal # orientation at the time of initialisation '[U0]'. Future states are # composed by rotations around axes of the phi-axis frame by Tait-Bryan # angles. # # [U] = [Phi3][Phi2][Phi1][U0] ### Set up the initial state istate = crystal.get_U() ### Set up the parameters phi1 = Parameter(.0, matrix.col((1, 0, 0)), 'angle (mrad)', 'Phi1') phi2 = Parameter(.0, matrix.col((0, 1, 0)), 'angle (mrad)', 'Phi2') phi3 = Parameter(.0, matrix.col((0, 0, 1)), 'angle (mrad)', 'Phi3') # build the parameter list in a specific, maintained order p_list = [phi1, phi2, phi3] # set up the base class ModelParameterisation.__init__(self, crystal, istate, p_list, experiment_ids=experiment_ids) # call compose to calculate all the derivatives self.compose() return
def analyse_corrections(distance, wavelength, thickness): x_corr = read_xds_calibration_file('X-CORRECTIONS.cbf').as_double() * 0.1 y_corr = read_xds_calibration_file('Y-CORRECTIONS.cbf').as_double() * 0.1 o_squared = x_corr * x_corr + y_corr * y_corr dir_x = 2463 * 0.5 dir_y = 2527 * 0.5 pixel = 0.172 from scitbx import matrix import math n = matrix.col((0, 0, 1)) theta_o = { } for j in range(101): x = 0.01 * dir_x * j y = 0.01 * dir_y * j nx = nint(x / 4) ny = nint(y / 4) o = math.sqrt(o_squared[ny, nx]) p = matrix.col((4 * pixel * (dir_x - x), 4 * pixel * (dir_y - y), distance)) theta = p.angle(n) theta_o[theta] = o return theta_o
def __init__(self, orientation = None, translation = None, panelgroup = None): if orientation is None or translation is None: """ Provide only orientation + translation or a panelgroup @param orientation rotation in the form of a quarternion @param translation vector translation in relation to the parent frame @param panelgroup dxtbx panelgroup object whose local d matrix will represent the basis shift """ assert orientation is None and translation is None d_mat = panelgroup.get_local_d_matrix() fast = matrix.col((d_mat[0],d_mat[3],d_mat[6])).normalize() slow = matrix.col((d_mat[1],d_mat[4],d_mat[7])).normalize() orig = matrix.col((d_mat[2],d_mat[5],d_mat[8])) v3 = fast.cross(slow).normalize() r3 = matrix.sqr((fast[0],slow[0],v3[0], fast[1],slow[1],v3[1], fast[2],slow[2],v3[2])) self.orientation = r3.r3_rotation_matrix_as_unit_quaternion() self.translation = orig else: assert panelgroup is None self.orientation = orientation self.translation = translation
def predict_angles(p0_star, experiment, s0=None): '''Predict Ewald sphere crossing angle for RLP x, returned in order (entering, exiting).''' from scitbx import matrix import math a = matrix.col(experiment.goniometer.get_rotation_axis()) if s0 is None: b = matrix.col(experiment.beam.get_s0()) else: b = s0 m2 = a.normalize() m1 = m2.cross(b.normalize()) m3 = m1.cross(m2) p0_sqr = p0_star.dot(p0_star) rho = math.sqrt(p0_sqr - p0_star.dot(m2) ** 2) p_star_m3 = (-0.5 * p0_sqr - p0_star.dot(m2) * b.dot(m2)) / b.dot(m3) p_star_m2 = p0_star.dot(m2) if rho ** 2 < p_star_m3 ** 2: return None p_star_m1 = math.sqrt(rho ** 2 - p_star_m3 ** 2) p0_star_m1 = p0_star.dot(m1) p0_star_m2 = p0_star.dot(m2) p0_star_m3 = p0_star.dot(m3) cp1 = + p_star_m1 * p0_star_m1 + p_star_m3 * p0_star_m3 cp2 = - p_star_m1 * p0_star_m1 + p_star_m3 * p0_star_m3 sp1 = + p_star_m1 * p0_star_m3 - p_star_m3 * p0_star_m1 sp2 = - p_star_m1 * p0_star_m3 - p_star_m3 * p0_star_m1 return math.atan2(sp1, cp1), math.atan2(sp2, cp2)
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 add_sensor(quad_id, sensor_id, sensor): metro[(0,quad_id,sensor_id)] = basis_from_geo(sensor) x, y, z = sensor.get_pixel_coords() x/=1000; y/=1000; z/=1000 assert x.shape == y.shape == z.shape sensor_px_slow = x.shape[0] sensor_px_fast = x.shape[1] assert sensor_px_fast % 2 == 0 a0ul = sul = matrix.col((x[0,0],y[0,0],z[0,0])) a1ur = sur = matrix.col((x[0,sensor_px_fast-1],y[0,sensor_px_fast-1],z[0,sensor_px_fast-1])) a1lr = slr = matrix.col((x[sensor_px_slow-1,sensor_px_fast-1],y[sensor_px_slow-1,sensor_px_fast-1],z[sensor_px_slow-1,sensor_px_fast-1])) a0ll = sll = matrix.col((x[sensor_px_slow-1,0],y[sensor_px_slow-1,0],z[sensor_px_slow-1,0])) a0ur = matrix.col((x[0,sensor_px_fast//2-1],y[0,sensor_px_fast//2-1],z[0,sensor_px_fast//2-1])) a0lr = matrix.col((x[sensor_px_slow-1,sensor_px_fast//2-1],y[sensor_px_slow-1,sensor_px_fast//2-1],z[sensor_px_slow-1,sensor_px_fast//2-1])) a1ul = matrix.col((x[0,sensor_px_fast//2],y[0,sensor_px_fast//2],z[0,sensor_px_fast//2])) a1ll = matrix.col((x[sensor_px_slow-1,sensor_px_fast//2],y[sensor_px_slow-1,sensor_px_fast//2],z[sensor_px_slow-1,sensor_px_fast//2])) sensor_center = center([sul,sur,slr,sll]) asic0_center = center([a0ul,a0ur,a0lr,a0ll]) asic1_center = center([a1ul,a1ur,a1lr,a1ll]) asic_trans0 = (asic0_center-sensor_center).length() asic_trans1 = (asic1_center-sensor_center).length() metro[(0,quad_id,sensor_id,0)] = basis(orientation=null_ori,translation=matrix.col((-asic_trans0,0,0))) metro[(0,quad_id,sensor_id,1)] = basis(orientation=null_ori,translation=matrix.col((+asic_trans1,0,0)))
def exercise_is_simple_interaction(): for space_group_symbol in ["P1", "P41"]: for shifts in flex.nested_loop((-2,-2,-2),(2,2,2),False): shifts = matrix.col(shifts) structure = xray.structure( crystal_symmetry=crystal.symmetry( unit_cell=(10,10,20,90,90,90), space_group_symbol=space_group_symbol), scatterers=flex.xray_scatterer([ xray.scatterer(label="O", site=shifts+matrix.col((0,0,0))), xray.scatterer(label="N", site=shifts+matrix.col((0.5,0.5,0))), xray.scatterer(label="C", site=shifts+matrix.col((0.25,0.25,0)))])) asu_mappings = structure.asu_mappings(buffer_thickness=7) pair_generator = crystal.neighbors_simple_pair_generator( asu_mappings=asu_mappings, distance_cutoff=7) simple_interactions = {} for i_pair,pair in enumerate(pair_generator): if (asu_mappings.is_simple_interaction(pair)): assert asu_mappings_is_simple_interaction_emulation( asu_mappings, pair) key = (pair.i_seq,pair.j_seq) assert simple_interactions.get(key, None) is None simple_interactions[key] = 1 else: assert not asu_mappings_is_simple_interaction_emulation( asu_mappings, pair) assert len(simple_interactions) == 2 assert simple_interactions[(0,2)] == 1 assert simple_interactions[(1,2)] == 1
def unstable_matrix_inversion_diagonal(self,Lower,Diag,Transpose): ### Can't use the Cholesky factorization to derive the Variance-Covariance matrix ### Demonstrate that inverting the matrix is numerically unstable Nx = len(self.helper.x) error_diagonal_elems = flex.double(Nx) for j_element in xrange(Nx): # now solve for the vector p = D * LT * x by substitution in eqn L * p = b # b is the column vector of zeroes except jth_element is 1. p = flex.double(Nx) p[j_element] = 1. for p_idx in xrange(j_element+1,Nx): for subs_idx in xrange(j_element,p_idx): p[p_idx] -= Lower(p_idx,subs_idx) * p[subs_idx] Pvec = col(p) # now solve for the vector q = LT * x by division in eqn D * q = b q = flex.double([ p[i] / Diag(i,i) for i in xrange(Nx)] ) # this is the unstable step. We can't divide by tiny denominators Qvec = col(q) # now solve for the jth element of x in the eqn LT * x = q xelem = flex.double(Qvec.elems) for x_idx in xrange(Nx-1,j_element-1,-1): #comment this in for production #for x_idx in xrange(Nx-1,-1,-1): for subs_idx in xrange(x_idx+1, Nx): xelem[x_idx] -= Transpose(x_idx,subs_idx) * xelem[subs_idx] Xvec = col(xelem) # got the whole vector; only need j_element for the error matrix diagonal error_diagonal_elems[j_element] = xelem[j_element] return col(error_diagonal_elems)
def understand(image_file): '''Check to see if this looks like an Rayonix TIFF format image, i.e. we can make sense of it. Returns true if the beam center is specified in pixels.''' width, height, depth, order, bytes = FormatTIFFRayonix.get_tiff_header( image_file) import struct from scitbx.matrix import col from dxtbx.format.FormatTIFFHelpers import LITTLE_ENDIAN, BIG_ENDIAN format = {LITTLE_ENDIAN:'<', BIG_ENDIAN:'>'}[order] offset = 1024 detector_size_pixels = col(struct.unpack(format+'ii',bytes[offset+80:offset+88])) detector_center_px = 0.5 * detector_size_pixels detector_pixel_sz_mm = 1.E-6 * col( # convert from nano to milli struct.unpack(format+'ii',bytes[offset+772:offset+780])) header_beam_center = 0.001 * col( # Rayonix says this should be pixels struct.unpack(format+'ii',bytes[offset+644:offset+652])) disagreement = header_beam_center[0]/detector_center_px[0] return header_beam_center[0] > 0 and header_beam_center[1] > 0 \ and disagreement < 0.5 # if header was in mm, disagreement should be
def exercise_ellipsoid(n_trials=100, n_sub_trials=10): from gltbx import quadrics rnd = random.Random(0) for i in xrange(n_trials): centre = matrix.col([ rnd.random() for k in xrange(3) ]) half_lengths = matrix.col([ 0.1 + rnd.random() for k in xrange(3) ]) r = scitbx.math.euler_angles_as_matrix( [ rnd.uniform(0, 360) for i in xrange(3) ], deg=True) metrics = r * matrix.diag([ x**2 for x in half_lengths ]) * r.transpose() t = quadrics.ellipsoid_to_sphere_transform(centre, metrics.as_sym_mat3()) assert approx_equal(t.translation_part(), centre) m = matrix.sqr(t.linear_part()) assert m.determinant() > 0 for j in xrange(n_sub_trials): y = matrix.col([ rnd.random() for k in xrange(3) ]) c_y = y.transpose() * y x = m*y c_x = x.transpose() * metrics.inverse() * x assert approx_equal(c_x, c_y) r = scitbx.math.euler_angles_as_matrix((30, 115, 260), deg=True) centre = matrix.col((-1, 2, 3)) metrics = r * matrix.diag((-1, 0.1, 1)) * r.transpose() t = quadrics.ellipsoid_to_sphere_transform(centre, metrics.as_sym_mat3()) assert t.non_positive_definite() x = r * matrix.col((1,0,0)) assert x.transpose() * metrics.inverse() * x > 0
def exercise_tensor_constraints_core(crystal_symmetry): from cctbx import crystal from cctbx import adptbx from scitbx import matrix site_symmetry = crystal.special_position_settings( crystal_symmetry).site_symmetry(site=(0,0,0)) unit_cell = crystal_symmetry.unit_cell() group = crystal_symmetry.space_group() assert site_symmetry.n_matrices() == group.order_p() for reciprocal_space in [False, True]: c_tensor_constraints = sgtbx.tensor_rank_2_constraints( space_group=group, reciprocal_space=reciprocal_space).row_echelon_form() p_tensor_constraints = python_tensor_constraints( self=group, reciprocal_space=reciprocal_space) assert c_tensor_constraints.all_eq(p_tensor_constraints) adp_constraints = group.adp_constraints() u_cart_p1 = adptbx.random_u_cart() u_star_p1 = adptbx.u_cart_as_u_star(unit_cell, u_cart_p1) u_star = site_symmetry.average_u_star(u_star_p1) f = unit_cell.volume()**(2/3.) assert approx_equal( list(matrix.col(group.average_u_star(u_star=u_star_p1))*f), list(matrix.col(u_star)*f)) independent_params = adp_constraints.independent_params(u_star) assert adp_constraints.n_independent_params() == len(independent_params) assert adp_constraints.n_independent_params() \ + adp_constraints.n_dependent_params() == 6 u_star_vfy = adp_constraints.all_params(independent_params) u_cart = adptbx.u_star_as_u_cart(unit_cell, u_star) u_cart_vfy = adptbx.u_star_as_u_cart(unit_cell, list(u_star_vfy)) assert approx_equal(u_cart_vfy, u_cart)
def ersatz_misset(integrate_lp): a_s = [] b_s = [] c_s = [] for record in open(integrate_lp): if 'COORDINATES OF UNIT CELL A-AXIS' in record: a = map(float, record.split()[-3:]) a_s.append(matrix.col(a)) elif 'COORDINATES OF UNIT CELL B-AXIS' in record: b = map(float, record.split()[-3:]) b_s.append(matrix.col(b)) elif 'COORDINATES OF UNIT CELL C-AXIS' in record: c = map(float, record.split()[-3:]) c_s.append(matrix.col(c)) assert(len(a_s) == len(b_s) == len(c_s)) ub0 = matrix.sqr(a_s[0].elems + b_s[0].elems + c_s[0].elems).inverse() for j in range(len(a_s)): ub = matrix.sqr(a_s[j].elems + b_s[j].elems + c_s[j].elems).inverse() print '%7.3f %7.3f %7.3f' % tuple(xyz_angles(ub.inverse() * ub0)) return
def apply_sub_pixel_metrology(tile, x, y, tcx, tcy, phil,handedness=0): handedness -= 1 if handedness < 0: return (x,y) if tile < 0: return None r = col((x, y)) # point of interest Ti = col((tcx,tcy)) # center of tile i # sub pixel translation/rotation if handednesses[handedness][h_swapped]: ti = col((phil.integration.subpixel_joint_model.translations[(tile*2)+1] * handednesses[handedness][h_y], phil.integration.subpixel_joint_model.translations[tile*2] * handednesses[handedness][h_x])) else: ti = col((phil.integration.subpixel_joint_model.translations[tile*2] * handednesses[handedness][h_x], phil.integration.subpixel_joint_model.translations[(tile*2)+1] * handednesses[handedness][h_y])) theta = phil.integration.subpixel_joint_model.rotations[tile] * (math.pi/180) * handednesses[handedness][h_theta] Ri = sqr((math.cos(theta),-math.sin(theta),math.sin(theta),math.cos(theta))) # apply sub-pixel translation to point of interest and tile center rp = r + ti # p: prime Tip = Ti + ti result = (Ri*(rp-Tip))+Tip return (result[0], result[1])
def tst_set_direction_wavelength(): """Test setting direction and wavelength""" from scitbx import matrix direction = matrix.col((0.013142, 0.002200, 1.450476)) unit_direction = direction.normalize() wavelength = 0.689400 # Create the beam b = Beam(direction, wavelength) eps = 1e-7 # Check direction is a unit vector assert(abs(matrix.col(b.get_direction()).length() - 1) <= eps) assert(abs(matrix.col(b.get_direction()) - unit_direction) <= eps) # Check wavelength is correct assert(abs(b.get_wavelength() - wavelength) <= eps) # Check s0 is in direction and has length 1/wavelength assert(abs(matrix.col(b.get_s0()).length() - 1.0 / wavelength) <= eps) assert(abs(-matrix.col(b.get_s0()).normalize() - unit_direction) <= eps) # Test passed print "OK"
def unit_cell_bases_mean_square_difference(self, other): diff_sqs = flex.double() for basis_vector in [(1,0,0),(0,1,0),(0,0,1)]: self_v = matrix.col(self.orthogonalize(basis_vector)) other_v = matrix.col(other.orthogonalize(basis_vector)) diff_sqs.append((self_v - other_v).norm_sq()) return flex.mean(diff_sqs)
def exercise(verbose=0): distance_ideal = 1.8 default_vdw_distance = 3.6 vdw_1_4_factor = 3.5 / 3.6 sites_cart_manual = flex.vec3_double([(1, 3, 0), (2, 3, 0), (3, 2, 0), (3, 1, 0), (4, 1, 0), (3, 4, 0), (4, 3, 0), (5, 3, 0), (6, 2, 0), (7, 2, 0), (8, 3, 0), (7, 4, 0), (6, 4, 0), (7, 5, 0), (6, 6, 0), (8, 6, 0)]) bond_proxies = geometry_restraints.bond_sorted_asu_proxies( asu_mappings=None) for i_seqs in [(0, 1), (1, 2), (2, 3), (3, 4), (1, 5), (2, 6), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 7), (11, 13), (13, 14), (14, 15), (15, 13)]: bond_proxies.process( geometry_restraints.bond_simple_proxy( i_seqs=i_seqs, distance_ideal=distance_ideal, weight=100)) angle_proxies = geometry_restraints.shared_angle_proxy() for i_seqs, angle_ideal in [[(0, 1, 2), 135], [(0, 1, 5), 135], [(1, 2, 3), 135], [(3, 2, 6), 135], [(2, 3, 4), 120], [(1, 2, 6), 90], [(2, 6, 5), 90], [(6, 5, 1), 90], [(5, 1, 2), 90], [(2, 6, 7), 135], [(5, 6, 7), 135], [(6, 7, 8), 120], [(6, 7, 12), 120], [(7, 8, 9), 120], [(8, 9, 10), 120], [(9, 10, 11), 120], [(10, 11, 12), 120], [(11, 12, 7), 120], [(12, 7, 8), 120], [(10, 11, 13), 120], [(12, 11, 13), 120], [(11, 13, 15), 150], [(11, 13, 14), 150], [(13, 15, 14), 60], [(15, 14, 13), 60], [(14, 13, 15), 60]]: angle_proxies.append( geometry_restraints.angle_proxy(i_seqs=i_seqs, angle_ideal=angle_ideal, weight=1)) if (0 or verbose): dump_pdb(file_name="manual.pdb", sites_cart=sites_cart_manual) for traditional_convergence_test in [True, False]: for sites_cart_selection in [True, False]: sites_cart = sites_cart_manual.deep_copy() if sites_cart_selection: sites_cart_selection = flex.bool(sites_cart.size(), True) sites_cart_selection[1] = False assert bond_proxies.asu.size() == 0 bond_params_table = geometry_restraints.extract_bond_params( n_seq=sites_cart.size(), bond_simple_proxies=bond_proxies.simple) manager = geometry_restraints.manager.manager( bond_params_table=bond_params_table, angle_proxies=angle_proxies) minimized = geometry_restraints.lbfgs.lbfgs( sites_cart=sites_cart, geometry_restraints_manager=manager, lbfgs_termination_params=scitbx.lbfgs.termination_parameters( traditional_convergence_test=traditional_convergence_test, drop_convergence_test_max_drop_eps=1.e-20, drop_convergence_test_iteration_coefficient=1, max_iterations=1000), sites_cart_selection=sites_cart_selection, ) assert minimized.minimizer.iter() > 100 sites_cart_minimized_1 = sites_cart.deep_copy() if (0 or verbose): dump_pdb(file_name="minimized_1.pdb", sites_cart=sites_cart_minimized_1) bond_deltas = geometry_restraints.bond_deltas( sites_cart=sites_cart_minimized_1, proxies=bond_proxies.simple) angle_deltas = geometry_restraints.angle_deltas( sites_cart=sites_cart_minimized_1, proxies=angle_proxies) if (0 or verbose): for proxy, delta in zip(bond_proxies.simple, bond_deltas): print("bond:", proxy.i_seqs, delta) for proxy, delta in zip(angle_proxies, angle_deltas): print("angle:", proxy.i_seqs, delta) assert is_below_limit(value=flex.max(flex.abs(bond_deltas)), limit=0, eps=1.e-6) assert is_below_limit(value=flex.max(flex.abs(angle_deltas)), limit=0, eps=2.e-6) sites_cart += matrix.col((1, 1, 0)) - matrix.col(sites_cart.min()) unit_cell_lengths = list( matrix.col(sites_cart.max()) + matrix.col((1, -1.2, 4))) unit_cell_lengths[1] *= 2 unit_cell_lengths[2] *= 2 xray_structure = xray.structure(crystal_symmetry=crystal.symmetry( unit_cell=unit_cell_lengths, space_group_symbol="P112")) for serial, site in zip(count(1), sites_cart): xray_structure.add_scatterer( xray.scatterer( label="C%02d" % serial, site=xray_structure.unit_cell().fractionalize(site))) if (0 or verbose): xray_structure.show_summary().show_scatterers() p1_structure = (xray_structure.apply_shift( (-.5, -.5, 0)).expand_to_p1().apply_shift((.5, .5, 0))) for shift in [(1, 0, 0), (0, 1, 0), (0, 0, 1)]: p1_structure.add_scatterers( p1_structure.apply_shift(shift).scatterers()) if (0 or verbose): open("p1_structure.pdb", "w").write(p1_structure.as_pdb_file()) nonbonded_cutoff = 6.5 asu_mappings = xray_structure.asu_mappings( buffer_thickness=nonbonded_cutoff) bond_asu_table = crystal.pair_asu_table(asu_mappings=asu_mappings) geometry_restraints.add_pairs(bond_asu_table, bond_proxies.simple) shell_asu_tables = crystal.coordination_sequences.shell_asu_tables( pair_asu_table=bond_asu_table, max_shell=3) shell_sym_tables = [ shell_asu_table.extract_pair_sym_table() for shell_asu_table in shell_asu_tables ] bond_params_table = geometry_restraints.extract_bond_params( n_seq=sites_cart.size(), bond_simple_proxies=bond_proxies.simple) atom_energy_types = flex.std_string(sites_cart.size(), "Default") nonbonded_params = geometry_restraints.nonbonded_params( factor_1_4_interactions=vdw_1_4_factor, const_shrink_1_4_interactions=0, default_distance=default_vdw_distance) nonbonded_params.distance_table.setdefault( "Default")["Default"] = default_vdw_distance pair_proxies = geometry_restraints.pair_proxies( bond_params_table=bond_params_table, shell_asu_tables=shell_asu_tables, model_indices=None, conformer_indices=None, nonbonded_params=nonbonded_params, nonbonded_types=atom_energy_types, nonbonded_distance_cutoff_plus_buffer=nonbonded_cutoff) if (0 or verbose): print("pair_proxies.bond_proxies.n_total():", \ pair_proxies.bond_proxies.n_total(), end=' ') print("simple:", pair_proxies.bond_proxies.simple.size(), end=' ') print("sym:", pair_proxies.bond_proxies.asu.size()) print("pair_proxies.nonbonded_proxies.n_total():", \ pair_proxies.nonbonded_proxies.n_total(), end=' ') print("simple:", pair_proxies.nonbonded_proxies.simple.size(), end=' ') print("sym:", pair_proxies.nonbonded_proxies.asu.size()) print("min_distance_nonbonded: %.2f" % flex.min( geometry_restraints.nonbonded_deltas( sites_cart=sites_cart, sorted_asu_proxies=pair_proxies.nonbonded_proxies))) s = StringIO() pair_proxies.bond_proxies.show_histogram_of_model_distances( sites_cart=sites_cart, f=s, prefix="[]") assert s.getvalue().splitlines()[0] == "[]Histogram of bond lengths:" assert s.getvalue().splitlines()[5].startswith("[] 1.80 - 1.80:") s = StringIO() pair_proxies.bond_proxies.show_histogram_of_deltas(sites_cart=sites_cart, f=s, prefix="][") assert s.getvalue().splitlines()[0] == "][Histogram of bond deltas:" assert s.getvalue().splitlines()[5].startswith("][ 0.000 - 0.000:") s = StringIO() pair_proxies.bond_proxies.show_sorted(by_value="residual", sites_cart=sites_cart, max_items=3, f=s, prefix=":;") l = s.getvalue().splitlines() assert l[0] == ":;Bond restraints: 18" assert l[1] == ":;Sorted by residual:" assert l[2].startswith(":;bond ") assert l[3].startswith(":; ") assert l[4] == ":; ideal model delta sigma weight residual" for i in [5, -2]: assert l[i].startswith(":; 1.800 1.800 ") assert l[-1] == ":;... (remaining 15 not shown)" s = StringIO() pair_proxies.nonbonded_proxies.show_histogram_of_model_distances( sites_cart=sites_cart, f=s, prefix="]^") assert not show_diff( s.getvalue(), """\ ]^Histogram of nonbonded interaction distances: ]^ 2.16 - 3.03: 3 ]^ 3.03 - 3.89: 12 ]^ 3.89 - 4.75: 28 ]^ 4.75 - 5.61: 44 ]^ 5.61 - 6.48: 54 """) s = StringIO() pair_proxies.nonbonded_proxies.show_sorted(by_value="delta", sites_cart=sites_cart, max_items=7, f=s, prefix=">,") assert not show_diff(s.getvalue(), """\ >,Nonbonded interactions: 141 >,Sorted by model distance: >,nonbonded 15 >, 15 >, model vdw sym.op. >, 2.164 3.600 -x+2,-y+1,z ... >,nonbonded 4 >, 8 >, model vdw >, 3.414 3.600 >,... (remaining 134 not shown) """, selections=[range(6), range(-5, 0)]) vdw_1_sticks = [] vdw_2_sticks = [] for proxy in pair_proxies.nonbonded_proxies.simple: if (proxy.vdw_distance == default_vdw_distance): vdw_1_sticks.append( pml_stick(begin=sites_cart[proxy.i_seqs[0]], end=sites_cart[proxy.i_seqs[1]])) else: vdw_2_sticks.append( pml_stick(begin=sites_cart[proxy.i_seqs[0]], end=sites_cart[proxy.i_seqs[1]])) mps = asu_mappings.mappings() for proxy in pair_proxies.nonbonded_proxies.asu: if (proxy.vdw_distance == default_vdw_distance): vdw_1_sticks.append( pml_stick(begin=mps[proxy.i_seq][0].mapped_site(), end=mps[proxy.j_seq][proxy.j_sym].mapped_site())) else: vdw_2_sticks.append( pml_stick(begin=mps[proxy.i_seq][0].mapped_site(), end=mps[proxy.j_seq][proxy.j_sym].mapped_site())) if (0 or verbose): pml_write(f=open("vdw_1.pml", "w"), label="vdw_1", sticks=vdw_1_sticks) pml_write(f=open("vdw_2.pml", "w"), label="vdw_2", sticks=vdw_2_sticks) # i_pdb = count(2) for use_crystal_symmetry in [False, True]: if (not use_crystal_symmetry): crystal_symmetry = None site_symmetry_table = None else: crystal_symmetry = xray_structure site_symmetry_table = xray_structure.site_symmetry_table() for sites_cart in [ sites_cart_manual.deep_copy(), sites_cart_minimized_1.deep_copy() ]: manager = geometry_restraints.manager.manager( crystal_symmetry=crystal_symmetry, site_symmetry_table=site_symmetry_table, nonbonded_params=nonbonded_params, nonbonded_types=atom_energy_types, nonbonded_function=geometry_restraints. prolsq_repulsion_function(), bond_params_table=bond_params_table, shell_sym_tables=shell_sym_tables, nonbonded_distance_cutoff=nonbonded_cutoff, nonbonded_buffer=1, angle_proxies=angle_proxies, plain_pairs_radius=5) manager = manager.select( selection=flex.bool(sites_cart.size(), True)) manager = manager.select(iselection=flex.size_t_range( stop=sites_cart.size())) pair_proxies = manager.pair_proxies(sites_cart=sites_cart) minimized = geometry_restraints.lbfgs.lbfgs( sites_cart=sites_cart, geometry_restraints_manager=manager, lbfgs_termination_params=scitbx.lbfgs.termination_parameters( max_iterations=1000)) if (0 or verbose): minimized.final_target_result.show() print("number of function evaluations:", minimized.minimizer.nfun()) print("n_updates_pair_proxies:", manager.n_updates_pair_proxies) if (not use_crystal_symmetry): assert minimized.final_target_result.bond_residual_sum < 1.e-3 assert minimized.final_target_result.nonbonded_residual_sum < 0.1 else: assert minimized.final_target_result.bond_residual_sum < 1.e-2 assert minimized.final_target_result.nonbonded_residual_sum < 0.1 assert minimized.final_target_result.angle_residual_sum < 1.e-3 if (0 or verbose): pdb_file_name = "minimized_%d.pdb" % next(i_pdb) print("Writing file:", pdb_file_name) dump_pdb(file_name=pdb_file_name, sites_cart=sites_cart) if (manager.site_symmetry_table is None): additional_site_symmetry_table = None else: additional_site_symmetry_table = sgtbx.site_symmetry_table() assert manager.new_including_isolated_sites( n_additional_sites=0, site_symmetry_table=additional_site_symmetry_table, nonbonded_types=flex.std_string()).plain_pairs_radius \ == manager.plain_pairs_radius if (crystal_symmetry is not None): assert len(manager.plain_pair_sym_table) == 16 if (0 or verbose): manager.plain_pair_sym_table.show() # xray_structure.set_u_iso(values=flex.double([ 0.77599982480241358, 0.38745781137212021, 0.20667558236418682, 0.99759840171302094, 0.8917287406687805, 0.64780251325379845, 0.24878590382983534, 0.59480621182194615, 0.58695637792905142, 0.33997130213653637, 0.51258699130743735, 0.79760289141276675, 0.39996577657875021, 0.4329328819341467, 0.70422156561726479, 0.87260110626999332 ])) class parameters: pass parameters.sphere_radius = 5 parameters.distance_power = 0.7 parameters.average_power = 0.9 parameters.wilson_b_weight = 1.3952 parameters.wilson_b_weight_auto = False adp_energies = adp_restraints.energies_iso( geometry_restraints_manager=manager, xray_structure=xray_structure, parameters=parameters, wilson_b=None, use_hd=False, use_u_local_only=False, compute_gradients=False, gradients=None, normalization=False, collect=True) assert adp_energies.number_of_restraints == 69 assert approx_equal(adp_energies.residual_sum, 6.24865382467) assert adp_energies.gradients is None assert adp_energies.u_i.size() == adp_energies.number_of_restraints assert adp_energies.u_j.size() == adp_energies.number_of_restraints assert adp_energies.r_ij.size() == adp_energies.number_of_restraints for wilson_b in [None, 10, 100]: finite_difference_gradients = flex.double() eps = 1.e-6 for i_scatterer in range(xray_structure.scatterers().size()): rs = [] for signed_eps in [eps, -eps]: xray_structure_eps = xray_structure.deep_copy_scatterers() xray_structure_eps.scatterers( )[i_scatterer].u_iso += signed_eps adp_energies = adp_restraints.energies_iso( geometry_restraints_manager=manager, xray_structure=xray_structure_eps, parameters=parameters, wilson_b=wilson_b, use_u_local_only=False, use_hd=False, compute_gradients=True, gradients=None, normalization=False, collect=False) rs.append(adp_energies.residual_sum) assert adp_energies.gradients.size() \ == xray_structure.scatterers().size() assert adp_energies.u_i == None assert adp_energies.u_j == None assert adp_energies.r_ij == None finite_difference_gradients.append((rs[0] - rs[1]) / (2 * eps)) sel = flex.bool(xray_structure.scatterers().size(), True) xray_structure.scatterers().flags_set_grad_u_iso(sel.iselection()) adp_energies = adp_restraints.energies_iso( geometry_restraints_manager=manager, xray_structure=xray_structure, parameters=parameters, wilson_b=wilson_b, use_u_local_only=False, use_hd=False, compute_gradients=True, gradients=None, normalization=False, collect=False) assert approx_equal(adp_energies.gradients, finite_difference_gradients) print("OK")
def __call__(self, reflections, experiments, d_min=None): from libtbx.math_utils import nearest_integer as nint from scitbx import matrix reciprocal_lattice_points = reflections["rlp"] if "miller_index" not in reflections: reflections["miller_index"] = flex.miller_index(len(reflections)) if d_min is not None: d_spacings = 1 / reciprocal_lattice_points.norms() inside_resolution_limit = d_spacings > d_min else: inside_resolution_limit = flex.bool( reciprocal_lattice_points.size(), True) sel = inside_resolution_limit & (reflections["id"] == -1) isel = sel.iselection() rlps = reciprocal_lattice_points.select(isel) refs = reflections.select(isel) phi = refs["xyzobs.mm.value"].parts()[2] if len(rlps) <= self._nearest_neighbours: raise DialsIndexError( "index_assignment.local.nearest_neighbour must be smaller than the number of accepted reflections (%d)" % len(rlps)) UB_matrices = flex.mat3_double( [cm.get_A() for cm in experiments.crystals()]) result = ext.AssignIndicesLocal( rlps, phi, UB_matrices, epsilon=self._epsilon, delta=self._delta, l_min=self._l_min, nearest_neighbours=self._nearest_neighbours, ) miller_indices = result.miller_indices() crystal_ids = result.crystal_ids() hkl = miller_indices.as_vec3_double().iround() assert miller_indices.select(crystal_ids < 0).all_eq((0, 0, 0)) for i_cryst in set(crystal_ids): if i_cryst < 0: continue A = matrix.sqr(experiments[i_cryst].crystal.get_A()) A_inv = A.inverse() cryst_sel = crystal_ids == i_cryst rlp_sel = rlps.select(cryst_sel) hkl_sel = hkl.select(cryst_sel).as_vec3_double() d_sel = 1 / rlp_sel.norms() d_perm = flex.sort_permutation(d_sel, reverse=True) hf_0 = A_inv * rlp_sel[d_perm[0]] h_0 = matrix.col([nint(j) for j in hf_0.elems]) offset = h_0 - matrix.col(hkl_sel[d_perm[0]]) # print "offset:", offset.elems h = hkl_sel + flex.vec3_double(hkl_sel.size(), offset.elems) refs["miller_index"].set_selected( cryst_sel, flex.miller_index(list(h.iround()))) refs["id"].set_selected(cryst_sel, i_cryst) crystal_ids.set_selected(crystal_ids < 0, -1) refs["id"] = crystal_ids refs["miller_index"].set_selected(crystal_ids < 0, (0, 0, 0)) reflections["miller_index"].set_selected(isel, refs["miller_index"]) reflections["id"].set_selected(isel, refs["id"]) reflections.set_flags(reflections["miller_index"] != (0, 0, 0), reflections.flags.indexed)
def _detector(self): '''Return a model for the detector, allowing for two-theta offsets and the detector position. This will be rather more complex...''' from scitbx import matrix detector_name = self._header_dictionary['DETECTOR_NAMES'].split( )[0].strip() detector_axes = map( float, self._header_dictionary['%sDETECTOR_VECTORS' % detector_name].split()) fast = matrix.col(tuple(detector_axes[:3])) slow = matrix.col(tuple(detector_axes[3:])) distortion = map( int, self._header_dictionary['%sSPATIAL_DISTORTION_VECTORS' % detector_name].split()) # multiply through by the distortion to get the true detector fast, slow detector_fast, detector_slow = distortion[0] * fast + distortion[1] * slow, \ distortion[2] * fast + distortion[3] * slow beam_pixels = map( float, self._header_dictionary['%sSPATIAL_DISTORTION_INFO' % detector_name].split()[:2]) pixel_size = map( float, self._header_dictionary['%sSPATIAL_DISTORTION_INFO' % detector_name].split()[2:]) image_size = map( int, self._header_dictionary['%sDETECTOR_DIMENSIONS' % detector_name].split()) detector_origin = - (beam_pixels[0] * pixel_size[0] * detector_fast + \ beam_pixels[1] * pixel_size[1] * detector_slow) gonio_axes = map( float, self._header_dictionary['%sGONIO_VECTORS' % detector_name].split()) gonio_values = map( float, self._header_dictionary['%sGONIO_VALUES' % detector_name].split()) gonio_units = self._header_dictionary['%sGONIO_UNITS' % detector_name].split() gonio_num_axes = int(self._header_dictionary['%sGONIO_NUM_VALUES' % detector_name]) rotations = [] translations = [] for j, unit in enumerate(gonio_units): axis = matrix.col(gonio_axes[3 * j:3 * (j + 1)]) if unit == 'deg': rotations.append( axis.axis_and_angle_as_r3_rotation_matrix(gonio_values[j], deg=True)) translations.append(matrix.col((0.0, 0.0, 0.0))) elif unit == 'mm': rotations.append( matrix.sqr((1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0))) translations.append(gonio_values[j] * axis) else: raise RuntimeError, 'unknown axis unit %s' % unit rotations.reverse() translations.reverse() for j in range(gonio_num_axes): detector_fast = rotations[j] * detector_fast detector_slow = rotations[j] * detector_slow detector_origin = rotations[j] * detector_origin detector_origin = translations[j] + detector_origin overload = int(float(self._header_dictionary['SATURATED_VALUE'])) underload = 0 return self._detector_factory.complex('PAD', detector_origin.elems, detector_fast.elems, detector_slow.elems, pixel_size, image_size, (underload, overload))
def _detector(self): """Detector model, allowing for small offsets in the positions of 60 detector modules""" distance = float( self._cif_header_dictionary["Detector_distance"].split()[0]) beam_xy = (self._cif_header_dictionary["Beam_xy"].replace( "(", "").replace(")", "").replace(",", "").split()[:2]) beam_x, beam_y = map(float, beam_xy) wavelength = float( self._cif_header_dictionary["Wavelength"].split()[0]) pixel_xy = (self._cif_header_dictionary["Pixel_size"].replace( "m", "").replace("x", "").split()) pixel_x, pixel_y = map(float, pixel_xy) thickness = float( self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0 nx = int( self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"]) ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"]) overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0]) underload = -1 # take into consideration here the thickness of the sensor also the # wavelength of the radiation (which we have in the same file...) table = attenuation_coefficient.get_table("Si") mu = table.mu_at_angstrom(wavelength) / 10.0 t0 = thickness # FIXME would also be very nice to be able to take into account the # misalignment of the individual modules given the calibration... # single detector or multi-module detector pixel_x *= 1000.0 pixel_y *= 1000.0 distance *= 1000.0 if not self._multi_panel: detector = self._detector_factory.simple( "PAD", distance, (beam_x * pixel_x, beam_y * pixel_y), "+x", "-y", (pixel_x, pixel_y), (nx, ny), (underload, overload), [], ParallaxCorrectedPxMmStrategy(mu, t0), ) for f0, f1, s0, s1 in determine_pilatus_mask(detector): detector[0].add_mask(f0 - 1, s0 - 1, f1, s1) detector[0].set_thickness(thickness) detector[0].set_material("Si") detector[0].set_mu(mu) return detector # got to here means 60-panel version d = Detector() beam_centre = matrix.col((beam_x * pixel_x, beam_y * pixel_y, 0)) fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, -1.0, 0.0)) s0 = matrix.col((0, 0, -1)) origin = (distance * s0) - (fast * beam_centre[0]) - (slow * beam_centre[1]) root = d.hierarchy() root.set_local_frame(fast.elems, slow.elems, origin.elems) xmins = [0, 494, 988, 1482, 1976] xmaxes = [487, 981, 1475, 1969, 2463] ymins = [ 0, 212, 424, 636, 848, 1060, 1272, 1484, 1696, 1908, 2120, 2332 ] ymaxes = [ 195, 407, 619, 831, 1043, 1255, 1467, 1679, 1891, 2103, 2315, 2527 ] self.coords = {} fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, 1.0, 0.0)) panel_idx = 0 for ymin, ymax in zip(ymins, ymaxes): for xmin, xmax in zip(xmins, xmaxes): xmin_mm = xmin * pixel_x ymin_mm = ymin * pixel_y origin_panel = fast * xmin_mm + slow * ymin_mm panel_name = "Panel%d" % panel_idx panel_idx += 1 p = d.add_panel() p.set_type("SENSOR_PAD") p.set_name(panel_name) p.set_raw_image_offset((xmin, ymin)) p.set_image_size((xmax - xmin, ymax - ymin)) p.set_trusted_range((underload, overload)) p.set_pixel_size((pixel_x, pixel_y)) p.set_thickness(thickness) p.set_material("Si") p.set_mu(mu) p.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0)) p.set_local_frame(fast.elems, slow.elems, origin_panel.elems) p.set_raw_image_offset((xmin, ymin)) self.coords[panel_name] = (xmin, ymin, xmax, ymax) return d
def _detector(self): '''Detector model, allowing for small offsets in the positions of 60 detector modules''' # Module positional offsets in x, y, in pixels - for the moment ignoring the # rotational offsets as these are not well defined. To be honest these # positional offsets are also not well defined as I do not know how they # should be applied... x = { (0, 0): -0.477546, (0, 1): 0.130578, (0, 2): 0.045041, (0, 3): -0.439872, (0, 4): -0.382077, (1, 0): 0.087405, (1, 1): 0.249597, (1, 2): 0.184265, (1, 3): 0.158342, (1, 4): 0.025225, (2, 0): -0.179892, (2, 1): -0.010974, (2, 2): -0.139207, (2, 3): 0.282851, (2, 4): -0.442219, (3, 0): -0.185027, (3, 1): 0.218601, (3, 2): 0.092585, (3, 3): 0.35862, (3, 4): -0.29161, (4, 0): 0.145368, (4, 1): 0.609289, (4, 2): 0.396265, (4, 3): 0.41625, (4, 4): 0.07152, (5, 0): 0.247142, (5, 1): 0.046563, (5, 2): 0.248714, (5, 3): -0.044628, (5, 4): -0.391509, (6, 0): 0.516643, (6, 1): 0.358453, (6, 2): 0.069219, (6, 3): 0.095861, (6, 4): -0.167403, (7, 0): -0.381352, (7, 1): -0.35338, (7, 2): 0.348656, (7, 3): 0.024543, (7, 4): 0.328706, (8, 0): 0.150886, (8, 1): 0.244987, (8, 2): -0.102911, (8, 3): 0.16633, (8, 4): 0.386622, (9, 0): 0.037924, (9, 1): 0.314392, (9, 2): 0.238818, (9, 3): 0.815028, (9, 4): -0.048818, (10, 0): -0.670524, (10, 1): -0.304119, (10, 2): 0.252284, (10, 3): -0.05485, (10, 4): -0.355264, (11, 0): -0.404947, (11, 1): -0.020622, (11, 2): 0.648473, (11, 3): -0.277175, (11, 4): -0.711951 } y = { (0, 0): -0.494797, (0, 1): -0.212976, (0, 2): 0.085351, (0, 3): 0.35494, (0, 4): 0.571189, (1, 0): -0.421708, (1, 1): 0.061914, (1, 2): 0.238996, (1, 3): 0.146692, (1, 4): 0.407145, (2, 0): -0.313212, (2, 1): -0.225025, (2, 2): 0.031613, (2, 3): -0.047839, (2, 4): 0.42716, (3, 0): -0.361193, (3, 1): 0.057663, (3, 2): 0.022357, (3, 3): 0.062717, (3, 4): 0.150611, (4, 0): 0.035511, (4, 1): -0.271567, (4, 2): 0.007761, (4, 3): -0.124021, (4, 4): 0.093017, (5, 0): -0.238897, (5, 1): -0.179724, (5, 2): -0.113608, (5, 3): 0.017841, (5, 4): -0.012933, (6, 0): -0.166337, (6, 1): -0.272922, (6, 2): -0.194665, (6, 3): -0.058535, (6, 4): -0.405404, (7, 0): -0.318824, (7, 1): -0.311276, (7, 2): -0.205223, (7, 3): -0.292664, (7, 4): -0.474762, (8, 0): -0.039504, (8, 1): -0.239887, (8, 2): -0.343485, (8, 3): -0.459429, (8, 4): -0.426901, (9, 0): -0.187805, (9, 1): 0.282727, (9, 2): -0.601164, (9, 3): -0.467605, (9, 4): -0.589271, (10, 0): 0.028311, (10, 1): -0.391571, (10, 2): -0.463112, (10, 3): -0.358092, (10, 4): -0.285396, (11, 0): 0.01863, (11, 1): -0.380099, (11, 2): -0.234953, (11, 3): -0.593992, (11, 4): -0.801247 } distance = float( self._cif_header_dictionary['Detector_distance'].split()[0]) beam_xy = self._cif_header_dictionary['Beam_xy'].replace( '(', '').replace(')', '').replace(',', '').split()[:2] beam_x, beam_y = map(float, beam_xy) wavelength = float( self._cif_header_dictionary['Wavelength'].split()[0]) pixel_xy = self._cif_header_dictionary['Pixel_size'].replace( 'm', '').replace('x', '').split() pixel_x, pixel_y = map(float, pixel_xy) thickness = float( self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0 nx = int( self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension']) ny = int( self._cif_header_dictionary['X-Binary-Size-Second-Dimension']) overload = int( self._cif_header_dictionary['Count_cutoff'].split()[0]) underload = -1 # take into consideration here the thickness of the sensor also the # wavelength of the radiation (which we have in the same file...) from cctbx.eltbx import attenuation_coefficient table = attenuation_coefficient.get_table("Si") mu = table.mu_at_angstrom(wavelength) / 10.0 t0 = thickness # FIXME would also be very nice to be able to take into account the # misalignment of the individual modules given the calibration... # single detector or multi-module detector pixel_x *= 1000.0 pixel_y *= 1000.0 distance *= 1000.0 if not self._multi_panel: detector = self._detector_factory.simple( 'PAD', distance, (beam_x * pixel_x, beam_y * pixel_y), '+x', '-y', (pixel_x, pixel_y), (nx, ny), (underload, overload), [], ParallaxCorrectedPxMmStrategy(mu, t0)) for f0, s0, f1, s1 in determine_pilatus_mask(detector): detector[0].add_mask(f0, s0, f1, s1) detector[0].set_thickness(thickness) detector[0].set_material('Si') detector[0].set_mu(mu) return detector # got to here means 60-panel version from dxtbx.model.detector import Detector from scitbx import matrix d = Detector() beam_centre = matrix.col((beam_x * pixel_x, beam_y * pixel_y, 0)) fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0,-1.0, 0.0)) s0 = matrix.col((0, 0, -1)) origin = (distance * s0) - (fast * beam_centre[0]) - \ (slow * beam_centre[1]) root = d.hierarchy() root.set_local_frame( fast.elems, slow.elems, origin.elems) xmins = [0, 494, 988, 1482, 1976] xmaxes = [487, 981, 1475, 1969, 2463] ymins = [0, 212, 424, 636, 848, 1060, 1272, 1484, 1696, 1908, 2120, 2332] ymaxes = [195, 407, 619, 831, 1043, 1255, 1467, 1679, 1891, 2103, 2315, 2527] self.coords = {} fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, 1.0, 0.0)) panel_idx = 0 for ymin, ymax in zip(ymins, ymaxes): for xmin, xmax in zip(xmins, xmaxes): xmin_mm = xmin * pixel_x ymin_mm = ymin * pixel_y origin_panel = fast * xmin_mm + slow * ymin_mm panel_name = "Panel%d" % panel_idx panel_idx += 1 p = d.add_panel() p.set_type('SENSOR_PAD') p.set_name(panel_name) p.set_raw_image_offset((xmin, ymin)) p.set_image_size((xmax-xmin, ymax-ymin)) p.set_trusted_range((underload, overload)) p.set_pixel_size((pixel_x,pixel_y)) p.set_thickness(thickness) p.set_material('Si') p.set_mu(mu) p.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0)) p.set_local_frame( fast.elems, slow.elems, origin_panel.elems) p.set_raw_image_offset((xmin, ymin)) self.coords[panel_name] = (xmin,ymin,xmax,ymax) return d
def _detector(self): # module positions from detector blueprints - modelling at the moment as # 24 modules, each consisting of 5 sensors (the latter is ignored) from dxtbx.model import Detector from scitbx import matrix import math x = matrix.col((-1, 0, 0)) y = matrix.col((0, 1, 0)) z = matrix.col((0, 0, 1)) beam_xy = self._cif_header_dictionary["Beam_xy"] beam_xy = beam_xy.replace("(", "").replace(")", "").replace(",", "").split()[:2] obs_beam_x, obs_beam_y = [float(f) for f in beam_xy] ideal_beam_x = 1075 ideal_beam_y = 2594 beam_shift_x = 0.172 * (ideal_beam_x - obs_beam_x) beam_shift_y = 0.172 * (ideal_beam_y - obs_beam_y) distance = (float( self._cif_header_dictionary["Detector_distance"].split()[0]) * 1000.0) wavelength = float( self._cif_header_dictionary["Wavelength"].split()[0]) thickness = float( self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0 off_x = 184.9 detector = Detector() root = detector.hierarchy() root.set_frame( x.elems, y.elems, (-distance * z + (beam_shift_x * x) + (beam_shift_y * y)).elems, ) from cctbx.eltbx import attenuation_coefficient table = attenuation_coefficient.get_table("Si") mu = table.mu_at_angstrom(wavelength) / 10.0 t0 = thickness px_mm = ParallaxCorrectedPxMmStrategy(mu, t0) self.coords = {} for j in range(24): shift_y = 195 + 17 ymin, ymax = j * shift_y, j * shift_y + 195 angle = math.pi * (-12.2 + 0.5 * 7.903 + j * (7.903 + 0.441)) / 180.0 fast = matrix.col((1, 0, 0)) slow = matrix.col((0, math.sin(angle), math.cos(angle))) normal = fast.cross(slow) row_origin = 250.0 * normal - off_x * fast - 16.8 * slow if not self._multi_panel: xmin, xmax = 0, 2463 # OK two calls to add_panel here for detector like things => two # copies of the panel then? https://github.com/dials/dials/issues/189 # ... this is also not the source of the leak # OBS! you need to set the panel to a root before set local frame... p = root.add_panel() p.set_type("SENSOR_PAD") p.set_name("row-%02d" % j) p.set_raw_image_offset((xmin, ymin)) p.set_image_size((2463, 195)) p.set_trusted_range((-1, 1000000)) p.set_pixel_size((0.172, 0.172)) p.set_local_frame(fast.elems, slow.elems, row_origin.elems) p.set_thickness(thickness) p.set_material("Si") p.set_mu(mu) p.set_px_mm_strategy(px_mm) p.set_raw_image_offset((xmin, ymin)) self.coords[p.get_name()] = (xmin, ymin, xmax, ymax) else: shift_x = 487 + 7 for i in range(5): xmin, xmax = i * shift_x, i * shift_x + 487 origin = row_origin + i * (487 + 7) * 0.172 * fast # OBS! you need to set the panel to a root before set local frame... p = root.add_panel() p.set_type("SENSOR_PAD") p.set_name("row-%02d-col-%02d" % (j, i)) p.set_raw_image_offset((xmin, ymin)) p.set_image_size((487, 195)) p.set_trusted_range((-1, 1000000)) p.set_pixel_size((0.172, 0.172)) p.set_local_frame(fast.elems, slow.elems, origin.elems) p.set_thickness(thickness) p.set_material("Si") p.set_mu(mu) p.set_px_mm_strategy(px_mm) p.set_raw_image_offset((xmin, ymin)) self.coords[p.get_name()] = (xmin, ymin, xmax, ymax) return detector
def get_goniometer_shadow_masker(self, goniometer=None): from dials.util.masking import GoniometerShadowMaskGenerator from scitbx.array_family import flex import math coords = flex.vec3_double(((0, 0, 0), )) alpha = flex.double_range(0, 190, step=10) * math.pi / 180 r = flex.double(alpha.size(), 40) x = flex.double(r.size(), 107.61) y = -r * flex.sin(alpha) z = -r * flex.cos(alpha) coords.extend(flex.vec3_double(x, y, z)) coords.extend( flex.vec3_double(( # fixed (107.49, 7.84, 39.49), (107.39, 15.69, 38.97), (107.27, 23.53, 38.46), (107.16, 31.37, 37.94), (101.76, 33.99, 36.25), (96.37, 36.63, 34.56), (90.98, 39.25, 33.00), (85.58, 41.88, 31.18), (80.89, 47.06, 31.00), (76.55, 51.51, 31.03), (72.90, 55.04, 31.18), (66.86, 60.46, 31.67), (62.10, 64.41, 32.25), ))) alpha = flex.double_range(180, 370, step=10) * math.pi / 180 r = flex.double(alpha.size(), 33) x = flex.sqrt(flex.pow2(r * flex.sin(alpha)) + 89.02**2) * flex.cos( (50 * math.pi / 180) - flex.atan(r / 89.02 * flex.sin(alpha))) y = flex.sqrt(flex.pow2(r * flex.sin(alpha)) + 89.02**2) * flex.sin( (50 * math.pi / 180) - flex.atan(r / 89.02 * flex.sin(alpha))) z = -r * flex.cos(alpha) coords.extend(flex.vec3_double(x, y, z)) coords.extend( flex.vec3_double(( # fixed (62.10, 64.41, -32.25), (66.86, 60.46, -31.67), (72.90, 55.04, -31.18), (76.55, 51.51, -31.03), (80.89, 47.06, -31.00), (85.58, 41.88, -31.18), (90.98, 39.25, -33.00), (96.37, 36.63, -34.56), (101.76, 33.99, -36.25), (107.16, 31.37, -37.94), (107.27, 23.53, -38.46), (107.39, 15.69, -38.97), (107.49, 7.84, -39.49), (107.61, 0.00, -40.00), ))) # I23 end station coordinate system: # X-axis: positive direction is facing away from the storage ring (from # sample towards goniometer) # Y-axis: positive direction is vertically up # Z-axis: positive direction is in the direction of the beam (from # sample towards detector) # K-axis (kappa): at an angle of +50 degrees from the X-axis # K & phi rotation axes: clockwise rotation is positive (right hand # thumb rule) # Omega-axis: along the X-axis; clockwise rotation is positive # End station x-axis is parallel to ImgCIF x-axis # End station z-axis points in opposite direction to ImgCIF definition # (ImgCIF: The Z-axis is derived from the source axis which goes from # the sample to the source) # Consequently end station y-axis (to complete set following right hand # rule) points in opposite direction to ImgCIF y-axis. # Kappa arm aligned with -y in ImgCIF convention from rstbx.cftbx.coordinate_frame_helpers import align_reference_frame from scitbx import matrix R = align_reference_frame( matrix.col((1, 0, 0)), matrix.col((1, 0, 0)), matrix.col((0, 1, 0)), matrix.col((0, -1, 0)), ) coords = R.elems * coords if goniometer is None: goniometer = self.get_goniometer() return GoniometerShadowMaskGenerator(goniometer, coords, flex.size_t(len(coords), 1))
def find_basis_vectors(self, reciprocal_lattice_vectors): """Find a list of likely basis vectors. Args: reciprocal_lattice_vectors (scitbx.array_family.flex.vec3_double): The list of reciprocal lattice vectors to search for periodicity. Returns: A tuple containing the list of basis vectors and a flex.bool array identifying which reflections were used in indexing. """ if self._params.reciprocal_space_grid.d_min is libtbx.Auto: # rough calculation of suitable d_min based on max cell # see also Campbell, J. (1998). J. Appl. Cryst., 31(3), 407-413. # fft_cell should be greater than twice max_cell, so say: # fft_cell = 2.5 * max_cell # then: # fft_cell = n_points * d_min/2 # 2.5 * max_cell = n_points * d_min/2 # a little bit of rearrangement: # d_min = 5 * max_cell/n_points max_cell = self._max_cell d_min = 5 * max_cell / self._n_points d_spacings = 1 / reciprocal_lattice_vectors.norms() d_min = max(d_min, min(d_spacings)) logger.info("Setting d_min: %.2f" % d_min) else: d_min = self._params.reciprocal_space_grid.d_min grid_real, used_in_indexing = self._fft(reciprocal_lattice_vectors, d_min) self.sites, self.volumes = self._find_peaks(grid_real, d_min) # hijack the xray.structure class to facilitate calculation of distances self.crystal_symmetry = crystal.symmetry(unit_cell=self._fft_cell, space_group_symbol="P1") xs = xray.structure(crystal_symmetry=self.crystal_symmetry) for i, site in enumerate(self.sites): xs.add_scatterer(xray.scatterer("C%i" % i, site=site)) xs = xs.sites_mod_short() sites_cart = xs.sites_cart() lengths = flex.double([matrix.col(sc).length() for sc in sites_cart]) perm = flex.sort_permutation(lengths) xs = xs.select(perm) volumes = self.volumes.select(perm) vectors = xs.sites_cart() norms = vectors.norms() sel = (norms > self._min_cell) & (norms < (2 * self._max_cell)) vectors = vectors.select(sel) vectors = [matrix.col(v) for v in vectors] volumes = volumes.select(sel) vector_groups = group_vectors(vectors, volumes) vectors = [g.mean for g in vector_groups] volumes = flex.double(max(g.weights) for g in vector_groups) # sort by peak size perm = flex.sort_permutation(volumes, reverse=True) volumes = volumes.select(perm) vectors = [vectors[i] for i in perm] for i, (v, volume) in enumerate(zip(vectors, volumes)): logger.debug("%s %s %s" % (i, v.length(), volume)) # sort by length lengths = flex.double(v.length() for v in vectors) perm = flex.sort_permutation(lengths) # exclude vectors that are (approximately) integer multiples of a shorter # vector unique_vectors = [] unique_volumes = flex.double() for p in perm: v = vectors[p] is_unique = True for i, v_u in enumerate(unique_vectors): if (unique_volumes[i] > volumes[p] ) and is_approximate_integer_multiple(v_u, v): logger.debug("rejecting %s: integer multiple of %s" % (v.length(), v_u.length())) is_unique = False break if is_unique: unique_vectors.append(v) unique_volumes.append(volumes[p]) # re-sort by peak volume perm = flex.sort_permutation(unique_volumes, reverse=True) self.candidate_basis_vectors = [unique_vectors[i] for i in perm] return self.candidate_basis_vectors, used_in_indexing
def euler_angles_xyz_qE_as_euler_params_qE(qE): s1, s2, s3 = [math.sin(q / 2.) for q in qE] c1, c2, c3 = [math.cos(q / 2.) for q in qE] return matrix.col( (c1 * c2 * c3 + s1 * s2 * s3, c1 * c2 * s3 - s1 * s2 * c3, c1 * s2 * c3 + s1 * c2 * s3, s1 * c2 * c3 - c1 * s2 * s3))
def run_single(experiments1, filename): # Dump the file params = phil_scope.extract().nxs params.hklout = filename dials.util.nexus.dump(experiments1, None, params) # Load the file experiments2, reflections = dials.util.nexus.load(filename) assert experiments2 is not None assert reflections is None assert len(experiments2) == len(experiments1) index1 = [] index2 = [] for exp1, exp2 in zip(experiments1, experiments2): # Check the beam b1 = exp1.beam b2 = exp2.beam assert all( d1 == pytest.approx(d2) for d1, d2 in zip( b1.get_sample_to_source_direction(), b2.get_sample_to_source_direction() ) ) assert b1.get_wavelength() == pytest.approx(b2.get_wavelength()) assert b1.get_polarization_fraction() == pytest.approx( b2.get_polarization_fraction() ) n1 = matrix.col(b1.get_polarization_normal()) n2 = matrix.col(b2.get_polarization_normal()) angle = n2.angle(n1) assert ( angle == pytest.approx(0, abs=1e-7) or angle == pytest.approx(math.pi) or angle == pytest.approx(2 * math.pi) ) # Check the goniometer g1 = exp1.goniometer g2 = exp2.goniometer if g1 is None: assert g2 is None else: assert all( d1 == pytest.approx(d2) for d1, d2 in zip(g1.get_rotation_axis(), g2.get_rotation_axis()) ) assert all( d1 == pytest.approx(d2) for d1, d2 in zip(g1.get_fixed_rotation(), g2.get_fixed_rotation()) ) assert all( d1 == pytest.approx(d2) for d1, d2 in zip(g1.get_setting_rotation(), g2.get_setting_rotation()) ) # Check the scan s1 = exp1.scan s2 = exp2.scan if s1 is None: assert s2 is None else: assert len(s1) == len(s2) assert s1.get_image_range() == s2.get_image_range() assert s1.get_oscillation() == pytest.approx(s2.get_oscillation()) assert s1.get_exposure_times() == pytest.approx(s2.get_exposure_times()) assert s1.get_epochs() == pytest.approx(s2.get_epochs()) # Check the detector d1 = exp1.detector d2 = exp2.detector assert len(d1) == len(d2) for p1, p2 in zip(d1, d2): assert p1.get_type() == p2.get_type() assert p1.get_material() == p2.get_material() assert p1.get_thickness() == p2.get_thickness() assert p1.get_image_size() == p2.get_image_size() assert p1.get_pixel_size() == p2.get_pixel_size() assert p1.get_trusted_range() == p2.get_trusted_range() assert p1.get_fast_axis() == pytest.approx(p2.get_fast_axis()) assert p1.get_slow_axis() == pytest.approx(p2.get_slow_axis()) assert p1.get_origin() == pytest.approx(p2.get_origin()) # Check the crystal c1 = exp1.crystal c2 = exp2.crystal assert c1.get_space_group() == c2.get_space_group() assert c1.get_unit_cell().parameters() == pytest.approx( c2.get_unit_cell().parameters() ) assert c1.get_A() == pytest.approx(c2.get_A()) assert c1.num_scan_points == c2.num_scan_points for i in range(c1.num_scan_points): assert c1.get_A_at_scan_point(i) == pytest.approx(c2.get_A_at_scan_point(i)) uc1 = c1.get_unit_cell_at_scan_point(i) uc2 = c2.get_unit_cell_at_scan_point(i) assert uc1.parameters() == pytest.approx(uc2.parameters()) index1.append( ( id(exp1.beam), id(exp1.detector), id(exp1.goniometer), id(exp1.scan), id(exp1.crystal), ) ) index2.append( ( id(exp2.beam), id(exp2.detector), id(exp2.goniometer), id(exp2.scan), id(exp2.crystal), ) ) # Get a list of all beam etc beam1, detector1, goniometer1, scan1, crystal1 = zip(*index1) beam2, detector2, goniometer2, scan2, crystal2 = zip(*index2) # If any models are shared then check they are shared in both num = len(beam1) for i in range(0, num - 1): for j in range(1, num): assert (beam1[i] == beam1[j]) is (beam2[i] == beam2[j]) assert (detector1[i] == detector1[j]) is (detector2[i] == detector2[j]) assert (goniometer1[i] == goniometer1[j]) is ( goniometer2[i] == goniometer2[j] ) assert (scan1[i] == scan1[j]) is (scan2[i] == scan2[j]) assert (crystal1[i] == crystal1[j]) is (crystal2[i] == crystal2[j])
def new_q(O, q): return spherical(type=O.type, qE=matrix.col(q))
uc = unit_cell([5.01, 5.01, 5.47, 90.0, 90.0, 120.0]) bmat = matrix.sqr(uc.orthogonalization_matrix()).inverse().transpose() #---------------------------- # prove that the matrix bmat is consistent with the ewald_sphere class # requirements: # / A*x B*x C*x \ # Matrix A* = | A*y B*y C*y | # \ A*z B*z C*z / uc_reciprocal = uc.reciprocal() astar, bstar, cstar, alphastar, betastar, gammastar = uc_reciprocal.parameters( ) astar_vec = matrix.col([bmat[0], bmat[3], bmat[6]]) bstar_vec = matrix.col([bmat[1], bmat[4], bmat[7]]) cstar_vec = matrix.col([bmat[2], bmat[5], bmat[8]]) assert approx_equal(astar, math.sqrt(astar_vec.dot(astar_vec))) assert approx_equal(bstar, math.sqrt(bstar_vec.dot(bstar_vec))) assert approx_equal(cstar, math.sqrt(cstar_vec.dot(cstar_vec))) assert approx_equal(bstar * cstar * math.cos(math.pi * alphastar / 180), bstar_vec.dot(cstar_vec)) assert approx_equal(cstar * astar * math.cos(math.pi * betastar / 180), cstar_vec.dot(astar_vec)) assert approx_equal(astar * bstar * math.cos(math.pi * gammastar / 180), astar_vec.dot(bstar_vec)) # proof complete, bmat == A* #----------------------------
def random_vector(): v = matrix.col((1, 0, 0)).rotate_around_origin(matrix.col((0, 1, 0)), random.uniform(0, math.pi)) return v.rotate_around_origin(matrix.col((1, 0, 0)), random.uniform(0, 2.0 * math.pi)).normalize()
def new_q(O, q): return revolute(qE=matrix.col(q))
def exercise_frac_orth(): u = uctbx.unit_cell(()) assert approx_equal(u.fractionalization_matrix(), u.orthogonalization_matrix()) u = uctbx.unit_cell((2, 3, 5)) assert approx_equal(u.fractionalize((1, 2, 4)), (1 / 2., 2 / 3., 4 / 5.)) assert approx_equal(u.orthogonalize((1 / 2., 2 / 3., 4 / 5.)), (1, 2, 4)) assert approx_equal(u.fractionalize(flex.vec3_double([(1, 2, 4)])), [(1 / 2., 2 / 3., 4 / 5.)]) assert approx_equal( u.orthogonalize(flex.vec3_double([(1 / 2., 2 / 3., 4 / 5.)])), [(1, 2, 4)]) assert approx_equal( u.length((1 / 2., 2 / 3., 4 / 5.))**2, 1**2 + 2**2 + 4**2) assert approx_equal( u.distance((7 / 2., 8 / 3., 9 / 5.), (3, 2, 1))**2, 1**2 + 2**2 + 4**2) assert approx_equal(u.angle((0, 0, 0), (1 / 2., 0, 0), (1, 0, 0)), 180.) assert approx_equal( u.angle((0, 0, 0), (1 / 2., 0, 0), (1 / 2., 1 / 3., 0)), 90.) assert approx_equal( u.angle((1 / 2., 0, 0), (1 / 2., 1 / 3., 0), (0, 0, 0)), 45.) assert u.angle((0, 0, 0), (0, 0, 0), (1, 0, 0)) is None assert approx_equal( u.dihedral((0, 0, 0), (1 / 2., 0, 0), (1 / 2., 0, 1 / 5.), (1, 0, 1 / 5.)), 180.) assert approx_equal( u.dihedral((0, 0, 0), (1 / 2., 0, 0), (1 / 2., 0, 1 / 5.), (1 / 2., -1 / 3., 1 / 5.)), 90.) assert approx_equal( u.dihedral((0, 0, 0), (1 / 2., 0, 0), (1 / 2., 0, 1 / 5.), (1, -1 / 3., 1 / 5.)), 135.) assert approx_equal( u.dihedral((0, 0, 0), (1 / 2., 0, 0), (1 / 2., 0, 1 / 5.), (1, 1 / 3., 1 / 5.)), -135.) assert u.dihedral((0, 0, 0), (1 / 2., 0, 0), (1 / 2., 0, 0), (1, 0, 1 / 5.)) is None assert approx_equal(u.mod_short_length((1 / 4., 2 / 3., 4 / 5.)), u.length((1 / 4., -1 / 3., -1 / 5.))) assert approx_equal( u.mod_short_distance((13 / 4., 8 / 3., 9 / 5.), (3, 2, 1)), u.length((1 / 4., -1 / 3., -1 / 5.))) c = flex.vec3_double(((7 / 2., 8 / 3., 9 / 5.), (13 / 4., 8 / 3., 9 / 5.))) assert approx_equal( u.min_mod_short_distance(c, (3, 2, 1)), u.mod_short_distance((13 / 4., 8 / 3., 9 / 5.), (3, 2, 1))) # u = uctbx.unit_cell((13, 17, 19, 83, 111, 95)) fm = matrix.sqr(u.fractionalization_matrix()) assert ",".join(["%.3g" % e for e in fm.elems]) \ == "0.0769,0.00673,0.029,0,0.059,-0.00578,0,0,0.0566" om = matrix.sqr(u.orthogonalization_matrix()) assert ",".join(["%.3g" % e for e in om.elems]) \ == "13,-1.48,-6.81,0,16.9,1.73,0,0,17.7" gm = matrix.sqr(u.grid_index_as_site_cart_matrix(gridding=(11, 13, 17))) pg = matrix.col((5, -7, 23)) pf = matrix.col((5 / 11, -7 / 13, 23 / 17)) assert approx_equal(u.orthogonalize(pf), om * pf) assert approx_equal(gm * pg, om * pf) f = flex.vec3_double(flex.random_double(size=12) * 2 - 1) c = u.orthogonalize(sites_frac=f) assert approx_equal(u.fractionalize(sites_cart=c), f) for fi, ci in zip(f, c): assert approx_equal(u.orthogonalize(site_frac=fi), ci) assert approx_equal(u.fractionalize(site_cart=ci), fi) assert approx_equal(om * matrix.col(fi), ci) assert approx_equal(fm * matrix.col(ci), fi) # from cctbx import sgtbx s = sgtbx.rt_mx("-x,-x+y,-x+z", r_den=12) assert approx_equal(u.matrix_cart(rot_mx=s.r()), [ -0.3622586, -0.1191822, -0.5137527, -1.435689, 0.8743934, -0.5414459, -1.357969, -0.1188069, 0.4878651 ]) from scitbx.math import r3_rotation_axis_and_angle_from_matrix as from_matrix def check(u, sg): for s in sg: t = s.r().info().type() c = matrix.sqr(u.matrix_cart(rot_mx=s.r())) d = c.determinant() assert approx_equal(abs(d), 1) assert (t < 0) is (d < 0) fm = from_matrix(r=c * d) expected = { 1: [0], 2: [180, -180], 3: [120, -120], 4: [90, -90], 6: [60, -60] }[abs(t)] observed = round(fm.angle(deg=True)) if (observed not in expected): raise RuntimeError( "%s not in %s (%s)" % (str(observed), str(expected), s.r().as_xyz())) check( # primitive settig of space group No. 230 u=uctbx.unit_cell([10.911236359717213] * 3 + [109.47122063449069] * 3), sg=sgtbx.space_group("-I 4bd 2c 3 (y+z,x+z,x+y)")) check( # P 6/m m m u=uctbx.unit_cell((13, 13, 17, 90, 90, 120)), sg=sgtbx.space_group("-P 6 2"))
def tst_overlapping(reflections, overlapping, adjacency_list, image_size): """Ensure masks for overlapping reflections are set properly.""" from scitbx import matrix from dials.algorithms import shoebox # Loop through all overlaps shoeboxes = reflections["shoebox"] coord = reflections["xyzcal.px"] for i in overlapping: r1 = shoeboxes[i] bbox_1 = r1.bbox r1_coord = matrix.col(coord[i]) # Create a mask that we expect r1_size = (bbox_1[5] - bbox_1[4], bbox_1[3] - bbox_1[2], bbox_1[1] - bbox_1[0]) expected_mask = np.zeros(shape=r1_size, dtype=np.int32) expected_mask[:, :, :] = shoebox.MaskCode.Valid # Loop through all reflections which this reflection overlaps for j in adjacency_list.adjacent_vertices(i): r2 = shoeboxes[j] bbox_2 = r2.bbox r2_coord = matrix.col(coord[j]) # Get bounding box of intersection bbox_3 = ( max(bbox_1[0], bbox_2[0]), min(bbox_1[1], bbox_2[1]), max(bbox_1[2], bbox_2[2]), min(bbox_1[3], bbox_2[3]), max(bbox_1[4], bbox_2[4]), min(bbox_1[5], bbox_2[5]), ) # Check intersection is valid assert bbox_3[0] < bbox_3[1] assert bbox_3[2] < bbox_3[3] assert bbox_3[4] < bbox_3[5] # Get the coordinates are all mask values mask_coord = [] for k in range(bbox_3[4], bbox_3[5]): for j in range(bbox_3[2], bbox_3[3]): for i in range(bbox_3[0], bbox_3[1]): mask_coord.append( matrix.col((i + 0.5, j + 0.5, k + 0.5))) def dist(a, m): return np.array([(a - b).length() for b in m]) # Find the indices in the intersection area where r2 is closer to # the point than r1 ind = np.where( dist(r1_coord, mask_coord) > dist(r2_coord, mask_coord))[0] # Set the mask values for r1 where r2 is closer to 0 k0, k1 = bbox_3[4] - bbox_1[4], bbox_3[5] - bbox_1[4] j0, j1 = bbox_3[2] - bbox_1[2], bbox_3[3] - bbox_1[2] i0, i1 = bbox_3[0] - bbox_1[0], bbox_3[1] - bbox_1[0] intersect_mask = expected_mask[k0:k1, j0:j1, i0:i1] intersect_mask_1d = intersect_mask.reshape(-1) intersect_mask_1d[ind] = 0 intersect_mask[:, :] = intersect_mask_1d.reshape( intersect_mask.shape) expected_mask[k0:k1, j0:j1, i0:i1] = intersect_mask # Check the masks are the same calculated_mask = r1.mask.as_numpy_array() assert np.all(calculated_mask == expected_mask)
def find_basis_vector_combinations_cluster_analysis(self): self.fft() # hijack the xray.structure class to facilitate calculation of distances xs = xray.structure(crystal_symmetry=self.crystal_symmetry) for i, site in enumerate(self.sites): xs.add_scatterer(xray.scatterer("C%i" % i, site=site)) xs = xs.sites_mod_short() xs = xs.select(xs.sites_frac().norms() < 0.45) cell_multiplier = 10 xs1 = xs.customized_copy(unit_cell=uctbx.unit_cell( [xs.unit_cell().parameters()[0] * cell_multiplier] * 3)) xs1.set_sites_cart(xs.sites_cart()) xs = xs1 sites_cart = xs.sites_cart() lengths = flex.double([matrix.col(sc).length() for sc in sites_cart]) xs = xs.select(flex.sort_permutation(lengths)) if self.params.debug: with open('peaks.pdb', 'wb') as f: f.write(xs.as_pdb_file()) vector_heights = flex.double() sites_frac = xs.sites_frac() pair_asu_table = xs.pair_asu_table( distance_cutoff=self.params.max_cell) asu_mappings = pair_asu_table.asu_mappings() distances = crystal.calculate_distances(pair_asu_table, sites_frac) vectors = [] difference_vectors = [] pairs = [] for di in distances: if di.distance < self.params.min_cell: continue i_seq, j_seq = di.i_seq, di.j_seq if i_seq > j_seq: continue pairs.append((i_seq, j_seq)) rt_mx_ji = di.rt_mx_ji site_frac_ji = rt_mx_ji * sites_frac[j_seq] site_cart_ji = xs.unit_cell().orthogonalize(site_frac_ji) site_cart_i = xs.unit_cell().orthogonalize(sites_frac[i_seq]) vectors.append(matrix.col(site_cart_ji)) diff_vec = matrix.col(site_cart_i) - matrix.col(site_cart_ji) if diff_vec[0] < 0: # only one hemisphere of difference vector space diff_vec = -diff_vec difference_vectors.append(diff_vec) params = self.params.multiple_lattice_search.cluster_analysis if params.method == 'dbscan': i_cluster = self.cluster_analysis_dbscan(difference_vectors) min_cluster_size = 1 elif params.method == 'hcluster': i_cluster = self.cluster_analysis_hcluster(difference_vectors) i_cluster -= 1 # hcluster starts counting at 1 min_cluster_size = params.min_cluster_size if self.params.debug_plots: self.debug_plot_clusters(difference_vectors, i_cluster, min_cluster_size=min_cluster_size) clusters = [] min_cluster_size = params.min_cluster_size for i in range(max(i_cluster) + 1): isel = (i_cluster == i).iselection() if len(isel) < min_cluster_size: continue clusters.append(isel) cluster_point_sets = [] centroids = [] cluster_sizes = flex.int() difference_vectors = flex.vec3_double(difference_vectors) from libtbx.utils import flat_list for cluster in clusters: points = flat_list([pairs[i] for i in cluster]) cluster_point_sets.append(set(points)) d_vectors = difference_vectors.select(cluster) cluster_sizes.append(len(d_vectors)) centroids.append(d_vectors.mean()) # build a graph where each node is a centroid from the difference vector # cluster analysis above, and an edge is defined when there is a # significant overlap between the sets of peaks in the FFT map that # contributed to the difference vectors in two clusters import networkx as nx G = nx.Graph() G.add_nodes_from(range(len(cluster_point_sets))) cutoff_frac = 0.25 for i in range(len(cluster_point_sets)): for j in range(i + 1, len(cluster_point_sets)): intersection_ij = cluster_point_sets[i].intersection( cluster_point_sets[j]) union_ij = cluster_point_sets[i].union(cluster_point_sets[j]) frac_connected = len(intersection_ij) / len(union_ij) if frac_connected > cutoff_frac: G.add_edge(i, j) # iteratively find the maximum cliques in the graph # break from the loop if there are no cliques remaining or there are # fewer than 3 vectors in the remaining maximum clique # Allow 1 basis vector to be shared between two cliques, to allow for # cases where two lattices share one basis vectors (e.g. two plate # crystals exactly aligned in one direction, but not in the other two) distinct_cliques = [] cliques = list(nx.find_cliques(G)) cliques = sorted(cliques, key=len, reverse=True) for i, clique in enumerate(cliques): clique = set(clique) if len(clique) < 3: break is_distinct = True for c in distinct_cliques: if len(c.intersection(clique)) > 1: is_distinct = False break if is_distinct: distinct_cliques.append(clique) this_set = set() for i_cluster in clique: this_set = this_set.union(cluster_point_sets[i_cluster]) logger.info("Clique %i: %i lattice points" % (i + 1, len(this_set))) assert len(distinct_cliques) > 0 logger.info("Estimated number of lattices: %i" % len(distinct_cliques)) self.candidate_basis_vectors = [] self.candidate_crystal_models = [] for clique in distinct_cliques: sel = flex.size_t(list(clique)) vectors = flex.vec3_double(centroids).select(sel) perm = flex.sort_permutation(vectors.norms()) vectors = [matrix.col(vectors[p]) for p in perm] # exclude vectors that are (approximately) integer multiples of a shorter # vector unique_vectors = [] for v in vectors: is_unique = True for v_u in unique_vectors: if is_approximate_integer_multiple(v_u, v, relative_tolerance=0.01, angular_tolerance=0.5): is_unique = False break if is_unique: unique_vectors.append(v) vectors = unique_vectors self.candidate_basis_vectors.extend(vectors) candidate_orientation_matrices \ = self.find_candidate_orientation_matrices(vectors) if len(candidate_orientation_matrices) == 0: continue crystal_model, n_indexed = self.choose_best_orientation_matrix( candidate_orientation_matrices) if crystal_model is None: continue # map to minimum reduced cell crystal_symmetry = crystal.symmetry( unit_cell=crystal_model.get_unit_cell(), space_group=crystal_model.get_space_group()) cb_op = crystal_symmetry.change_of_basis_op_to_minimum_cell() crystal_model = crystal_model.change_basis(cb_op) self.candidate_crystal_models.append(crystal_model) if self.params.debug: file_name = "vectors.pdb" a = self.params.max_cell cs = crystal.symmetry(unit_cell=(a, a, a, 90, 90, 90), space_group="P1") xs = xray.structure(crystal_symmetry=cs) for v in difference_vectors: v = matrix.col(v) xs.add_scatterer(xray.scatterer("C", site=v / (a / 10))) xs.sites_mod_short() with open(file_name, 'wb') as f: f.write(xs.as_pdb_file()) for crystal_model in self.candidate_crystal_models: logger.debug(crystal_model)
def _detector(self): """Dummy detector""" from scitbx import matrix # 55 mu pixels pixel_size = 0.055, 0.055 trusted_range = (-1, 65535) material = "Si" thickness = 0.3 # assume 300 mu thick. This is actually in the header too # so could take it from there # Initialise detector frame - dummy origin to place detector at the header # distance along the canonical beam direction distance = (float( self._cif_header_dictionary["Detector_distance"].split()[0]) * 1000) fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, -1.0, 0.0)) cntr = matrix.col((0.0, 0.0, -100.0)) # shifts to go from the centre to the origin off_x = (self._array_size[0] / 2) * pixel_size[0] shift_x = -1.0 * fast * off_x off_y = (self._array_size[1] / 2) * pixel_size[1] shift_y = -1.0 * slow * off_y orig = cntr + shift_x + shift_y d = Detector() root = d.hierarchy() root.set_local_frame(fast.elems, slow.elems, orig.elems) self.coords = {} panel_idx = 0 # set panel extent in pixel numbers and x, y mm shifts. Origins taken from # an XDS.INP pnl_data = [] pnl_data.append({ "xmin": 0, "ymin": 0, "xmax": 516, "ymax": 516, "xmin_mm": 0, "ymin_mm": 0 }) pnl_data.append({ "xmin": 516, "ymin": 0, "xmax": 1032, "ymax": 516, "xmin_mm": (516 + 163.0) * pixel_size[0], "ymin_mm": -3.6969 * pixel_size[1], }) pnl_data.append({ "xmin": 0, "ymin": 516, "xmax": 516, "ymax": 1032, "xmin_mm": -2.5455 * pixel_size[0], "ymin_mm": (516 + 35.0) * pixel_size[1], }) pnl_data.append({ "xmin": 516, "ymin": 516, "xmax": 1032, "ymax": 1032, "xmin_mm": (516 + 165.866) * pixel_size[0], "ymin_mm": (516 + 32.4545) * pixel_size[1], }) # redefine fast, slow for the local frame fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, 1.0, 0.0)) for ipanel, pd in enumerate(pnl_data): xmin = pd["xmin"] xmax = pd["xmax"] ymin = pd["ymin"] ymax = pd["ymax"] xmin_mm = pd["xmin_mm"] ymin_mm = pd["ymin_mm"] origin_panel = fast * xmin_mm + slow * ymin_mm panel_name = "Panel%d" % panel_idx panel_idx += 1 p = d.add_panel() p.set_type("SENSOR_PAD") p.set_name(panel_name) p.set_raw_image_offset((xmin, ymin)) p.set_image_size((xmax - xmin, ymax - ymin)) p.set_trusted_range(trusted_range) p.set_pixel_size((pixel_size[0], pixel_size[1])) p.set_thickness(thickness) p.set_material("Si") # p.set_mu(mu) # p.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0)) p.set_local_frame(fast.elems, slow.elems, origin_panel.elems) p.set_raw_image_offset((xmin, ymin)) p.set_gain(3.0) # exact gain self.coords[panel_name] = (xmin, ymin, xmax, ymax) return d
def __init__(self, measurements_orig, params, i_model, miller_set, result, out): measurements = measurements_orig.deep_copy() # Now manipulate the data to conform to unit cell, asu, and space group # of reference. The resolution will be cut later. # Only works if there is NOT an indexing ambiguity! observations = measurements.customized_copy( anomalous_flag=not params.merge_anomalous, crystal_symmetry=miller_set.crystal_symmetry()).map_to_asu() observations_original_index = measurements.customized_copy( anomalous_flag=not params.merge_anomalous, crystal_symmetry=miller_set.crystal_symmetry()) # Ensure that match_multi_indices() will return identical results # when a frame's observations are matched against the # pre-generated Miller set, self.miller_set, and the reference # data set, self.i_model. The implication is that the same match # can be used to map Miller indices to array indices for intensity # accumulation, and for determination of the correlation # coefficient in the presence of a scaling reference. assert len(i_model.indices()) == len(miller_set.indices()) \ and (i_model.indices() == miller_set.indices()).count(False) == 0 matches = miller.match_multi_indices( miller_indices_unique=miller_set.indices(), miller_indices=observations.indices()) pair1 = flex.int([pair[1] for pair in matches.pairs()]) pair0 = flex.int([pair[0] for pair in matches.pairs()]) # narrow things down to the set that matches, only observations_pair1_selected = observations.customized_copy( indices=flex.miller_index( [observations.indices()[p] for p in pair1]), data=flex.double([observations.data()[p] for p in pair1]), sigmas=flex.double([observations.sigmas()[p] for p in pair1]), ) observations_original_index_pair1_selected = observations_original_index.customized_copy( indices=flex.miller_index( [observations_original_index.indices()[p] for p in pair1]), data=flex.double( [observations_original_index.data()[p] for p in pair1]), sigmas=flex.double( [observations_original_index.sigmas()[p] for p in pair1]), ) ################### I_observed = observations_pair1_selected.data() chosen = chosen_weights(observations_pair1_selected, params) MILLER = observations_original_index_pair1_selected.indices() ORI = result["current_orientation"][0] Astar = matrix.sqr(ORI.reciprocal_matrix()) WAVE = result["wavelength"] BEAM = matrix.col((0.0, 0.0, -1. / WAVE)) BFACTOR = 0. #calculation of correlation here I_reference = flex.double( [i_model.data()[pair[0]] for pair in matches.pairs()]) I_invalid = flex.bool( [i_model.sigmas()[pair[0]] < 0. for pair in matches.pairs()]) use_weights = False # New facility for getting variance-weighted correlation if use_weights: #variance weighting I_weight = flex.double([ 1. / (observations_pair1_selected.sigmas()[pair[1]])**2 for pair in matches.pairs() ]) else: I_weight = flex.double(len(observations_pair1_selected.sigmas()), 1.) I_weight.set_selected(I_invalid, 0.) chosen.set_selected(I_invalid, 0.) """Explanation of 'include_negatives' semantics as originally implemented in cxi.merge postrefinement: include_negatives = True + and - reflections both used for Rh distribution for initial estimate of RS parameter + and - reflections both used for calc/obs correlation slope for initial estimate of G parameter + and - reflections both passed to the refinery and used in the target function (makes sense if you look at it from a certain point of view) include_negatives = False + and - reflections both used for Rh distribution for initial estimate of RS parameter + reflections only used for calc/obs correlation slope for initial estimate of G parameter + and - reflections both passed to the refinery and used in the target function (makes sense if you look at it from a certain point of view) """ if params.include_negatives: SWC = simple_weighted_correlation(I_weight, I_reference, I_observed) else: non_positive = (observations_pair1_selected.data() <= 0) SWC = simple_weighted_correlation( I_weight.select(~non_positive), I_reference.select(~non_positive), I_observed.select(~non_positive)) print("Old correlation is", SWC.corr, file=out) assert params.postrefinement.algorithm == "rs_hybrid" Rhall = flex.double() for mill in MILLER: H = matrix.col(mill) Xhkl = Astar * H Rh = (Xhkl + BEAM).length() - (1. / WAVE) Rhall.append(Rh) Rs = math.sqrt(flex.mean(Rhall * Rhall)) RS = 1. / 10000. # reciprocal effective domain size of 1 micron RS = Rs # try this empirically determined approximate, monochrome, a-mosaic value self.rs2_current = flex.double([SWC.slope, BFACTOR, RS, 0., 0.]) self.rs2_parameterization_class = rs_parameterization self.rs2_refinery = rs2_refinery(ORI=ORI, MILLER=MILLER, BEAM=BEAM, WAVE=WAVE, ICALCVEC=I_reference, IOBSVEC=I_observed, WEIGHTS=chosen) self.rs2_refinery.set_profile_shape(params.postrefinement.lineshape) self.nave1_refinery = nave1_refinery(ORI=ORI, MILLER=MILLER, BEAM=BEAM, WAVE=WAVE, ICALCVEC=I_reference, IOBSVEC=I_observed, WEIGHTS=chosen) self.nave1_refinery.set_profile_shape(params.postrefinement.lineshape) self.out = out self.params = params self.miller_set = miller_set self.observations_pair1_selected = observations_pair1_selected self.observations_original_index_pair1_selected = observations_original_index_pair1_selected self.i_model = i_model
def XDS(self): sensor = self.get_detector().get_type() fast, slow = map(int, self.get_detector().get_image_size()) f, s = self.get_detector().get_pixel_size() df = int(1000 * f) ds = int(1000 * s) # FIXME probably need to rotate by pi about the X axis R = matrix.col( (1.0, 0.0, 0.0)).axis_and_angle_as_r3_rotation_matrix(180.0, deg=True) detector = xds_detector_name( detector_helpers_types.get(sensor, fast, slow, df, ds)) trusted = self.get_detector().get_trusted_range() print 'DETECTOR=%s MINIMUM_VALID_PIXEL_VALUE=%d OVERLOAD=%d' % \ (detector, trusted[0] + 1, trusted[1]) if detector == 'PILATUS': print 'SENSOR_THICKNESS= 0.32' print 'DIRECTION_OF_DETECTOR_X-AXIS= %.3f %.3f %.3f' % \ (R * self.get_detector().get_fast_axis()).elems print 'DIRECTION_OF_DETECTOR_Y-AXIS= %.3f %.3f %.3f' % \ (R * self.get_detector().get_slow_axis()).elems print 'NX=%d NY=%d QX=%.4f QY=%.4f' % (fast, slow, f, s) F = R * self.get_detector().get_fast_axis() S = R * self.get_detector().get_slow_axis() N = F.cross(S) origin = R * self.get_detector().get_origin() beam = R * self.get_beam().get_direction() / \ math.sqrt(matrix.col(self.get_beam().get_direction()).dot()) centre = -(origin - origin.dot(N) * N) x = centre.dot(F) y = centre.dot(S) print 'DETECTOR_DISTANCE= %.3f' % origin.dot(N) print 'ORGX= %.1f ORGY= %.1f' % (x / f, y / s) print 'ROTATION_AXIS= %.3f %.3f %.3f' % \ (R * self.get_goniometer().get_rotation_axis()).elems print 'STARTING_ANGLE= %.3f' % \ self.get_scan().get_oscillation()[0] print 'OSCILLATION_RANGE= %.3f' % \ self.get_scan().get_oscillation()[1] print 'X-RAY_WAVELENGTH= %.5f' % \ self.get_beam().get_wavelength() print 'INCIDENT_BEAM_DIRECTION= %.3f %.3f %.3f' % \ (- beam).elems print 'FRACTION_OF_POLARIZATION= %.3f' % \ self.get_beam().get_polarization_fraction() print 'POLARIZATION_PLANE_NORMAL= %.3f %.3f %.3f' % \ self.get_beam().get_polarization_normal() print 'NAME_TEMPLATE_OF_DATA_FRAMES= %s' % self._template.replace( '#', '?') print 'TRUSTED_REGION= 0.0 1.41' for f0, f1, s0, s1 in self.get_detector().get_mask(): print 'UNTRUSTED_RECTANGLE= %d %d %d %d' % \ (f0 - 1, f1 + 1, s0 - 1, s1 + 1) start_end = self.get_scan().get_image_range() if start_end[0] == 0: start_end = (1, start_end[1]) print 'DATA_RANGE= %d %d' % start_end print 'JOB=XYCORR INIT COLSPOT IDXREF DEFPIX INTEGRATE CORRECT'
def tst_outer_bounds(self): from scitbx import matrix from random import uniform from dials.algorithms.profile_model.gaussian_rs import CoordinateSystem assert (len(self.detector) == 1) s0 = self.beam.get_s0() m2 = self.gonio.get_rotation_axis() s0_length = matrix.col(self.beam.get_s0()).length() width, height = self.detector[0].get_image_size() zrange = self.scan.get_array_range() for i in range(1000): # Get random x, y, z x = uniform(0, 2000) y = uniform(0, 2000) z = uniform(0, 9) # Get random s1, phi, panel s1 = matrix.col(self.detector[0].get_pixel_lab_coord( (x, y))).normalize() * s0_length phi = self.scan.get_angle_from_array_index(z, deg=False) panel = 0 # Calculate the bounding box bbox = self.calculate_bbox(s1, z, panel) x1, x2 = bbox[0], bbox[1] y1, y2 = bbox[2], bbox[3] z1, z2 = bbox[4], bbox[5] # Calculate the rotation angle for each point phi_dash1 = self.scan.get_angle_from_array_index(z1, deg=False) phi_dash2 = self.scan.get_angle_from_array_index(z2, deg=False) # Create the XDS coordinate system xcs = CoordinateSystem(m2, s0, s1, phi) # Calculate reciprocal space coordinates at each point e11, e21, e31 = xcs.from_beam_vector_and_rotation_angle( s1, phi_dash1) e12, e22, e32 = xcs.from_beam_vector_and_rotation_angle( s1, phi_dash2) # Check vertical edges for j in range(bbox[2], bbox[3] + 1): xyz1 = self.detector[0].get_pixel_lab_coord((bbox[0], j)) xyz2 = self.detector[0].get_pixel_lab_coord((bbox[1] + 1, j)) sdash1 = matrix.col(xyz1).normalize() * s0_length sdash2 = matrix.col(xyz2).normalize() * s0_length e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle( sdash1, phi) e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle( sdash2, phi) if bbox[0] > 0 and bbox[1] < width: assert (abs(e11) >= self.delta_divergence or abs(e21) >= self.delta_divergence) assert (abs(e12) >= self.delta_divergence or abs(e22) >= self.delta_divergence) # Check horizontal edges for i in range(bbox[0], bbox[1] + 1): xyz1 = self.detector[0].get_pixel_lab_coord((i, bbox[2])) xyz2 = self.detector[0].get_pixel_lab_coord((i, bbox[3] + 1)) sdash1 = matrix.col(xyz1).normalize() * s0_length sdash2 = matrix.col(xyz2).normalize() * s0_length e11, e21, e3 = xcs.from_beam_vector_and_rotation_angle( sdash1, phi) e12, e22, e3 = xcs.from_beam_vector_and_rotation_angle( sdash2, phi) if bbox[2] > 0 and bbox[3] < height: assert (abs(e11) >= self.delta_divergence or abs(e21) >= self.delta_divergence) assert (abs(e12) >= self.delta_divergence or abs(e22) >= self.delta_divergence) # All e3 coords >= delta_mosaicity if bbox[4] > zrange[0] and bbox[5] < zrange[1]: assert (abs(e31) >= self.delta_mosaicity) assert (abs(e32) >= self.delta_mosaicity) print 'OK'
def find_candidate_basis_vectors(self): self.fft() # hijack the xray.structure class to facilitate calculation of distances xs = xray.structure(crystal_symmetry=self.crystal_symmetry) for i, site in enumerate(self.sites): xs.add_scatterer(xray.scatterer("C%i" % i, site=site)) xs = xs.sites_mod_short() sites_cart = xs.sites_cart() lengths = flex.double([matrix.col(sc).length() for sc in sites_cart]) perm = flex.sort_permutation(lengths) xs = xs.select(perm) volumes = self.volumes.select(perm) if self.params.debug: with open('peaks.pdb', 'wb') as f: f.write(xs.as_pdb_file()) sites_frac = xs.sites_frac() vectors = xs.sites_cart() norms = vectors.norms() sel = (norms > self.params.min_cell) & (norms < (2 * self.params.max_cell)) vectors = vectors.select(sel) vectors = [matrix.col(v) for v in vectors] volumes = volumes.select(sel) # XXX loop over these vectors and sort into groups similar to further down # group similar angle and lengths, also catch integer multiples of vectors vector_groups = [] relative_length_tolerance = 0.1 angle_tolerance = 5 # degrees orth = self.fft_cell.orthogonalize for v, volume in zip(vectors, volumes): length = v.length() if length < self.params.min_cell or length > ( 2 * self.params.max_cell): continue matched_group = False for group in vector_groups: mean_v = group.mean() mean_v_length = mean_v.length() if (abs(mean_v_length - length) / max(mean_v_length, length) < relative_length_tolerance): angle = mean_v.angle(v, deg=True) if angle < angle_tolerance: group.append(v, length, volume) matched_group = True break elif abs(180 - angle) < angle_tolerance: group.append(-v, length, volume) matched_group = True break if not matched_group: group = vector_group() group.append(v, length, volume) vector_groups.append(group) vectors = [g.mean() for g in vector_groups] volumes = flex.double(max(g.volumes) for g in vector_groups) ## sort by length #lengths = flex.double([v.length() for v in vectors]) #perm = flex.sort_permutation(lengths) # sort by peak size perm = flex.sort_permutation(volumes, reverse=True) volumes = volumes.select(perm) vectors = [vectors[i] for i in perm] for i, (v, volume) in enumerate(zip(vectors, volumes)): logger.debug("%s %s %s" % (i, v.length(), volume)) lengths = flex.double(v.length() for v in vectors) perm = flex.sort_permutation(lengths) # exclude vectors that are (approximately) integer multiples of a shorter # vector unique_vectors = [] unique_volumes = flex.double() for p in perm: v = vectors[p] is_unique = True for i, v_u in enumerate(unique_vectors): if ((unique_volumes[i] > volumes[p]) and is_approximate_integer_multiple(v_u, v)): logger.debug("rejecting %s: integer multiple of %s" % (v.length(), v_u.length())) is_unique = False break if is_unique: unique_vectors.append(v) unique_volumes.append(volumes[p]) # re-sort by peak volume perm = flex.sort_permutation(unique_volumes, reverse=True) vectors = [unique_vectors[i] for i in perm] volumes = unique_volumes.select(perm) #for i, (v, volume) in enumerate(zip(vectors, volumes)): #logger.debug("%s %s %s" %(i, v.length(), volume)) self.candidate_basis_vectors = vectors return self.candidate_basis_vectors
def test_ensure_axes_have_length_of_one(xdscoordinates): eps = 1e-7 assert abs(matrix.col(xdscoordinates["cs"].e1_axis()).length() - 1.0) <= eps assert abs(matrix.col(xdscoordinates["cs"].e2_axis()).length() - 1.0) <= eps assert abs(matrix.col(xdscoordinates["cs"].e3_axis()).length() - 1.0) <= eps
for ispot in range(len(pixel)): dials_roi = dials[ispot].roi pixel_roi = pixel[ispot].roi focus = dials_roi.focus() S = flex.double(range(focus[0])) F = flex.double(range(focus[1])) # matrix giving the slow coordinate: cslow = S.matrix_outer_product(flex.double([1] * focus[1])) # matrix giving the fast coordinate: cfast = flex.double([1] * focus[0]).matrix_outer_product(F) sum_dials_roi = flex.sum(dials_roi) dials_expectation_value = col( (flex.sum(cfast * dials_roi) / sum_dials_roi, flex.sum(cslow * dials_roi) / sum_dials_roi)) sum_pixel_roi = flex.sum(pixel_roi) pixel_expectation_value = col( (flex.sum(cfast * pixel_roi) / sum_pixel_roi, flex.sum(cslow * pixel_roi) / sum_pixel_roi)) delta_position = pixel_expectation_value - dials_expectation_value deltafast.append(delta_position[0]) deltaslow.append(delta_position[1]) print(delta_position.elems) from matplotlib import pyplot as plt #from IPython import embed; embed() statss = flex.mean_and_variance(deltaslow)
def plot_isotropic_umats(UMAT_nm, mos_spread_deg): # analysis of rotation angles from simtbx.nanoBragg.tst_gaussian_mosaicity import check_distributions angle_deg, rot_ax = check_distributions.get_angle_deg_and_axes(UMAT_nm) # in degrees nm_rms_angle = math.sqrt(flex.mean(angle_deg*angle_deg)) from matplotlib import pyplot as plt fig_angles,axis_angles = plt.subplots(1,1) axis_angles.set_xlabel("rotation (°)") axis_angles.hist(angle_deg,bins=int(math.sqrt(len(UMAT_nm)))) axis_angles.set_title( "Histogram of rotation angles\nrms %.4f° expected %.4f°"%(nm_rms_angle, mos_spread_deg)) # analysis of rotation axes fig, axes = plt.subplots(1, 3,figsize=(10,5)) axes[0].plot(rot_ax.parts()[0], rot_ax.parts()[1], "b,") # looking down from the pole axes[0].set_aspect("equal") axes[0].set_title("Rot_ax projected on z") axes[0].set_xlim(-1.1,1.1) axes[0].set_ylim(-1.1,1.1) axes[1].plot(rot_ax.parts()[1], rot_ax.parts()[2], "b,") # looking at equator above prime meridian axes[1].set_aspect("equal") axes[1].set_title("Rot_ax projected on x") axes[1].set_xlim(-1.1,1.1) axes[1].set_ylim(-1.1,1.1) axes[2].plot(rot_ax.parts()[2], rot_ax.parts()[0], "b,") # looking at equator above 90-deg meridian axes[2].set_aspect("equal") axes[2].set_title("Rot_ax projected on y") axes[2].set_xlim(-1.1,1.1) axes[2].set_ylim(-1.1,1.1) # action on unit vectors cube_diag = math.sqrt(1./3) # 0.57735 unit_vectors = [(1,0,0), (0,1,0), (0,0,1), (cube_diag, cube_diag, cube_diag)] fig3,axes3 = plt.subplots(1,4,sharey=True,figsize=(15,7)) axes3[0].set_ylabel("unit projection") for icol, RLP in enumerate(unit_vectors): RLP = col(RLP) axis = axes3[icol] unit = RLP.normalize() seed = col(unit_vectors[(icol+2)%(len(unit_vectors))]) perm2 = unit.cross(seed) perm3 = unit.cross(perm2) a2 = flex.double(); a3 = flex.double() angles_deg = flex.double() for u in UMAT_nm: U = sqr(u) newvec = U * unit angles_deg.append((180./math.pi)*math.acos(newvec.dot(unit))) a2.append(newvec.dot(perm2)); a3.append(newvec.dot(perm3)) rms_angle = math.sqrt(flex.mean(angles_deg*angles_deg)) axis.plot (a2,a3,'r,')[0] axis.set_aspect("equal") axis_str = "(%5.3f,%5.3f,%5.3f)"%(RLP.elems) if icol==3 else "(%.0f,%.0f,%.0f)"%(RLP.elems) axis.set_title("Transformation of unit vector\n%s\nrms %.4f° expected %.4f°"%( axis_str, rms_angle, math.sqrt(mos_spread_deg*mos_spread_deg*(2/3)))) # Pythagorean thm axis.set_xlabel("unit projection") axis.set_xlim(-0.0005,0.0005) axis.set_ylim(-0.0005,0.0005) plt.show()
def test_to_beamvector_xds_origin(beamvector): """Test the beam vector at the XDS origin is equal to s1.""" eps = 1e-7 s_dash = beamvector["cs"].to_beam_vector((0, 0)) assert abs(matrix.col(s_dash) - matrix.col(beamvector["s1"])) <= eps
def get_coefficients(self, ih): """ This function determines parameters for three cases: 1. planar geometry 2. two tetragonal CH2 geometry 3. H out of plane of its 3 neighbors (should be rare and not in AA) """ neighbors = self.h_connectivity[ih] if (neighbors.number_h_neighbors == 1): i_h1 = neighbors.h1['iseq'] else: i_h1 = None i_a0 = neighbors.a0['iseq'] i_a1 = neighbors.a1['iseq'] i_a2 = neighbors.a2['iseq'] rh = matrix.col(self.sites_cart[ih]) r0 = matrix.col(self.sites_cart[i_a0]) r1 = matrix.col(self.sites_cart[i_a1]) r2 = matrix.col(self.sites_cart[i_a2]) self.check_if_atoms_superposed(rh, r0, ih, i_a0) self.check_if_atoms_superposed(r1, r0, i_a1, i_a0) self.check_if_atoms_superposed(r2, r0, i_a2, i_a0) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() u20 = (r2 - r0).normalize() if self.use_ideal_bonds_angles: alpha0 = math.radians(neighbors.a0['angle_a1a0a2']) alpha1 = math.radians(neighbors.a1['angle_ideal']) alpha2 = math.radians(neighbors.a2['angle_ideal']) c0, c1, c2 = math.cos(alpha0), math.cos(alpha1), math.cos(alpha2) else: alpha0 = (u10).angle(u20) alpha0 = math.acos(u10.dot(u20)) alpha1 = (u10).angle(uh0) alpha2 = (uh0).angle(u20) c0 = (u10).dot(u20) c1 = (u10).dot(uh0) c2 = (uh0).dot(u20) sumang = alpha0 + alpha1 + alpha2 denom = (1.0 - c0**2) if (denom == 0): self.broadcast_problem(ih=ih, i_a0=i_a0) #raise RuntimeError( # "Denominator zero: (1-c0*c0) in get_h_parameterization.") a = (c1 - c0 * c2) / (1 - c0 * c0) b = (c2 - c0 * c1) / (1 - c0 * c0) root = None # # check if H, A0, A1, A2 are in a plane if (sumang < (2 * math.pi + 0.05) and (sumang > 2 * math.pi - 0.05)): h = None elif (sumang > (2 * math.pi + 0.05) and 1 - c1 * c1 - c2 * c2 - c0 * c0 + 2 * c0 * c1 * c2 < 0): root = 1 - c1 * c1 - c2 * c2 - c0 * c0 + 2 * c0 * c1 * c2 h = None return sumang, a, b, h, root else: # two tetragonal geometry: e.g. CH2 group if (i_h1 is not None): rh2 = matrix.col(self.sites_cart[neighbors.h1['iseq']]) #print(i_h1, neighbors.h1['iseq'], i_a0) self.check_if_atoms_superposed(rh2, r0, neighbors.h1['iseq'], i_a0) uh02 = (rh2 - r0).normalize() if self.use_ideal_bonds_angles: h = math.radians(neighbors.h1['angle_ideal']) * 0.5 else: h = (uh0).angle(uh02) * 0.5 #test if vector v points to same 'side' as uh0 if ((u10.cross(u20)).dot(uh0) < 0): h = -h else: # if H is out of plane, but not in tetrahedral geometry root = 1 - c1 * c1 - c2 * c2 - c0 * c0 + 2 * c0 * c1 * c2 if (root < 0): self.broadcast_problem( ih=ih, i_a0=i_a0, msg= '(Square root of zero in get_coefficients: H out of plane)' ) denom = math.sin(alpha0) if (denom == 0): self.broadcast_problem( ih=ih, i_a0=i_a0, msg= '(Denominator zero in get_coefficients: H out of plane)' ) cz = (math.sqrt(1 - c1 * c1 - c2 * c2 - c0 * c0 + 2 * c0 * c1 * c2)) / math.sin(alpha0) h = cz #test if vector v points to same 'side' as uh0 if ((u10.cross(u20)).dot(uh0) < 0): h = -h return sumang, a, b, h, root
def compose(self, reflections, skip_derivatives=False): """Compose scan-varying crystal parameterisations at the specified image number, for the specified experiment, for each image. Put the varying matrices in the reflection table, and cache the derivatives.""" self._prepare_for_compose(reflections, skip_derivatives) for iexp, exp in enumerate(self._experiments): # select the reflections of interest sel = reflections["id"] == iexp isel = sel.iselection() # skip empty experiments (https://github.com/dials/dials/issues/1417) if len(isel) == 0: continue blocks = reflections["block"].select(isel) # identify which parameterisations to use for this experiment xl_op = self._get_xl_orientation_parameterisation(iexp) xl_ucp = self._get_xl_unit_cell_parameterisation(iexp) bp = self._get_beam_parameterisation(iexp) dp = self._get_detector_parameterisation(iexp) gp = self._get_goniometer_parameterisation(iexp) # reset current frame cache for scan-varying parameterisations self._current_frame = {} # get state and derivatives for each block for block in range(flex.min(blocks), flex.max(blocks) + 1): # determine the subset of reflections this affects subsel = isel.select(blocks == block) if len(subsel) == 0: continue # get the panels hit by these reflections panels = reflections["panel"].select(subsel) # get the integer frame number nearest the centre of that block frames = reflections["block_centre"].select(subsel) # can only be false if original block assignment has gone wrong assert frames.all_eq( frames[0] ), "Failing: a block contains reflections that shouldn't be there" frame = int(math.floor(frames[0])) # model states at current frame U = self._get_state_from_parameterisation(xl_op, frame) if U is None: U = matrix.sqr(exp.crystal.get_U()) B = self._get_state_from_parameterisation(xl_ucp, frame) if B is None: B = matrix.sqr(exp.crystal.get_B()) s0 = self._get_state_from_parameterisation(bp, frame) if s0 is None: s0 = matrix.col(exp.beam.get_s0()) S = self._get_state_from_parameterisation(gp, frame) if S is None: S = matrix.sqr(exp.goniometer.get_setting_rotation()) # set states for crystal, beam and goniometer reflections["u_matrix"].set_selected(subsel, U.elems) reflections["b_matrix"].set_selected(subsel, B.elems) reflections["s0_vector"].set_selected(subsel, s0.elems) reflections["S_matrix"].set_selected(subsel, S.elems) # set states and derivatives for this detector if dp is not None: # detector is parameterised if dp.is_multi_state(): # parameterised detector is multi panel # loop through the panels in this detector for panel_id, _ in enumerate(exp.detector): # get the right subset of array indices to set for this panel subsel2 = subsel.select(panels == panel_id) if len(subsel2) == 0: # if no reflections intersect this panel, skip calculation continue dmat = self._get_state_from_parameterisation( dp, frame, multi_state_elt=panel_id ) if dmat is None: dmat = exp.detector[panel_id].get_d_matrix() Dmat = exp.detector[panel_id].get_D_matrix() reflections["d_matrix"].set_selected(subsel2, dmat) reflections["D_matrix"].set_selected(subsel2, Dmat) if self._varying_detectors and not skip_derivatives: for j, dd in enumerate( dp.get_ds_dp( multi_state_elt=panel_id, use_none_as_null=True ) ): if dd is None: continue self._derivative_cache.append(dp, j, dd, subsel) else: # parameterised detector is single panel dmat = self._get_state_from_parameterisation(dp, frame) if dmat is None: dmat = exp.detector[0].get_d_matrix() Dmat = exp.detector[0].get_D_matrix() reflections["d_matrix"].set_selected(subsel, dmat) reflections["D_matrix"].set_selected(subsel, Dmat) if self._varying_detectors and not skip_derivatives: for j, dd in enumerate(dp.get_ds_dp(use_none_as_null=True)): if dd is None: continue self._derivative_cache.append(dp, j, dd, subsel) else: # set states for unparameterised detector (dp is None) # loop through the panels in this detector for panel_id, _ in enumerate(exp.detector): # get the right subset of array indices to set for this panel subsel2 = subsel.select(panels == panel_id) if len(subsel2) == 0: # if no reflections intersect this panel, skip to the next continue dmat = exp.detector[panel_id].get_d_matrix() Dmat = exp.detector[panel_id].get_D_matrix() reflections["d_matrix"].set_selected(subsel2, dmat) reflections["D_matrix"].set_selected(subsel2, Dmat) # set derivatives of the states for crystal, beam and goniometer if not skip_derivatives: if xl_op is not None and self._varying_xl_orientations: for j, dU in enumerate(xl_op.get_ds_dp(use_none_as_null=True)): if dU is None: continue self._derivative_cache.append(xl_op, j, dU, subsel) if xl_ucp is not None and self._varying_xl_unit_cells: for j, dB in enumerate(xl_ucp.get_ds_dp(use_none_as_null=True)): if dB is None: continue self._derivative_cache.append(xl_ucp, j, dB, subsel) if bp is not None and self._varying_beams: for j, ds0 in enumerate(bp.get_ds_dp(use_none_as_null=True)): if ds0 is None: continue self._derivative_cache.append(bp, j, ds0, subsel) if gp is not None and self._varying_goniometers: for j, dS in enumerate(gp.get_ds_dp(use_none_as_null=True)): if dS is None: continue self._derivative_cache.append(gp, j, dS, subsel) # set the UB matrices for prediction reflections["ub_matrix"] = reflections["u_matrix"] * reflections["b_matrix"]
def process_1_neighbor_type_arg(self, neighbors): """ alg1a: X-H2 planar groups, such as in ARG, ASN, GLN requires that dihedral angle restraint exists for at least one H atom """ ih = neighbors.ih i_h1 = neighbors.h1['iseq'] i_a0 = neighbors.a0['iseq'] rh = matrix.col(self.sites_cart[ih]) r0 = matrix.col(self.sites_cart[i_a0]) if self.use_ideal_bonds_angles: disth = neighbors.a0['dist_ideal'] else: disth = (r0 - rh).length() i_a1 = neighbors.a1['iseq'] r1 = matrix.col(self.sites_cart[i_a1]) if ('dihedral_ideal' in neighbors.b1): ih_dihedral = ih ih_no_dihedral = i_h1 else: if ('dihedral_ideal' in self.h_connectivity[i_h1].b1): ih_dihedral = i_h1 ih_no_dihedral = ih else: self.unk_list.append(ih) return i_b1 = self.h_connectivity[ih_dihedral].b1['iseq'] rb1 = matrix.col(self.sites_cart[i_b1]) # check if angle is typical for propeller # catches case of missing propeller atom if (neighbors.h1['angle_ideal'] > 107 and neighbors.h1['angle_ideal'] < 111): self.unk_list.append(ih) else: dihedral = dihedral_angle(sites=[ self.sites_cart[i_b1], self.sites_cart[i_a1], self.sites_cart[i_a0], self.sites_cart[ih_dihedral] ]) self.check_if_atoms_superposed(rh, r0, ih, i_a0) self.check_if_atoms_superposed(r1, r0, i_a1, i_a0) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() if self.use_ideal_bonds_angles: alpha = math.radians(neighbors.a1['angle_ideal']) phi = math.radians( self.h_connectivity[ih_dihedral].b1['dihedral_ideal']) else: alpha = (u10).angle(uh0) phi = dihedral u1 = (r0 - r1).normalize() rb10 = rb1 - r1 # TODO check needed? u2 = (rb10 - ((rb10).dot(u10)) * u10).normalize() u3 = u1.cross(u2) for ih_alg1a, phi_alg1a in zip([ih_dihedral, ih_no_dihedral], [phi, phi + math.pi]): if self.h_parameterization[ih_alg1a] is None: self.h_parameterization[ih_alg1a] = riding_coefficients( htype='alg1a', ih=ih_alg1a, a0=i_a0, a1=i_a1, a2=i_b1, a3=-1, a=alpha, b=phi_alg1a, n=0, h=0, disth=disth)
def process_1_neighbor(self, neighbors): ih = neighbors.ih # if used for hydrogenate, make sure that first we use the H with dihedral angle # However, this needs some tweaking for neutron H/D situations if (neighbors.number_h_neighbors == 2): i_h1, i_h2 = neighbors.h1['iseq'], neighbors.h2['iseq'] if ('dihedral_ideal' in neighbors.b1): neighbors = self.h_connectivity[ih] elif ('dihedral_ideal' in self.h_connectivity[i_h1].b1): if self.h_parameterization[i_h1] is None: neighbors = self.h_connectivity[i_h1] elif ('dihedral_ideal' in self.h_connectivity[i_h2].b1): if self.h_parameterization[i_h2] is None: neighbors = self.h_connectivity[i_h2] ih = neighbors.ih #print(self.site_labels[ih]) i_a0 = neighbors.a0['iseq'] rh = matrix.col(self.sites_cart[ih]) r0 = matrix.col(self.sites_cart[i_a0]) if self.use_ideal_bonds_angles: disth = neighbors.a0['dist_ideal'] else: disth = (r0 - rh).length() if (not neighbors.a1 or not neighbors.b1): self.unk_list.append(ih) return i_a1 = neighbors.a1['iseq'] i_b1 = neighbors.b1['iseq'] r1 = matrix.col(self.sites_cart[i_a1]) rb1 = matrix.col(self.sites_cart[i_b1]) self.check_if_atoms_superposed(rh, r0, ih, i_a0) self.check_if_atoms_superposed(r1, r0, i_a1, i_a0) uh0 = (rh - r0).normalize() u10 = (r1 - r0).normalize() dihedral = dihedral_angle(sites=[ self.sites_cart[ih], self.sites_cart[i_a0], self.sites_cart[i_a1], self.sites_cart[i_b1] ]) if self.use_ideal_bonds_angles: alpha = math.radians(neighbors.a1['angle_ideal']) #allow for rotation even for idealize = True phi = dihedral if self.use_ideal_dihedral: #phi = math.radians(b1.dihedral_ideal) if 'dihedral_ideal' in neighbors.b1: phi = math.radians(neighbors.b1['dihedral_ideal']) else: alpha = (u10).angle(uh0) phi = dihedral #print(math.degrees(phi)) u1 = (r0 - r1).normalize() rb10 = rb1 - r1 # TODO check needed? u2 = (rb10 - ((rb10).dot(u1)) * u1).normalize() u3 = u1.cross(u2) if (neighbors.number_h_neighbors == 0): self.h_parameterization[ih] = riding_coefficients(htype='alg1b', ih=ih, a0=i_a0, a1=i_a1, a2=i_b1, a3=-1, a=alpha, b=phi, h=0, n=0, disth=disth) if (neighbors.number_h_neighbors == 2): i_h1, i_h2 = neighbors.h1['iseq'], neighbors.h2['iseq'] i_h1, i_h2 = self.check_propeller_order(i_a0=i_a0, i_a1=i_a1, ih=ih, i_h1=i_h1, i_h2=i_h2) for nprop, hprop in zip([0, 1, 2], [ih, i_h1, i_h2]): self.h_parameterization[hprop] = riding_coefficients( htype='prop', ih=hprop, a0=i_a0, a1=i_a1, a2=i_b1, a3=-1, a=alpha, n=nprop, b=phi, h=0, disth=disth)