def tst_with_old_index_generator(self): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.array_family import flex predict = ScanStaticReflectionPredictor(self.experiments[0]) r_old = predict.for_ub_old_index_generator( self.experiments[0].crystal.get_A()) r_new = predict.for_ub(self.experiments[0].crystal.get_A()) index1 = flex.size_t( sorted(range(len(r_old)), key=lambda x: r_old['miller_index'][x])) index2 = flex.size_t( sorted(range(len(r_new)), key=lambda x: r_new['miller_index'][x])) r_old = r_old.select(index1) r_new = r_new.select(index2) assert (len(r_old) == len(r_new)) eps = 1e-7 for r1, r2 in zip(r_old.rows(), r_new.rows()): assert (r1['miller_index'] == r2['miller_index']) assert (r1['panel'] == r2['panel']) assert (r1['entering'] == r2['entering']) assert (all(abs(a - b) < eps for a, b in zip(r1['s1'], r2['s1']))) assert (all( abs(a - b) < eps for a, b in zip(r1['xyzcal.px'], r2['xyzcal.px']))) assert (all( abs(a - b) < eps for a, b in zip(r1['xyzcal.mm'], r2['xyzcal.mm']))) print 'OK'
def test_with_old_index_generator(data): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.array_family import flex predict = ScanStaticReflectionPredictor(data.experiments[0]) r_old = predict.for_ub_old_index_generator( data.experiments[0].crystal.get_A()) r_new = predict.for_ub(data.experiments[0].crystal.get_A()) index1 = flex.size_t( sorted(range(len(r_old)), key=lambda x: r_old["miller_index"][x])) index2 = flex.size_t( sorted(range(len(r_new)), key=lambda x: r_new["miller_index"][x])) r_old = r_old.select(index1) r_new = r_new.select(index2) assert len(r_old) == len(r_new) for r1, r2 in zip(r_old.rows(), r_new.rows()): assert r1["miller_index"] == r2["miller_index"] assert r1["panel"] == r2["panel"] assert r1["entering"] == r2["entering"] assert all(a == pytest.approx(b, abs=1e-7) for a, b in zip(r1["s1"], r2["s1"])) assert all(a == pytest.approx(b, abs=1e-7) for a, b in zip(r1["xyzcal.px"], r2["xyzcal.px"])) assert all(a == pytest.approx(b, abs=1e-7) for a, b in zip(r1["xyzcal.mm"], r2["xyzcal.mm"]))
def predict_new(self, experiment=None, hkl=None, panel=None): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor if experiment is None: experiment=self.experiments[0] predict = ScanStaticReflectionPredictor(experiment) if hkl is None: return predict.for_ub(experiment.crystal.get_A()) else: if panel is None: return predict(hkl) else: return predict(hkl, panel)
def predict_new(self, experiment=None, hkl=None, panel=None): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor if experiment is None: experiment = self.experiments[0] predict = ScanStaticReflectionPredictor(experiment) if hkl is None: return predict.for_ub(experiment.crystal.get_A()) else: if panel is None: return predict(hkl) else: return predict(hkl, panel)
def test_with_reflection_table(data): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.array_family import flex r_old = data.reflections r_new = flex.reflection_table() r_new['miller_index'] = r_old['miller_index'] r_new['panel'] = r_old['panel'] r_new['entering'] = r_old['entering'] predict = ScanStaticReflectionPredictor(data.experiments[0]) predict.for_reflection_table(r_new, data.experiments[0].crystal.get_A()) for r1, r2 in zip(r_old.rows(), r_new.rows()): assert r1['miller_index'] == r2['miller_index'] assert r1['panel'] == r2['panel'] assert r1['entering'] == r2['entering'] assert all(a == pytest.approx(b, abs=1e-7) for a, b in zip(r1['s1'], r2['s1'])) assert all(a == pytest.approx(b, abs=1e-7) for a, b in zip(r1['xyzcal.px'], r2['xyzcal.px'])) assert all(a == pytest.approx(b, abs=1e-7) for a, b in zip(r1['xyzcal.mm'], r2['xyzcal.mm']))
def tst_with_reflection_table(self): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.array_family import flex r_old = self.reflections r_new = flex.reflection_table() r_new['miller_index'] = r_old['miller_index'] r_new['panel'] = r_old['panel'] r_new['entering'] = r_old['entering'] predict = ScanStaticReflectionPredictor(self.experiments[0]) predict.for_reflection_table(r_new, self.experiments[0].crystal.get_A()) eps = 1e-7 for r1, r2 in zip(r_old.rows(), r_new.rows()): assert(r1['miller_index'] == r2['miller_index']) assert(r1['panel'] == r2['panel']) assert(r1['entering'] == r2['entering']) assert(all(abs(a-b) < eps for a, b in zip(r1['s1'], r2['s1']))) assert(all(abs(a-b) < eps for a, b in zip(r1['xyzcal.px'], r2['xyzcal.px']))) assert(all(abs(a-b) < eps for a, b in zip(r1['xyzcal.mm'], r2['xyzcal.mm']))) print 'OK'
def test_connected_components_centred_cell(dials_data): experiment = ExperimentList.from_file( dials_data("insulin_processed").join("scaled.expt").strpath, check_format=False )[0] experiment.scan.set_image_range((1, 10)) predict = ScanStaticReflectionPredictor(experiment, dmin=3, margin=1) refl = predict.for_ub(experiment.crystal.get_A()) miller_set = miller.set( experiment.crystal.get_crystal_symmetry(), refl["miller_index"], anomalous_flag=False, ) miller_array = miller_set.d_spacings().resolution_filter(d_min=3) complete_set, unique_ms = missing_reflections.connected_components(miller_array) assert [ms.size() for ms in unique_ms] == [581, 32, 29, 6, 3, 3, 3, 2] # Verify that all the indices reported missing are actually missing from the input for ms in unique_ms: assert ms.common_set(miller_array.map_to_asu()).size() == 0 assert complete_set.completeness() == 1
def test_for_reflection_table(data): from dials.algorithms.spot_prediction import ( ScanStaticReflectionPredictor, ScanVaryingReflectionPredictor, ) from dials.array_family import flex predict = ScanStaticReflectionPredictor(data.experiments[0]) preds = predict.for_ub(data.experiments[0].crystal.get_A()) preds["ub_matrix"] = flex.mat3_double(len(preds), data.experiments[0].crystal.get_A()) preds["s0"] = flex.vec3_double(len(preds), data.experiments[0].beam.get_s0()) preds["d_matrix"] = flex.mat3_double(len(preds)) preds["S_matrix"] = flex.mat3_double( len(preds), data.experiments[0].goniometer.get_setting_rotation()) for ipanel, panel in enumerate(data.experiments[0].detector): sel = preds["panel"] == ipanel D = panel.get_d_matrix() preds["d_matrix"].set_selected(sel, D) predict = ScanVaryingReflectionPredictor(data.experiments[0]) old_preds = copy.deepcopy(preds) predict.for_reflection_table(preds, preds["ub_matrix"], preds["s0"], preds["d_matrix"], preds["S_matrix"]) # Because UB, s0, d and S values are the same for all reflections, the new # reflections should be approx equal to those produced by the scan static # predictor old_x, old_y, old_z = old_preds["xyzcal.px"].parts() new_x, new_y, new_z = preds["xyzcal.px"].parts() assert old_x.all_approx_equal(new_x) assert old_y.all_approx_equal(new_y) assert old_z.all_approx_equal(new_z)
def tst_for_reflection_table(self): from libtbx.test_utils import approx_equal from dials.algorithms.spot_prediction import \ ScanVaryingReflectionPredictor, ScanStaticReflectionPredictor from dials.array_family import flex predict = ScanStaticReflectionPredictor(self.experiments[0]) preds = predict.for_ub(self.experiments[0].crystal.get_A()) preds['ub_matrix'] = flex.mat3_double(len(preds), self.experiments[0].crystal.get_A()) preds['s0'] = flex.vec3_double(len(preds), self.experiments[0].beam.get_s0()) preds['d_matrix'] = flex.mat3_double(len(preds)) for ipanel, panel in enumerate(self.experiments[0].detector): sel = preds['panel'] == ipanel D = panel.get_d_matrix() preds['d_matrix'].set_selected(sel, D) predict = ScanVaryingReflectionPredictor(self.experiments[0]) from copy import deepcopy old_preds = deepcopy(preds) predict.for_reflection_table(preds, preds['ub_matrix'], preds['s0'], preds['d_matrix']) # Because UB, s0 and d values are the same for all reflections, the new # reflections should be approx equal to those produced by the scan static # predictor old_x, old_y, old_z = old_preds['xyzcal.px'].parts() new_x, new_y, new_z = preds['xyzcal.px'].parts() assert old_x.all_approx_equal(new_x) assert old_y.all_approx_equal(new_y) assert old_z.all_approx_equal(new_z) print "OK" return
def tst_with_reflection_table(self): from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.array_family import flex r_old = self.reflections r_new = flex.reflection_table() r_new['miller_index'] = r_old['miller_index'] r_new['panel'] = r_old['panel'] r_new['entering'] = r_old['entering'] predict = ScanStaticReflectionPredictor(self.experiments[0]) predict.for_reflection_table(r_new, self.experiments[0].crystal.get_A()) eps = 1e-7 for r1, r2 in zip(r_old.rows(), r_new.rows()): assert (r1['miller_index'] == r2['miller_index']) assert (r1['panel'] == r2['panel']) assert (r1['entering'] == r2['entering']) assert (all(abs(a - b) < eps for a, b in zip(r1['s1'], r2['s1']))) assert (all( abs(a - b) < eps for a, b in zip(r1['xyzcal.px'], r2['xyzcal.px']))) assert (all( abs(a - b) < eps for a, b in zip(r1['xyzcal.mm'], r2['xyzcal.mm']))) print 'OK'
def test_connected_components(dials_data): experiment = ExperimentList.from_file( dials_data("centroid_test_data").join("experiments.json").strpath )[0] image_ranges = [(1, 9), (1, 100), (1, 1000)] expected_ms_sizes = [[755], [242, 14, 10, 5, 2, 2, 2], []] for image_range, expected_sizes in zip(image_ranges, expected_ms_sizes): experiment.scan.set_image_range(image_range) predict = ScanStaticReflectionPredictor(experiment, dmin=3, margin=1) refl = predict.for_ub(experiment.crystal.get_A()) miller_set = miller.set( experiment.crystal.get_crystal_symmetry(), refl["miller_index"], anomalous_flag=False, ) miller_array = miller_set.d_spacings().resolution_filter(d_min=3) complete_set, unique_ms = missing_reflections.connected_components(miller_array) assert len(unique_ms) == len(expected_sizes) assert [ms.size() for ms in unique_ms] == expected_sizes # Verify that all the indices reported missing are actually missing from the input for ms in unique_ms: assert ms.common_set(miller_array.map_to_asu()).size() == 0 assert complete_set.completeness() == 1
def tst_for_reflection_table(self): from libtbx.test_utils import approx_equal from dials.algorithms.spot_prediction import \ ScanVaryingReflectionPredictor, ScanStaticReflectionPredictor from dials.array_family import flex predict = ScanStaticReflectionPredictor(self.experiments[0]) preds = predict.for_ub(self.experiments[0].crystal.get_A()) preds['ub_matrix'] = flex.mat3_double(len(preds), self.experiments[0].crystal.get_A()) preds['s0'] = flex.vec3_double(len(preds), self.experiments[0].beam.get_s0()) preds['d_matrix'] = flex.mat3_double(len(preds)) preds['S_matrix'] = flex.mat3_double(len(preds), self.experiments[0].goniometer.get_setting_rotation()) for ipanel, panel in enumerate(self.experiments[0].detector): sel = preds['panel'] == ipanel D = panel.get_d_matrix() preds['d_matrix'].set_selected(sel, D) predict = ScanVaryingReflectionPredictor(self.experiments[0]) from copy import deepcopy old_preds = deepcopy(preds) predict.for_reflection_table(preds, preds['ub_matrix'], preds['s0'], preds['d_matrix'], preds['S_matrix']) # Because UB, s0, d and S values are the same for all reflections, the new # reflections should be approx equal to those produced by the scan static # predictor old_x, old_y, old_z = old_preds['xyzcal.px'].parts() new_x, new_y, new_z = preds['xyzcal.px'].parts() assert old_x.all_approx_equal(new_x) assert old_y.all_approx_equal(new_y) assert old_z.all_approx_equal(new_z) print "OK" return
def __init__(self, experiment, dmin=None, dmax=None, margin=1, force_static=False, padding=0): ''' Initialise a predictor for each experiment. :param experiment: The experiment to predict for :param dmin: The maximum resolution :param dmax: The minimum resolution :param margin: The margin of hkl to predict :param force_static: force scan varying prediction to be static ''' from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.algorithms.spot_prediction import ScanVaryingReflectionPredictor from dials.algorithms.spot_prediction import StillsReflectionPredictor from dxtbx.imageset import ImageSweep from dials.array_family import flex class Predictor(object): def __init__(self, name, func): self.name = name self.func = func def __call__(self): result = self.func() if dmax is not None: assert (dmax > 0) result.compute_d_single(experiment) mask = result['d'] > dmax result.del_selected(mask) return result # Check prediction to maximum resolution is possible wl = experiment.beam.get_wavelength() if dmin is not None and dmin < 0.5 * wl: raise Sorry("Prediction at d_min of {0} is not possible " "with wavelength {1}".format(dmin, wl)) # Select the predictor class if isinstance(experiment.imageset, ImageSweep): nsp = experiment.crystal.num_scan_points nim = experiment.scan.get_num_images() if not force_static and nsp == nim + 1: predictor = ScanVaryingReflectionPredictor(experiment, dmin=dmin, margin=margin, padding=padding) A = [ experiment.crystal.get_A_at_scan_point(i) for i in range(experiment.crystal.num_scan_points) ] predict = Predictor( "scan varying prediction", lambda: predictor.for_ub(flex.mat3_double(A))) else: predictor = ScanStaticReflectionPredictor(experiment, dmin=dmin, padding=padding) predict = Predictor( "scan static prediction", lambda: predictor.for_ub(experiment.crystal.get_A())) else: predictor = StillsReflectionPredictor(experiment, dmin=dmin) predict = Predictor( "stills prediction", lambda: predictor.for_ub(experiment.crystal.get_A())) # Create and add the predictor class self._predict = predict
def export_sadabs(integrated_data, experiment_list, params): """Export data from integrated_data corresponding to experiment_list to a file for input to SADABS. FIXME probably need to make a .p4p file as well...""" from dials.array_family import flex # for the moment assume (and assert) that we will convert data from exactly # one lattice... assert len(experiment_list) == 1 # select reflections that are assigned to an experiment (i.e. non-negative id) integrated_data = integrated_data.select(integrated_data["id"] >= 0) assert max(integrated_data["id"]) == 0 # export for sadabs should only be for non-scaled reflections assert any(i in integrated_data for i in ["intensity.sum.value", "intensity.prf.value"]) integrated_data = filter_reflection_table( integrated_data, intensity_choice=params.intensity, partiality_threshold=params.mtz.partiality_threshold, combine_partials=params.mtz.combine_partials, min_isigi=params.mtz.min_isigi, filter_ice_rings=params.mtz.filter_ice_rings, d_min=params.mtz.d_min, ) experiment = experiment_list[0] assert experiment.scan is not None # sort data before output nref = len(integrated_data["miller_index"]) indices = flex.size_t_range(nref) perm = sorted(indices, key=lambda k: integrated_data["miller_index"][k]) integrated_data = integrated_data.select(flex.size_t(perm)) assert experiment.goniometer is not None # Warn of unhelpful SADABS behaviour for certain multi-sequence data sets hkl_file_root, _ = os.path.splitext(params.sadabs.hklout) if not params.sadabs.run or re.search("_0+$", hkl_file_root): logger.warning( "It seems SADABS rejects multi-sequence data when the first " "filename ends " "'_0', '_00', etc., with a cryptic error message:\n" "\t'Inconsistent 2theta values in same scan'.\n" "You may need to begin the numbering of your SADABS HKL files from 1, " "rather than 0, and ensure the SADABS run/batch number is greater than 0." ) axis = matrix.col(experiment.goniometer.get_rotation_axis_datum()) beam = matrix.col(experiment.beam.get_sample_to_source_direction()) s0 = matrix.col(experiment.beam.get_s0()) F = matrix.sqr(experiment.goniometer.get_fixed_rotation()) S = matrix.sqr(experiment.goniometer.get_setting_rotation()) unit_cell = experiment.crystal.get_unit_cell() if params.debug: m_format = "%6.3f%6.3f%6.3f\n%6.3f%6.3f%6.3f\n%6.3f%6.3f%6.3f" c_format = "%.2f %.2f %.2f %.2f %.2f %.2f" logger.info( "Unit cell parameters from experiment: %s", c_format % unit_cell.parameters(), ) logger.info( "Symmetry: %s", experiment.crystal.get_space_group().type().lookup_symbol()) logger.info("Goniometer fixed matrix:\n%s", m_format % F.elems) logger.info("Goniometer setting matrix:\n%s", m_format % S.elems) logger.info("Goniometer scan axis:\n%6.3f%6.3f%6.3f", axis.elems) # detector scaling info assert len(experiment.detector) == 1 panel = experiment.detector[0] dims = panel.get_image_size() pixel = panel.get_pixel_size() fast_axis = matrix.col(panel.get_fast_axis()) slow_axis = matrix.col(panel.get_slow_axis()) normal = fast_axis.cross(slow_axis) detector2t = s0.angle(normal, deg=True) if params.debug: logger.info("Detector fast, slow axes:") logger.info("%6.3f%6.3f%6.3f", fast_axis.elems) logger.info("%6.3f%6.3f%6.3f", slow_axis.elems) logger.info("Detector two theta (degrees): %.2f", detector2t) scl_x = 512.0 / (dims[0] * pixel[0]) scl_y = 512.0 / (dims[1] * pixel[1]) image_range = experiment.scan.get_image_range() from cctbx.array_family import flex as cflex # implicit import # noqa: F401 from cctbx.miller import map_to_asu_isym # implicit import # noqa: F401 # gather the required information for the reflection file nref = len(integrated_data["miller_index"]) miller_index = integrated_data["miller_index"] if "intensity.sum.value" in integrated_data: I = integrated_data["intensity.sum.value"] V = integrated_data["intensity.sum.variance"] assert V.all_gt(0) sigI = flex.sqrt(V) else: I = integrated_data["intensity.prf.value"] V = integrated_data["intensity.prf.variance"] assert V.all_gt(0) sigI = flex.sqrt(V) # figure out scaling to make sure data fit into format 2F8.2 i.e. Imax < 1e5 Imax = flex.max(I) if params.debug: logger.info("Maximum intensity in file: %8.2f", Imax) if Imax > 99999.0: scale = 99999.0 / Imax I = I * scale sigI = sigI * scale phi_start, phi_range = experiment.scan.get_image_oscillation( image_range[0]) if params.sadabs.predict: logger.info("Using scan static predicted spot locations") from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor predictor = ScanStaticReflectionPredictor(experiment) UB = experiment.crystal.get_A() predictor.for_reflection_table(integrated_data, UB) if not experiment.crystal.num_scan_points: logger.info("No scan varying model: use static") static = True else: static = False with open(params.sadabs.hklout, "w") as fout: for j in range(nref): h, k, l = miller_index[j] if params.sadabs.predict: x_mm, y_mm, z_rad = integrated_data["xyzcal.mm"][j] else: x_mm, y_mm, z_rad = integrated_data["xyzobs.mm.value"][j] z0 = integrated_data["xyzcal.px"][j][2] istol = int(round(10000 * unit_cell.stol((h, k, l)))) if params.sadabs.predict or static: # work from a scan static model & assume perfect goniometer # FIXME maybe should work back in the option to predict spot positions UB = matrix.sqr(experiment.crystal.get_A()) phi = phi_start + z0 * phi_range R = axis.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) RUB = S * R * F * UB else: # properly compute RUB for every reflection UB = matrix.sqr( experiment.crystal.get_A_at_scan_point(int(round(z0)))) phi = phi_start + z0 * phi_range R = axis.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) RUB = S * R * F * UB x = RUB * (h, k, l) s = (s0 + x).normalize() # can also compute s based on centre of mass of spot # s = (origin + x_mm * fast_axis + y_mm * slow_axis).normalize() astar = (RUB * (1, 0, 0)).normalize() bstar = (RUB * (0, 1, 0)).normalize() cstar = (RUB * (0, 0, 1)).normalize() ix = beam.dot(astar) iy = beam.dot(bstar) iz = beam.dot(cstar) dx = s.dot(astar) dy = s.dot(bstar) dz = s.dot(cstar) x = x_mm * scl_x y = y_mm * scl_y z = (z_rad * 180 / math.pi - phi_start) / phi_range fout.write("%4d%4d%4d%8.2f%8.2f%4d%8.5f%8.5f%8.5f%8.5f%8.5f%8.5f" % (h, k, l, I[j], sigI[j], params.sadabs.run, ix, dx, iy, dy, iz, dz)) fout.write("%7.2f%7.2f%8.2f%7.2f%5d\n" % (x, y, z, detector2t, istol)) fout.close() logger.info("Output %d reflections to %s", nref, params.sadabs.hklout)
def export_sadabs(integrated_data, experiment_list, hklout, run=0, summation=False, include_partials=False, keep_partials=False, debug=False, predict=True): '''Export data from integrated_data corresponding to experiment_list to a file for input to SADABS. FIXME probably need to make a .p4p file as well...''' from dials.array_family import flex from scitbx import matrix import math # for the moment assume (and assert) that we will convert data from exactly # one lattice... assert(len(experiment_list) == 1) # select reflections that are assigned to an experiment (i.e. non-negative id) integrated_data = integrated_data.select(integrated_data['id'] >= 0) assert max(integrated_data['id']) == 0 if not summation: assert('intensity.prf.value' in integrated_data) # strip out negative variance reflections: these should not really be there # FIXME Doing select on summation results. Should do on profile result if # present? Yes if 'intensity.prf.variance' in integrated_data: selection = integrated_data.get_flags( integrated_data.flags.integrated, all=True) else: selection = integrated_data.get_flags( integrated_data.flags.integrated_sum) integrated_data = integrated_data.select(selection) selection = integrated_data['intensity.sum.variance'] <= 0 if selection.count(True) > 0: integrated_data.del_selected(selection) logger.info('Removing %d reflections with negative variance' % \ selection.count(True)) if 'intensity.prf.variance' in integrated_data: selection = integrated_data['intensity.prf.variance'] <= 0 if selection.count(True) > 0: integrated_data.del_selected(selection) logger.info('Removing %d profile reflections with negative variance' % \ selection.count(True)) if include_partials: integrated_data = sum_partial_reflections(integrated_data) integrated_data = scale_partial_reflections(integrated_data) if 'partiality' in integrated_data: selection = integrated_data['partiality'] < 0.99 if selection.count(True) > 0 and not keep_partials: integrated_data.del_selected(selection) logger.info('Removing %d incomplete reflections' % \ selection.count(True)) experiment = experiment_list[0] assert(not experiment.scan is None) # sort data before output nref = len(integrated_data['miller_index']) indices = flex.size_t_range(nref) perm = sorted(indices, key=lambda k: integrated_data['miller_index'][k]) integrated_data = integrated_data.select(flex.size_t(perm)) assert (not experiment.goniometer is None) axis = matrix.col(experiment.goniometer.get_rotation_axis_datum()) beam = matrix.col(experiment.beam.get_direction()) s0 = matrix.col(experiment.beam.get_s0()) F = matrix.sqr(experiment.goniometer.get_fixed_rotation()) S = matrix.sqr(experiment.goniometer.get_setting_rotation()) unit_cell = experiment.crystal.get_unit_cell() if debug: m_format = '%6.3f%6.3f%6.3f\n%6.3f%6.3f%6.3f\n%6.3f%6.3f%6.3f' c_format = '%.2f %.2f %.2f %.2f %.2f %.2f' logger.info('Unit cell parameters from experiment: %s' % (c_format % unit_cell.parameters())) logger.info('Symmetry: %s' % experiment.crystal.get_space_group().type( ).lookup_symbol()) logger.info('Goniometer fixed matrix:\n%s' % (m_format % F.elems)) logger.info('Goniometer setting matrix:\n%s' % (m_format % S.elems)) logger.info('Goniometer scan axis:\n%6.3f%6.3f%6.3f' % (axis.elems)) # detector scaling info assert(len(experiment.detector) == 1) panel = experiment.detector[0] dims = panel.get_image_size() pixel = panel.get_pixel_size() fast_axis = matrix.col(panel.get_fast_axis()) slow_axis = matrix.col(panel.get_slow_axis()) normal = fast_axis.cross(slow_axis) detector2t = s0.angle(normal, deg=True) origin = matrix.col(panel.get_origin()) if debug: logger.info('Detector fast, slow axes:') logger.info('%6.3f%6.3f%6.3f' % (fast_axis.elems)) logger.info('%6.3f%6.3f%6.3f' % (slow_axis.elems)) logger.info('Detector two theta (degrees): %.2f' % detector2t) scl_x = 512.0 / (dims[0] * pixel[0]) scl_y = 512.0 / (dims[1] * pixel[1]) image_range = experiment.scan.get_image_range() from cctbx.array_family import flex as cflex # implicit import from cctbx.miller import map_to_asu_isym # implicit import # gather the required information for the reflection file nref = len(integrated_data['miller_index']) zdet = flex.double(integrated_data['xyzcal.px'].parts()[2]) miller_index = integrated_data['miller_index'] I = None sigI = None # export including scale factors if 'lp' in integrated_data: lp = integrated_data['lp'] else: lp = flex.double(nref, 1.0) if 'dqe' in integrated_data: dqe = integrated_data['dqe'] else: dqe = flex.double(nref, 1.0) scl = lp / dqe if summation: I = integrated_data['intensity.sum.value'] * scl V = integrated_data['intensity.sum.variance'] * scl * scl assert V.all_gt(0) sigI = flex.sqrt(V) else: I = integrated_data['intensity.prf.value'] * scl V = integrated_data['intensity.prf.variance'] * scl * scl assert V.all_gt(0) sigI = flex.sqrt(V) # figure out scaling to make sure data fit into format 2F8.2 i.e. Imax < 1e5 Imax = flex.max(I) if debug: logger.info('Maximum intensity in file: %8.2f' % Imax) if Imax > 99999.0: scale = 99999.0 / Imax I = I * scale sigI = sigI * scale phi_start, phi_range = experiment.scan.get_image_oscillation(image_range[0]) if predict: logger.info('Using scan static predicted spot locations') from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor predictor = ScanStaticReflectionPredictor(experiment) UB = experiment.crystal.get_A() predictor.for_reflection_table(integrated_data, UB) if not experiment.crystal.num_scan_points: logger.info('No scan varying model: use static') static = True else: static = False fout = open(hklout, 'w') for j in range(nref): h, k, l = miller_index[j] if predict: x_mm, y_mm, z_rad = integrated_data['xyzcal.mm'][j] else: x_mm, y_mm, z_rad = integrated_data['xyzobs.mm.value'][j] z0 = integrated_data['xyzcal.px'][j][2] istol = int(round(10000 * unit_cell.stol((h, k, l)))) if predict or static: # work from a scan static model & assume perfect goniometer # FIXME maybe should work back in the option to predict spot positions UB = experiment.crystal.get_A() phi = phi_start + z0 * phi_range R = axis.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) RUB = S * R * F * UB else: # properly compute RUB for every reflection UB = experiment.crystal.get_A_at_scan_point(int(round(z0))) phi = phi_start + z0 * phi_range R = axis.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) RUB = S * R * F * UB x = RUB * (h, k, l) s = (s0 + x).normalize() # can also compute s based on centre of mass of spot # s = (origin + x_mm * fast_axis + y_mm * slow_axis).normalize() astar = (RUB * (1, 0, 0)).normalize() bstar = (RUB * (0, 1, 0)).normalize() cstar = (RUB * (0, 0, 1)).normalize() ix = beam.dot(astar) iy = beam.dot(bstar) iz = beam.dot(cstar) dx = s.dot(astar) dy = s.dot(bstar) dz = s.dot(cstar) x = x_mm * scl_x y = y_mm * scl_y z = (z_rad * 180 / math.pi - phi_start) / phi_range fout.write('%4d%4d%4d%8.2f%8.2f%4d%8.5f%8.5f%8.5f%8.5f%8.5f%8.5f' % \ (h, k, l, I[j], sigI[j], run, ix, dx, iy, dy, iz, dz)) fout.write('%7.2f%7.2f%8.2f%7.2f%5d\n' % (x, y, z, detector2t, istol)) fout.close() logger.info('Output %d reflections to %s' % (nref, hklout)) return
def __init__( self, experiment, dmin=None, dmax=None, margin=1, force_static=False, padding=0 ): """ Initialise a predictor for each experiment. :param experiment: The experiment to predict for :param dmin: The maximum resolution :param dmax: The minimum resolution :param margin: The margin of hkl to predict :param force_static: force scan varying prediction to be static """ from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor from dials.algorithms.spot_prediction import ScanVaryingReflectionPredictor from dials.algorithms.spot_prediction import StillsReflectionPredictor from dxtbx.imageset import ImageSweep from dials.array_family import flex class Predictor(object): def __init__(self, name, func): self.name = name self.func = func def __call__(self): result = self.func() if dmax is not None: assert dmax > 0 result.compute_d_single(experiment) mask = result["d"] > dmax result.del_selected(mask) return result # Check prediction to maximum resolution is possible wl = experiment.beam.get_wavelength() if dmin is not None and dmin < 0.5 * wl: raise Sorry( "Prediction at d_min of {0} is not possible " "with wavelength {1}".format(dmin, wl) ) # Select the predictor class if isinstance(experiment.imageset, ImageSweep): xl_nsp = experiment.crystal.num_scan_points bm_nsp = experiment.beam.num_scan_points gn_nsp = experiment.goniometer.num_scan_points nim = experiment.scan.get_num_images() sv_compatible = (xl_nsp == nim + 1) or (bm_nsp == nim + 1) if not force_static and sv_compatible: predictor = ScanVaryingReflectionPredictor( experiment, dmin=dmin, margin=margin, padding=padding ) if bm_nsp == 0 and gn_nsp == 0: # Only varying crystal A = [ experiment.crystal.get_A_at_scan_point(i) for i in range(experiment.crystal.num_scan_points) ] predict = Predictor( "scan varying crystal prediction", lambda: predictor.for_ub(flex.mat3_double(A)), ) else: # Any allowed model may vary if xl_nsp == nim + 1: A = [ experiment.crystal.get_A_at_scan_point(i) for i in range(experiment.crystal.num_scan_points) ] else: A = [experiment.crystal.get_A() for i in range(nim + 1)] if bm_nsp == nim + 1: s0 = [ experiment.beam.get_s0_at_scan_point(i) for i in range(experiment.beam.num_scan_points) ] else: s0 = [experiment.beam.get_s0() for i in range(nim + 1)] if gn_nsp == nim + 1: S = [ experiment.goniometer.get_setting_rotation_at_scan_point(i) for i in range(experiment.goniometer.num_scan_points) ] else: S = [ experiment.goniometer.get_setting_rotation() for i in range(nim + 1) ] predict = Predictor( "scan varying model prediction", lambda: predictor.for_varying_models( flex.mat3_double(A), flex.vec3_double(s0), flex.mat3_double(S), ), ) else: predictor = ScanStaticReflectionPredictor( experiment, dmin=dmin, padding=padding ) # Choose index generation method based on number of images # https://github.com/dials/dials/issues/585 if experiment.scan.get_num_images() > 50: predict_method = predictor.for_ub_old_index_generator else: predict_method = predictor.for_ub predict = Predictor( "scan static prediction", lambda: predict_method(experiment.crystal.get_A()), ) else: predictor = StillsReflectionPredictor(experiment, dmin=dmin) predict = Predictor( "stills prediction", lambda: predictor.for_ub(experiment.crystal.get_A()), ) # Create and add the predictor class self._predict = predict
def export_sadabs(integrated_data, experiment_list, hklout, run=0, summation=False, include_partials=False, keep_partials=False, debug=False, predict=True): '''Export data from integrated_data corresponding to experiment_list to a file for input to SADABS. FIXME probably need to make a .p4p file as well...''' from dials.array_family import flex from scitbx import matrix import math # for the moment assume (and assert) that we will convert data from exactly # one lattice... assert (len(experiment_list) == 1) # select reflections that are assigned to an experiment (i.e. non-negative id) integrated_data = integrated_data.select(integrated_data['id'] >= 0) assert max(integrated_data['id']) == 0 if not summation: assert ('intensity.prf.value' in integrated_data) # strip out negative variance reflections: these should not really be there # FIXME Doing select on summation results. Should do on profile result if # present? Yes if 'intensity.prf.variance' in integrated_data: selection = integrated_data.get_flags(integrated_data.flags.integrated, all=True) else: selection = integrated_data.get_flags( integrated_data.flags.integrated_sum) integrated_data = integrated_data.select(selection) selection = integrated_data['intensity.sum.variance'] <= 0 if selection.count(True) > 0: integrated_data.del_selected(selection) logger.info('Removing %d reflections with negative variance' % \ selection.count(True)) if 'intensity.prf.variance' in integrated_data: selection = integrated_data['intensity.prf.variance'] <= 0 if selection.count(True) > 0: integrated_data.del_selected(selection) logger.info('Removing %d profile reflections with negative variance' % \ selection.count(True)) if include_partials: integrated_data = sum_partial_reflections(integrated_data) integrated_data = scale_partial_reflections(integrated_data) if 'partiality' in integrated_data: selection = integrated_data['partiality'] < 0.99 if selection.count(True) > 0 and not keep_partials: integrated_data.del_selected(selection) logger.info('Removing %d incomplete reflections' % \ selection.count(True)) experiment = experiment_list[0] assert (not experiment.scan is None) # sort data before output nref = len(integrated_data['miller_index']) indices = flex.size_t_range(nref) perm = sorted(indices, key=lambda k: integrated_data['miller_index'][k]) integrated_data = integrated_data.select(flex.size_t(perm)) assert (not experiment.goniometer is None) axis = matrix.col(experiment.goniometer.get_rotation_axis_datum()) beam = matrix.col(experiment.beam.get_direction()) s0 = matrix.col(experiment.beam.get_s0()) F = matrix.sqr(experiment.goniometer.get_fixed_rotation()) S = matrix.sqr(experiment.goniometer.get_setting_rotation()) unit_cell = experiment.crystal.get_unit_cell() if debug: m_format = '%6.3f%6.3f%6.3f\n%6.3f%6.3f%6.3f\n%6.3f%6.3f%6.3f' c_format = '%.2f %.2f %.2f %.2f %.2f %.2f' logger.info('Unit cell parameters from experiment: %s' % (c_format % unit_cell.parameters())) logger.info( 'Symmetry: %s' % experiment.crystal.get_space_group().type().lookup_symbol()) logger.info('Goniometer fixed matrix:\n%s' % (m_format % F.elems)) logger.info('Goniometer setting matrix:\n%s' % (m_format % S.elems)) logger.info('Goniometer scan axis:\n%6.3f%6.3f%6.3f' % (axis.elems)) # detector scaling info assert (len(experiment.detector) == 1) panel = experiment.detector[0] dims = panel.get_image_size() pixel = panel.get_pixel_size() fast_axis = matrix.col(panel.get_fast_axis()) slow_axis = matrix.col(panel.get_slow_axis()) normal = fast_axis.cross(slow_axis) detector2t = s0.angle(normal, deg=True) origin = matrix.col(panel.get_origin()) if debug: logger.info('Detector fast, slow axes:') logger.info('%6.3f%6.3f%6.3f' % (fast_axis.elems)) logger.info('%6.3f%6.3f%6.3f' % (slow_axis.elems)) logger.info('Detector two theta (degrees): %.2f' % detector2t) scl_x = 512.0 / (dims[0] * pixel[0]) scl_y = 512.0 / (dims[1] * pixel[1]) image_range = experiment.scan.get_image_range() from cctbx.array_family import flex as cflex # implicit import from cctbx.miller import map_to_asu_isym # implicit import # gather the required information for the reflection file nref = len(integrated_data['miller_index']) zdet = flex.double(integrated_data['xyzcal.px'].parts()[2]) miller_index = integrated_data['miller_index'] I = None sigI = None # export including scale factors if 'lp' in integrated_data: lp = integrated_data['lp'] else: lp = flex.double(nref, 1.0) if 'qe' in integrated_data: qe = integrated_data['qe'] elif 'dqe' in integrated_data: qe = integrated_data['dqe'] else: qe = flex.double(nref, 1.0) scl = lp / qe if summation: I = integrated_data['intensity.sum.value'] * scl V = integrated_data['intensity.sum.variance'] * scl * scl assert V.all_gt(0) sigI = flex.sqrt(V) else: I = integrated_data['intensity.prf.value'] * scl V = integrated_data['intensity.prf.variance'] * scl * scl assert V.all_gt(0) sigI = flex.sqrt(V) # figure out scaling to make sure data fit into format 2F8.2 i.e. Imax < 1e5 Imax = flex.max(I) if debug: logger.info('Maximum intensity in file: %8.2f' % Imax) if Imax > 99999.0: scale = 99999.0 / Imax I = I * scale sigI = sigI * scale phi_start, phi_range = experiment.scan.get_image_oscillation( image_range[0]) if predict: logger.info('Using scan static predicted spot locations') from dials.algorithms.spot_prediction import ScanStaticReflectionPredictor predictor = ScanStaticReflectionPredictor(experiment) UB = experiment.crystal.get_A() predictor.for_reflection_table(integrated_data, UB) if not experiment.crystal.num_scan_points: logger.info('No scan varying model: use static') static = True else: static = False fout = open(hklout, 'w') for j in range(nref): h, k, l = miller_index[j] if predict: x_mm, y_mm, z_rad = integrated_data['xyzcal.mm'][j] else: x_mm, y_mm, z_rad = integrated_data['xyzobs.mm.value'][j] z0 = integrated_data['xyzcal.px'][j][2] istol = int(round(10000 * unit_cell.stol((h, k, l)))) if predict or static: # work from a scan static model & assume perfect goniometer # FIXME maybe should work back in the option to predict spot positions UB = matrix.sqr(experiment.crystal.get_A()) phi = phi_start + z0 * phi_range R = axis.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) RUB = S * R * F * UB else: # properly compute RUB for every reflection UB = matrix.sqr( experiment.crystal.get_A_at_scan_point(int(round(z0)))) phi = phi_start + z0 * phi_range R = axis.axis_and_angle_as_r3_rotation_matrix(phi, deg=True) RUB = S * R * F * UB x = RUB * (h, k, l) s = (s0 + x).normalize() # can also compute s based on centre of mass of spot # s = (origin + x_mm * fast_axis + y_mm * slow_axis).normalize() astar = (RUB * (1, 0, 0)).normalize() bstar = (RUB * (0, 1, 0)).normalize() cstar = (RUB * (0, 0, 1)).normalize() ix = beam.dot(astar) iy = beam.dot(bstar) iz = beam.dot(cstar) dx = s.dot(astar) dy = s.dot(bstar) dz = s.dot(cstar) x = x_mm * scl_x y = y_mm * scl_y z = (z_rad * 180 / math.pi - phi_start) / phi_range fout.write('%4d%4d%4d%8.2f%8.2f%4d%8.5f%8.5f%8.5f%8.5f%8.5f%8.5f' % \ (h, k, l, I[j], sigI[j], run, ix, dx, iy, dy, iz, dz)) fout.write('%7.2f%7.2f%8.2f%7.2f%5d\n' % (x, y, z, detector2t, istol)) fout.close() logger.info('Output %d reflections to %s' % (nref, hklout))