def rotation_scattering(reflections, UB_mat, rotation_vector, wavelength, resolution, assert_non_integer_index=False): '''Perform some kind of calculation...''' ra = rotation_angles(resolution, UB_mat, wavelength, rotation_vector) beam_vector = matrix.col([0, 0, 1 / wavelength]) for hkl in reflections: if ra(hkl): omegas = ra.get_intersection_angles() if assert_non_integer_index: assert ra.H[0] != int(ra.H[0]) or \ ra.H[1] != int(ra.H[1]) or \ ra.H[2] != int(ra.H[2]) for omegaidx in [0, 1]: rot_mat = rotation_vector.axis_and_angle_as_r3_rotation_matrix( omegas[omegaidx]) assert (-0.0001 < math.fabs(rot_mat.determinant() - 1.0) < 0.0001) H1 = (rot_mat * UB_mat) * hkl H1 = H1 + beam_vector len_H1 = math.sqrt((H1[0] * H1[0]) + (H1[1] * H1[1]) + (H1[2] * H1[2])) if math.fabs(len_H1 - 1.0 / wavelength) > 0.0001: raise RuntimeError, 'length error for %d %d %d' % hkl
def observed_indices_and_angles_from_angle_range( self, phi_start_rad, phi_end_rad, indices ): """For a list of indices, return those indices that can be rotated into diffracting position, along with the corresponding angles""" # calculate conversion matrix to rossmann frame. R_to_rossmann = self.align_reference_frame( self._beam.get_unit_s0(), (0.0, 0.0, 1.0), self._gonio.get_rotation_axis(), (0.0, 1.0, 0.0), ) # Create a rotation_angles object for the current geometry ra = rotation_angles( self._dmin, R_to_rossmann * self._crystal.get_U() * self._crystal.get_B(), self._beam.get_wavelength(), R_to_rossmann * matrix.col(self._gonio.get_rotation_axis()), ) (obs_indices, obs_angles) = ra.observed_indices_and_angles_from_angle_range( phi_start_rad=0.0, phi_end_rad=pi, indices=indices ) # convert to integer miller indices obs_indices_int = flex.miller_index() for hkl in obs_indices: hkl = map(lambda x: int(round(x)), hkl) obs_indices_int.append(tuple(hkl)) return obs_indices_int, obs_angles
def predict(self, hkl): """Solve the prediction formula for the reflecting angle phi""" # calculate conversion matrix to rossmann frame. R_to_rossmann = self.align_reference_frame( self._beam.get_unit_s0(), (0.0, 0.0, 1.0), self._gonio.get_rotation_axis(), (0.0, 1.0, 0.0), ) # Create a rotation_angles object for the current geometry ra = rotation_angles( self._dmin, R_to_rossmann * self._crystal.get_U() * self._crystal.get_B(), self._beam.get_wavelength(), R_to_rossmann * matrix.col(self._gonio.get_rotation_axis()), ) if ra(hkl): return ra.get_intersection_angles() else: return None
def observed_indices_and_angles_from_angle_range(self, phi_start_rad, phi_end_rad, indices): """For a list of indices, return those indices that can be rotated into diffracting position, along with the corresponding angles""" # calculate conversion matrix to rossmann frame. R_to_rossmann = self.align_reference_frame( self._beam.get_unit_s0(), (0.0, 0.0, 1.0), self._gonio.get_rotation_axis(), (0.0, 1.0, 0.0)) # Create a rotation_angles object for the current geometry ra = rotation_angles(self._dmin, R_to_rossmann * self._crystal.get_U() * self._crystal.get_B(), self._beam.get_wavelength(), R_to_rossmann * matrix.col(self._gonio.get_rotation_axis())) (obs_indices, obs_angles) = ra.observed_indices_and_angles_from_angle_range( phi_start_rad = 0.0, phi_end_rad = pi, indices = indices) # convert to integer miller indices obs_indices_int = flex.miller_index() for hkl in obs_indices: hkl = map(lambda x: int(round(x)), hkl) obs_indices_int.append(tuple(hkl)) return obs_indices_int, obs_angles
def rotation_scattering(reflections, UB_mat, rotation_vector, wavelength, resolution, assert_non_integer_index = False): '''Perform some kind of calculation...''' ra = rotation_angles(resolution, UB_mat, wavelength, rotation_vector) beam_vector = matrix.col([0, 0, 1 / wavelength]) for hkl in reflections: if ra(hkl): omegas = ra.get_intersection_angles() if assert_non_integer_index: assert ra.H[0] != int(ra.H[0]) or \ ra.H[1] != int(ra.H[1]) or \ ra.H[2] != int(ra.H[2]) for omegaidx in [0,1]: rot_mat = rotation_vector.axis_and_angle_as_r3_rotation_matrix( omegas[omegaidx]) assert( -0.0001 < math.fabs(rot_mat.determinant() - 1.0) < 0.0001) H1 = (rot_mat * UB_mat)*hkl H1 = H1 + beam_vector len_H1 = math.sqrt((H1[0] * H1[0]) + (H1[1] * H1[1]) + (H1[2] * H1[2])) if math.fabs(len_H1 - 1.0 / wavelength) > 0.0001: raise RuntimeError, 'length error for %d %d %d' % hkl
def get_predicted_spot_positions_and_status( self, old_status=None ): #similar to above function; above can be refactored panel = self.detector[0] from scitbx import matrix Astar = matrix.sqr(self.getOrientation().reciprocal_matrix()) # must have set the basis in order to generate Astar matrix. How to assert this has been done??? import math, copy xyz = self.getXyzData() if old_status is None: spot_status = [SpotClass.GOOD] * len(xyz) else: assert len(old_status) == len(xyz) spot_status = copy.copy( old_status) # valid way of copying enums w/o reference self.assigned_hkl = [(0, 0, 0)] * len(xyz) # step 1. Deduce fractional HKL values from the XyzData. start with x = A* h # solve for h: h = (A*^-1) x Astarinv = Astar.inverse() Hint = flex.vec3_double() results = flex.vec3_double() for x in xyz: H = Astarinv * x Hint.append((round(H[0], 0), round(H[1], 0), round(H[2], 0))) xyz_miller = flex.vec3_double() from rstbx.diffraction import rotation_angles ra = rotation_angles(limiting_resolution=1.0, orientation=Astar, wavelength=1. / self.inv_wave, axial_direction=self.axis) for ij, hkl in enumerate(Hint): xyz_miller.append( Astar * hkl) # figure out how to do this efficiently on vector data if ra(hkl): omegas = ra.get_intersection_angles() rotational_diffs = [ abs((-omegas[omegaidx] * 180. / math.pi) - self.raw_spot_input[ij][2]) for omegaidx in [0, 1] ] min_diff = min(rotational_diffs) min_index = rotational_diffs.index(min_diff) omega = omegas[min_index] rot_mat = self.axis.axis_and_angle_as_r3_rotation_matrix(omega) Svec = (rot_mat * Astar) * hkl + self.S0_vector if self.panelID is not None: panel = self.detector[self.panelID[ij]] xy = panel.get_ray_intersection(Svec) results.append((xy[0], xy[1], 0.0)) self.assigned_hkl[ij] = hkl else: results.append((0.0, 0.0, 0.0)) spot_status[ij] = SpotClass.NONE return results, spot_status
def model_likelihood(self, separation_mm): TOLERANCE = 0.5 fraction_properly_predicted = 0.0 #help(self.detector) #print self.detector[0] #help(self.detector[0]) panel = self.detector[0] from scitbx import matrix Astar = matrix.sqr(self.getOrientation().reciprocal_matrix()) import math xyz = self.getXyzData() # step 1. Deduce fractional HKL values from the XyzData. start with x = A* h # solve for h: h = (A*^-1) x Astarinv = Astar.inverse() Hint = flex.vec3_double() for x in xyz: H = Astarinv * x #print "%7.3f %7.3f %7.3f"%(H[0],H[1],H[2]) Hint.append((round(H[0], 0), round(H[1], 0), round(H[2], 0))) xyz_miller = flex.vec3_double() from rstbx.diffraction import rotation_angles # XXX limiting shell of 1.0 angstroms probably needs to be changed/ removed. How? ra = rotation_angles(limiting_resolution=1.0, orientation=Astar, wavelength=1. / self.inv_wave, axial_direction=self.axis) for ij, hkl in enumerate(Hint): xyz_miller.append( Astar * hkl) # figure out how to do this efficiently on vector data if ra(hkl): omegas = ra.get_intersection_angles() rotational_diffs = [ abs((-omegas[omegaidx] * 180. / math.pi) - self.raw_spot_input[ij][2]) for omegaidx in [0, 1] ] min_diff = min(rotational_diffs) min_index = rotational_diffs.index(min_diff) omega = omegas[min_index] rot_mat = self.axis.axis_and_angle_as_r3_rotation_matrix(omega) Svec = (rot_mat * Astar) * hkl + self.S0_vector # print panel.get_ray_intersection(Svec), self.raw_spot_input[ij] if self.panelID is not None: panel = self.detector[self.panelID[ij]] calc = matrix.col(panel.get_ray_intersection(Svec)) pred = matrix.col(self.raw_spot_input[ij][0:2]) # print (calc-pred).length(), separation_mm * TOLERANCE if ((calc - pred).length() < separation_mm * TOLERANCE): fraction_properly_predicted += 1. / self.raw_spot_input.size( ) #print "fraction properly predicted",fraction_properly_predicted,"with spot sep (mm)",separation_mm return fraction_properly_predicted
def regression_test(): """Perform a regression test by comparing to indices generating by the brute force method used in the Use Case.""" from rstbx.diffraction import rotation_angles from rstbx.diffraction import full_sphere_indices from cctbx.sgtbx import space_group, space_group_symbols from cctbx.uctbx import unit_cell # cubic, 50A cell, 1A radiation, 1 deg osciillation, everything ideal a = 50.0 ub_beg = matrix.sqr( (1.0 / a, 0.0, 0.0, 0.0, 1.0 / a, 0.0, 0.0, 0.0, 1.0 / a)) axis = matrix.col((0, 1, 0)) r_osc = matrix.sqr( scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=axis, angle=1.0, deg=True)) ub_end = r_osc * ub_beg uc = unit_cell((a, a, a, 90, 90, 90)) sg = space_group(space_group_symbols('P23').hall()) s0 = matrix.col((0, 0, 1)) wavelength = 1.0 dmin = 1.5 indices = full_sphere_indices(unit_cell=uc, resolution_limit=dmin, space_group=sg) ra = rotation_angles(dmin, ub_beg, wavelength, axis) obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range( phi_start_rad=0.0 * pi / 180.0, phi_end_rad=1.0 * pi / 180.0, indices=indices) r = reeke_model(ub_beg, ub_end, axis, s0, dmin, 1.0) reeke_indices = r.generate_indices() #r.visualize_with_rgl() for oi in obs_indices: assert (tuple(map(int, oi)) in reeke_indices) #TODO Tests for an oblique cell print "OK"
def model_likelihood(self,separation_mm): TOLERANCE = 0.5 fraction_properly_predicted = 0.0 #help(self.detector) #print self.detector[0] #help(self.detector[0]) panel = self.detector[0] from scitbx import matrix Astar = matrix.sqr(self.getOrientation().reciprocal_matrix()) import math xyz = self.getXyzData() # step 1. Deduce fractional HKL values from the XyzData. start with x = A* h # solve for h: h = (A*^-1) x Astarinv = Astar.inverse() Hint = flex.vec3_double() for x in xyz: H = Astarinv * x #print "%7.3f %7.3f %7.3f"%(H[0],H[1],H[2]) Hint.append((round(H[0],0), round(H[1],0), round(H[2],0))) xyz_miller = flex.vec3_double() from rstbx.diffraction import rotation_angles # XXX limiting shell of 1.0 angstroms probably needs to be changed/ removed. How? ra = rotation_angles(limiting_resolution=1.0,orientation = Astar, wavelength = 1./self.inv_wave, axial_direction = self.axis) for ij,hkl in enumerate(Hint): xyz_miller.append( Astar * hkl ) # figure out how to do this efficiently on vector data if ra(hkl): omegas = ra.get_intersection_angles() rotational_diffs = [ abs((-omegas[omegaidx] * 180./math.pi)-self.raw_spot_input[ij][2]) for omegaidx in [0,1] ] min_diff = min(rotational_diffs) min_index = rotational_diffs.index(min_diff) omega = omegas[min_index] rot_mat = self.axis.axis_and_angle_as_r3_rotation_matrix(omega) Svec = (rot_mat * Astar) * hkl + self.S0_vector # print panel.get_ray_intersection(Svec), self.raw_spot_input[ij] if self.panelID is not None: panel = self.detector[ self.panelID[ij] ] calc = matrix.col(panel.get_ray_intersection(Svec)) pred = matrix.col(self.raw_spot_input[ij][0:2]) # print (calc-pred).length(), separation_mm * TOLERANCE if ((calc-pred).length() < separation_mm * TOLERANCE): fraction_properly_predicted += 1./ self.raw_spot_input.size() #print "fraction properly predicted",fraction_properly_predicted,"with spot sep (mm)",separation_mm return fraction_properly_predicted
def scattering_prediction(reflections, UB_mat, rotation_vector, wavelength, resolution, assert_non_integer_index=False): '''Test the reflection_prediction class.''' ra = rotation_angles(resolution, UB_mat, wavelength, rotation_vector) beam_vector = matrix.col([0, 0, 1 / wavelength]) detector_size = 100 detector_distance = 100 s = sensor( matrix.col( (-0.5 * detector_size, -0.5 * detector_size, detector_distance)), matrix.col((1, 0, 0)), matrix.col((0, 1, 0)), (0, detector_size), (0, detector_size)) rp = reflection_prediction(rotation_vector, beam_vector, UB_mat, s) for hkl in reflections: if ra(hkl): omegas = ra.get_intersection_angles() if assert_non_integer_index: assert ra.H[0] != int(ra.H[0]) or \ ra.H[1] != int(ra.H[1]) or \ ra.H[2] != int(ra.H[2]) for omegaidx in [0, 1]: rot_mat = rotation_vector.axis_and_angle_as_r3_rotation_matrix( omegas[omegaidx]) assert (math.fabs(rot_mat.determinant() - 1.0) < 0.0001) H1 = (rot_mat * UB_mat) * hkl H1 = H1 + beam_vector len_H1 = math.sqrt((H1[0] * H1[0]) + (H1[1] * H1[1]) + (H1[2] * H1[2])) if math.fabs(len_H1 - 1.0 / wavelength) > 0.0001: raise RuntimeError, 'length error for %d %d %d' % hkl if rp(hkl, omegas[omegaidx]): x, y = rp.get_prediction() assert (0 < x < detector_size) assert (0 < y < detector_size)
def get_predicted_spot_positions_and_status(self, old_status=None): #similar to above function; above can be refactored panel = self.detector[0] from scitbx import matrix Astar = matrix.sqr(self.getOrientation().reciprocal_matrix()) # must have set the basis in order to generate Astar matrix. How to assert this has been done??? import math,copy xyz = self.getXyzData() if old_status is None: spot_status = [SpotClass.GOOD]*len(xyz) else: assert len(old_status)==len(xyz) spot_status = copy.copy( old_status ) # valid way of copying enums w/o reference self.assigned_hkl= [(0,0,0)]*len(xyz) # step 1. Deduce fractional HKL values from the XyzData. start with x = A* h # solve for h: h = (A*^-1) x Astarinv = Astar.inverse() Hint = flex.vec3_double() results = flex.vec3_double() for x in xyz: H = Astarinv * x Hint.append((round(H[0],0), round(H[1],0), round(H[2],0))) xyz_miller = flex.vec3_double() from rstbx.diffraction import rotation_angles ra = rotation_angles(limiting_resolution=1.0,orientation = Astar, wavelength = 1./self.inv_wave, axial_direction = self.axis) for ij,hkl in enumerate(Hint): xyz_miller.append( Astar * hkl ) # figure out how to do this efficiently on vector data if ra(hkl): omegas = ra.get_intersection_angles() rotational_diffs = [ abs((-omegas[omegaidx] * 180./math.pi)-self.raw_spot_input[ij][2]) for omegaidx in [0,1] ] min_diff = min(rotational_diffs) min_index = rotational_diffs.index(min_diff) omega = omegas[min_index] rot_mat = self.axis.axis_and_angle_as_r3_rotation_matrix(omega) Svec = (rot_mat * Astar) * hkl + self.S0_vector if self.panelID is not None: panel = self.detector[ self.panelID[ij] ] xy = panel.get_ray_intersection(Svec) results.append((xy[0],xy[1],0.0)) self.assigned_hkl[ij]=hkl else: results.append((0.0,0.0,0.0)) spot_status[ij]=SpotClass.NONE return results,spot_status
def scattering_prediction(reflections, UB_mat, rotation_vector, wavelength, resolution, assert_non_integer_index = False): '''Test the reflection_prediction class.''' ra = rotation_angles(resolution, UB_mat, wavelength, rotation_vector) beam_vector = matrix.col([0, 0, 1 / wavelength]) detector_size = 100 detector_distance = 100 s = sensor(matrix.col((- 0.5 * detector_size, - 0.5 * detector_size, detector_distance)), matrix.col((1, 0, 0)), matrix.col((0, 1, 0)), (0, detector_size), (0, detector_size)) rp = reflection_prediction(rotation_vector, beam_vector, UB_mat, s) for hkl in reflections: if ra(hkl): omegas = ra.get_intersection_angles() if assert_non_integer_index: assert ra.H[0] != int(ra.H[0]) or \ ra.H[1] != int(ra.H[1]) or \ ra.H[2] != int(ra.H[2]) for omegaidx in [0,1]: rot_mat = rotation_vector.axis_and_angle_as_r3_rotation_matrix( omegas[omegaidx]) assert(math.fabs(rot_mat.determinant() - 1.0) < 0.0001) H1 = (rot_mat * UB_mat)*hkl H1 = H1 + beam_vector len_H1 = math.sqrt((H1[0] * H1[0]) + (H1[1] * H1[1]) + (H1[2] * H1[2])) if math.fabs(len_H1 - 1.0 / wavelength) > 0.0001: raise RuntimeError, 'length error for %d %d %d' % hkl if rp(hkl, omegas[omegaidx]): x, y = rp.get_prediction() assert(0 < x < detector_size) assert(0 < y < detector_size)
def regression_test(): """Perform a regression test by comparing to indices generating by the brute force method used in the Use Case.""" from rstbx.diffraction import rotation_angles from rstbx.diffraction import full_sphere_indices from cctbx.sgtbx import space_group, space_group_symbols from cctbx.uctbx import unit_cell # cubic, 50A cell, 1A radiation, 1 deg osciillation, everything ideal a = 50.0 ub_beg = matrix.sqr((1.0 / a, 0.0, 0.0, 0.0, 1.0 / a, 0.0, 0.0, 0.0, 1.0 / a)) axis = matrix.col((0, 1, 0)) r_osc = matrix.sqr(scitbx.math.r3_rotation_axis_and_angle_as_matrix(axis=axis, angle=1.0, deg=True)) ub_end = r_osc * ub_beg uc = unit_cell((a, a, a, 90, 90, 90)) sg = space_group(space_group_symbols("P23").hall()) s0 = matrix.col((0, 0, 1)) wavelength = 1.0 dmin = 1.5 indices = full_sphere_indices(unit_cell=uc, resolution_limit=dmin, space_group=sg) ra = rotation_angles(dmin, ub_beg, wavelength, axis) obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range( phi_start_rad=0.0 * pi / 180.0, phi_end_rad=1.0 * pi / 180.0, indices=indices ) r = reeke_model(ub_beg, ub_end, axis, s0, dmin, 1.0) reeke_indices = r.generate_indices() # r.visualize_with_rgl() for oi in obs_indices: assert tuple(map(int, oi)) in reeke_indices # TODO Tests for an oblique cell print "OK"
def test_versus_brute_force(): """Perform a regression test by comparing to indices generated by the brute force method""" # cubic, 50A cell, 1A radiation, 1 deg osciillation, everything ideal a = 50.0 ub_beg = matrix.sqr( (1.0 / a, 0.0, 0.0, 0.0, 1.0 / a, 0.0, 0.0, 0.0, 1.0 / a)) axis = matrix.col((0, 1, 0)) r_osc = matrix.sqr( r3_rotation_axis_and_angle_as_matrix(axis=axis, angle=1.0, deg=True)) ub_end = r_osc * ub_beg uc = unit_cell((a, a, a, 90, 90, 90)) sg = space_group(space_group_symbols("P23").hall()) s0 = matrix.col((0, 0, 1)) wavelength = 1.0 dmin = 1.5 # get the full set of indices indices = full_sphere_indices(unit_cell=uc, resolution_limit=dmin, space_group=sg) # find the observed indices ra = rotation_angles(dmin, ub_beg, wavelength, axis) obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range( phi_start_rad=0.0 * math.pi / 180.0, phi_end_rad=1.0 * math.pi / 180.0, indices=indices, ) # r = reeke_model(ub_beg, ub_end, axis, s0, dmin, 1.0) # reeke_indices = r.generate_indices() # now try the Reeke method to generate indices r = ReekeIndexGenerator(ub_beg, ub_end, sg.type(), axis, s0, dmin, margin=1) reeke_indices = r.to_array() for oi in obs_indices: assert tuple(map(int, oi)) in reeke_indices
def predict(self, hkl): """Solve the prediction formula for the reflecting angle phi""" # calculate conversion matrix to rossmann frame. R_to_rossmann = self.align_reference_frame( self._beam.get_unit_s0(), (0.0, 0.0, 1.0), self._gonio.get_rotation_axis(), (0.0, 1.0, 0.0)) # Create a rotation_angles object for the current geometry ra = rotation_angles(self._dmin, R_to_rossmann * self._crystal.get_U() * self._crystal.get_B(), self._beam.get_wavelength(), R_to_rossmann * matrix.col(self._gonio.get_rotation_axis())) if ra(hkl): return ra.get_intersection_angles() else: return None
def generate_intersection_angles(a_matrix, dmin, wavelength, indices): """From an A matrix following the Mosflm convention and the list of indices, return a list of phi, (h, k, l) where (typically) there will be two records corresponding to each h, k, l.""" from rstbx.diffraction import rotation_angles from scitbx import matrix import math ra = rotation_angles(dmin, a_matrix, wavelength, matrix.col((0, 1, 0))) phi_hkl = [] r2d = 180.0 / math.pi for i in indices: if ra(i): phis = ra.get_intersection_angles() phi_hkl.append((phis[0] * r2d % 360, i)) phi_hkl.append((phis[1] * r2d % 360, i)) return phi_hkl
def generate_intersection_angles(a_matrix, dmin, wavelength, indices): '''From an A matrix following the Mosflm convention and the list of indices, return a list of phi, (h, k, l) where (typically) there will be two records corresponding to each h, k, l.''' from rstbx.diffraction import rotation_angles from scitbx import matrix import math ra = rotation_angles(dmin, a_matrix, wavelength, matrix.col((0, 1, 0))) phi_hkl = [] r2d = 180.0 / math.pi for i in indices: if ra(i): phis = ra.get_intersection_angles() phi_hkl.append((phis[0] * r2d % 360, i)) phi_hkl.append((phis[1] * r2d % 360, i)) return phi_hkl
def find_HKL(cbf_image): # construct and link a cbf_handle to the image itself. cbf_handle = pycbf.cbf_handle_struct() cbf_handle.read_file(cbf_image, pycbf.MSG_DIGEST) # get the beam direction cbf_handle.find_category('axis') cbf_handle.find_column('equipment') cbf_handle.find_row('source') beam_direction = [] for j in range(3): cbf_handle.find_column('vector[%d]' % (j + 1)) beam_direction.append(cbf_handle.get_doublevalue()) B = - matrix.col(beam_direction).normalize() detector = cbf_handle.construct_detector(0) # this returns slow fast slow fast pixels pixels mm mm detector_normal = tuple(detector.get_detector_normal()) distance = detector.get_detector_distance() pixel = (detector.get_inferred_pixel_size(1), detector.get_inferred_pixel_size(2)) gonio = cbf_handle.construct_goniometer() real_axis, real_angle = determine_effective_scan_axis(gonio) axis = tuple(gonio.get_rotation_axis()) angles = tuple(gonio.get_rotation_range()) # this method returns slow then fast dimensions i.e. (y, x) size = tuple(reversed(cbf_handle.get_image_size(0))) wavelength = cbf_handle.get_wavelength() O = matrix.col(detector.get_pixel_coordinates(0, 0)) fast = matrix.col(detector.get_pixel_coordinates(0, 1)) slow = matrix.col(detector.get_pixel_coordinates(1, 0)) X = fast - O Y = slow - O X = X.normalize() Y = Y.normalize() N = X.cross(Y) S0 = (1.0 / wavelength) * B # Need to rotate into Rossmann reference frame for phi calculation, as # that's code from Labelit :o( RB = matrix.col([0, 0, 1]) if B.angle(RB) % math.pi: RtoR = RB.cross(R).axis_and_angle_as_r3_rotation_matrix( RB.angle(R)) elif B.angle(RB): RtoR = matrix.sqr((1, 0, 0, 0, -1, 0, 0, 0, -1)) else: RtoR = matrix.sqr((1, 0, 0, 0, 1, 0, 0, 0, 1)) Raxis = RtoR * axis RUB = RtoR * UB RA = rotation_angles(wavelength, RUB, wavelength, Raxis) assert(RA(hkl)) omegas = [180.0 / math.pi * a for a in RA.get_intersection_angles()] print '%.2f %.2f' % tuple(omegas) for omega in omegas: R = matrix.col(axis).axis_and_angle_as_r3_rotation_matrix( math.pi * omega / 180.0) q = R * UB * hkl p = S0 + q p_ = p * (1.0 / math.sqrt(p.dot())) P = p_ * (O.dot(N) / (p_.dot(N))) R = P - O i = R.dot(X) j = R.dot(Y) k = R.dot(N) print '%d %d %d %.3f %.3f %.3f %.3f %.3f' % \ (hkl[0], hkl[1], hkl[2], i, j, omega, i / pixel[0], j / pixel[1]) # finally, the inverse calculation - given a position on the detector, # and omega setting, give the Miller index of the reflection i = 193 j = 267 w = 42 # RUBI is (R * UB).inverse() RUBI = (matrix.col(axis).axis_and_angle_as_r3_rotation_matrix( math.pi * w / 180.0) * UB).inverse() p = matrix.col(detector.get_pixel_coordinates(j, i)).normalize() q = (1.0 / wavelength) * p - S0 h, k, l = map(nint, (RUBI * q).elems) assert(h == -17) assert(k == -10) assert(l == 9) print h, k, l detector.__swig_destroy__(detector) del(detector) gonio.__swig_destroy__(gonio) del(gonio)
def predict_observations(self): '''Actually perform the prediction calculations.''' d2r = math.pi / 180.0 cfc = coordinate_frame_converter(self._configuration_file) self.img_start, self.osc_start, self.osc_range = parse_xds_xparm_scan_info( self._configuration_file) if self._dmin is None: self._dmin = cfc.derive_detector_highest_resolution() phi_start = ((self._img_range[0] - self.img_start) * self.osc_range + \ self.osc_start) * d2r phi_end = ((self._img_range[1] - self.img_start + 1) * self.osc_range + \ self.osc_start) * d2r self.phi_start_rad = phi_start self.phi_end_rad = phi_end # in principle this should come from the crystal model - should that # crystal model record the cell parameters or derive them from the # axis directions? A = cfc.get_c('real_space_a') B = cfc.get_c('real_space_b') C = cfc.get_c('real_space_c') cell = (A.length(), B.length(), C.length(), B.angle(C, deg = True), C.angle(A, deg = True), A.angle(B, deg = True)) self.uc = unit_cell(cell) # generate all of the possible indices, then pull out those which should # be systematically absent sg = cfc.get('space_group_number') indices = full_sphere_indices( unit_cell = self.uc, resolution_limit = self._dmin, space_group = space_group(space_group_symbols(sg).hall())) # then get the UB matrix according to the Rossmann convention which # is used within the Labelit code. u, b = cfc.get_u_b(convention = cfc.ROSSMANN) axis = cfc.get('rotation_axis', convention = cfc.ROSSMANN) ub = u * b wavelength = cfc.get('wavelength') self.wavelength = wavelength # work out which reflections should be observed (i.e. pass through the # Ewald sphere) ra = rotation_angles(self._dmin, ub, wavelength, axis) obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range( phi_start_rad = phi_start, phi_end_rad = phi_end, indices = indices) # convert all of these to full scattering vectors in a laboratory frame # (for which I will use the CBF coordinate frame) and calculate which # will intersect with the detector u, b = cfc.get_u_b() axis = cfc.get_c('rotation_axis') # must guarantee that sample_to_source vector is normalized so that # s0 has length of 1/wavelength. sample_to_source_vec = cfc.get_c('sample_to_source').normalize() s0 = (- 1.0 / wavelength) * sample_to_source_vec ub = u * b # need some detector properties for this as well... starting to # abstract these to a detector model. df = detector_factory_from_cfc(cfc) d = df.build() # the Use Case assumes the detector consists of a single sensor sensor = d.sensors()[0] self.pixel_size_fast, self.pixel_size_slow = d.px_size_fast(), \ d.px_size_slow() # used for polarization correction self.distance = sensor.distance rp = reflection_prediction(axis, s0, ub, sensor) if self._rocking_curve is not None: assert self._rocking_curve != "none" rp.set_rocking_curve(self._rocking_curve) rp.set_mosaicity(self._mosaicity_deg, degrees = True) return rp.predict(obs_indices, obs_angles)
def regenerate_predictions_brute(xds_integrate_hkl_file, phi_range): from rstbx.cftbx.coordinate_frame_converter import coordinate_frame_converter from rstbx.diffraction import rotation_angles from rstbx.diffraction import full_sphere_indices from cctbx.sgtbx import space_group, space_group_symbols from cctbx.uctbx import unit_cell import math cfc = coordinate_frame_converter(xds_integrate_hkl_file) d2r = math.pi / 180.0 dmin = cfc.derive_detector_highest_resolution() A = cfc.get_c('real_space_a') B = cfc.get_c('real_space_b') C = cfc.get_c('real_space_c') cell = (A.length(), B.length(), C.length(), B.angle(C, deg = True), C.angle(A, deg = True), A.angle(B, deg = True)) uc = unit_cell(cell) sg = cfc.get('space_group_number') indices = full_sphere_indices( unit_cell = uc, resolution_limit = dmin, space_group = space_group(space_group_symbols(sg).hall())) u, b = cfc.get_u_b(convention = cfc.ROSSMANN) axis = cfc.get('rotation_axis', convention = cfc.ROSSMANN) ub = u * b wavelength = cfc.get('wavelength') ra = rotation_angles(dmin, ub, wavelength, axis) obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range( phi_start_rad = phi_range[0] * d2r, phi_end_rad = phi_range[1] * d2r, indices = indices) # in here work in internal (i.e. not Rossmann) coordinate frame u, b = cfc.get_u_b() axis = cfc.get_c('rotation_axis') sample_to_source_vec = cfc.get_c('sample_to_source').normalize() s0 = (- 1.0 / wavelength) * sample_to_source_vec ub = u * b detector_origin = cfc.get_c('detector_origin') detector_fast = cfc.get_c('detector_fast') detector_slow = cfc.get_c('detector_slow') detector_normal = detector_fast.cross(detector_slow) distance = detector_origin.dot(detector_normal.normalize()) nx, ny = cfc.get('detector_size_fast_slow') px, py = cfc.get('detector_pixel_size_fast_slow') limits = [0, nx * px, 0, ny * py] xyz_to_hkl = { } for hkl, angle in zip(obs_indices, obs_angles): s = (ub * hkl).rotate(axis, angle) q = (s + s0).normalize() # check if diffracted ray parallel to detector face q_dot_n = q.dot(detector_normal) if q_dot_n == 0: continue r = (q * distance / q_dot_n) - detector_origin x = r.dot(detector_fast) y = r.dot(detector_slow) if x < limits[0] or y < limits[2]: continue if x > limits[1] or y > limits[3]: continue xyz = (x, y, angle / d2r) xyz_to_hkl[xyz] = map(int, hkl) return xyz_to_hkl
def regenerate_predictions_reeke(xds_integrate_hkl_file, phi_range): from rstbx.cftbx.coordinate_frame_converter import coordinate_frame_converter from rstbx.diffraction import rotation_angles from cctbx.sgtbx import space_group, space_group_symbols from cctbx.uctbx import unit_cell import math from dials.algorithms.refinement.prediction.reeke import reeke_model from cctbx.array_family import flex cfc = coordinate_frame_converter(xds_integrate_hkl_file) d2r = math.pi / 180.0 dmin = cfc.derive_detector_highest_resolution() A = cfc.get_c('real_space_a') B = cfc.get_c('real_space_b') C = cfc.get_c('real_space_c') cell = (A.length(), B.length(), C.length(), B.angle(C, deg = True), C.angle(A, deg = True), A.angle(B, deg = True)) uc = unit_cell(cell) sg = cfc.get('space_group_number') u, b = cfc.get_u_b() axis = cfc.get_c('rotation_axis') sample_to_source_vec = cfc.get_c('sample_to_source').normalize() wavelength = cfc.get('wavelength') s0 = (- 1.0 / wavelength) * sample_to_source_vec ub = u * b rm = reeke_model(ub, axis, s0, dmin, phi_range[0], phi_range[1], 3) reeke_indices = rm.generate_indices() # the following are in Rossmann coordinate frame to fit in with # Labelit code... ur, br = cfc.get_u_b(convention = cfc.ROSSMANN) axisr = cfc.get('rotation_axis', convention = cfc.ROSSMANN) ubr = ur * br ra = rotation_angles(dmin, ubr, wavelength, axisr) obs_indices, obs_angles = ra.observed_indices_and_angles_from_angle_range( phi_start_rad = phi_range[0] * d2r, phi_end_rad = phi_range[1] * d2r, indices = reeke_indices) detector_origin = cfc.get_c('detector_origin') detector_fast = cfc.get_c('detector_fast') detector_slow = cfc.get_c('detector_slow') detector_normal = detector_fast.cross(detector_slow) distance = detector_origin.dot(detector_normal.normalize()) nx, ny = cfc.get('detector_size_fast_slow') px, py = cfc.get('detector_pixel_size_fast_slow') limits = [0, nx * px, 0, ny * py] xyz_to_hkl = { } for hkl, angle in zip(obs_indices, obs_angles): s = (ub * hkl).rotate(axis, angle) q = (s + s0).normalize() # check if diffracted ray parallel to detector face q_dot_n = q.dot(detector_normal) if q_dot_n == 0: continue r = (q * distance / q_dot_n) - detector_origin x = r.dot(detector_fast) y = r.dot(detector_slow) if x < limits[0] or y < limits[2]: continue if x > limits[1] or y > limits[3]: continue xyz = (x, y, angle / d2r) xyz_to_hkl[xyz] = map(int, hkl) return xyz_to_hkl
mygonio = goniometer_factory.known_axis((1, 0, 0)) # generate some indices resolution = 2.0 indices = full_sphere_indices( unit_cell = mycrystal.get_unit_cell(), resolution_limit = resolution, space_group = space_group(space_group_symbols(1).hall())) # generate list of phi values R_to_rossmann = align_reference_frame( mybeam.get_unit_s0(), (0.0, 0.0, 1.0), mygonio.get_rotation_axis(), (0.0, 1.0, 0.0)) ra = rotation_angles(resolution, R_to_rossmann * mycrystal.get_U() * mycrystal.get_B(), mybeam.get_wavelength(), R_to_rossmann * matrix.col(mygonio.get_rotation_axis())) obs_indices_rstbx, obs_angles_rstbx = \ ra.observed_indices_and_angles_from_angle_range( phi_start_rad = 0.0, phi_end_rad = math.pi, indices = indices) # test my rotation_angles wrapper, AnglePredictor_rstbx ap = AnglePredictor_rstbx(mycrystal, mybeam, mygonio, resolution) obs_indices_wrap, obs_angles_wrap = ap.observed_indices_and_angles_from_angle_range( phi_start_rad = 0.0, phi_end_rad = math.pi, indices = indices) # NB # * obs_indices is a scitbx_array_family_flex_ext.vec3_double and contains # floating point indices. # * obs_indices2 is a cctbx_array_family_flex_ext.miller_index containing
# generate some indices resolution = 2.0 indices = full_sphere_indices( unit_cell=mycrystal.get_unit_cell(), resolution_limit=resolution, space_group=space_group(space_group_symbols(1).hall()), ) # generate list of phi values R_to_rossmann = align_reference_frame( mybeam.get_unit_s0(), (0.0, 0.0, 1.0), mygonio.get_rotation_axis(), (0.0, 1.0, 0.0) ) ra = rotation_angles( resolution, R_to_rossmann * mycrystal.get_U() * mycrystal.get_B(), mybeam.get_wavelength(), R_to_rossmann * matrix.col(mygonio.get_rotation_axis()), ) obs_indices_rstbx, obs_angles_rstbx = ra.observed_indices_and_angles_from_angle_range( phi_start_rad=0.0, phi_end_rad=math.pi, indices=indices ) # test my rotation_angles wrapper, AnglePredictor_rstbx ap = AnglePredictor_rstbx(mycrystal, mybeam, mygonio, resolution) obs_indices_wrap, obs_angles_wrap = ap.observed_indices_and_angles_from_angle_range( phi_start_rad=0.0, phi_end_rad=math.pi, indices=indices ) # NB # * obs_indices is a scitbx_array_family_flex_ext.vec3_double and contains
wavelength = results['wavelength'] start = results['starting_frame'] - 1 phi_start = results['phi_start'] phi_width = results['phi_width'] # FIXME really need to rotate the reference frame to put the # direct beam vector along (0,0,1) resolution = 1.8 orientation = A + B + C co = crystal_orientation(orientation, basis_type.direct) mm = co.unit_cell().max_miller_indices(resolution) ra = rotation_angles(resolution, co.reciprocal_matrix(), wavelength, axis) for record in open('SPOT.XDS', 'r').readlines(): lst = record.split() hkl = tuple(map(int, lst[-3:])) if hkl == (0, 0, 0): continue image = nint(float(lst[2])) if ra(hkl): phi1, phi2 = ra.get_intersection_angles() i = nint(start + (rtod * phi1 - phi_start) / phi_width) j = nint(start + (rtod * phi2 - phi_start) / phi_width) if abs(i - image) <= abs(j - image): print '%4d %4d' % (image, i) else: