def as_explist(self): """ return experiment list for simulated image """ exp = Experiment() exp.crystal = self.crystal exp.beam = self.beam exp.detector = self.detector exp.imageset = self.imageset explist = ExperimentList() explist.append(exp) return explist
def as_explist(self, fname=None, toggle_conventions=False): """ return experiment list for simulated image """ C = self.crystal if toggle_conventions: # switch to DIALS convention before writing CBF # also change basis of crystal CURRENT_CONV = self.beamcenter_convention FSO = sqr(self.fdet_vector + self.sdet_vector + self.pix0_vector_mm) self.beamcenter_convention = DIALS FSO2 = sqr(self.fdet_vector + self.sdet_vector + self.dials_origin_mm) xtal_transform = FSO.inverse() * FSO2 # transform the crystal vectors a, b, c = map(lambda x: xtal_transform * col(x), C.get_real_space_vectors()) Cdict = C.to_dict() Cdict['real_space_a'] = a Cdict['real_space_b'] = b Cdict['real_space_b'] = c C = CrystalFactory.from_dict(Cdict) exp = Experiment() exp.crystal = C exp.beam = self.beam exp.detector = self.detector exp.imageset = self.imageset explist = ExperimentList() explist.append(exp) if fname is not None: explist.as_file(fname) if toggle_conventions: self.beamcenter_convention = CURRENT_CONV return explist
def load(entry, exp_index): from dxtbx.model.experiment_list import Experiment, ExperimentList print("Loading NXmx") # Check file contains the feature assert "features" in entry assert 6 in entry["features"][()] experiment_list = ExperimentList() # Find all the experiments entries = find_nx_mx_entries(entry, ".") if len(entries) > 1: entries = sorted(entries, key=lambda x: x["dials/index"][()]) assert len(entries) == len(exp_index) for nxmx, name in zip(entries, exp_index): assert np.string_(nxmx.name) == name, (nxmx.name, name) index = [] rotations = [] for name in exp_index: # Get the entry nxmx = entry.file[name] # Get the definition definition = nxmx["definition"] assert definition[()] == "NXmx" assert definition.attrs["version"] == 1 # Get dials specific stuff nx_dials = get_nx_dials(nxmx, "dials") # Set index b = nx_dials["index"].attrs["source"] d = nx_dials["index"].attrs["detector"] if "goniometer" in nx_dials["index"].attrs: g = nx_dials["index"].attrs["goniometer"] else: g = None if "scan" in nx_dials["index"].attrs: s = nx_dials["index"].attrs["scan"] else: s = None c = nx_dials["index"].attrs["sample"] index.append((b, d, g, s, c)) # Get the original orientation (dials specific) transformations = get_nx_transformations(nx_dials, "transformations") angle = transformations["angle"][()] assert transformations["angle"].attrs[ "transformation_type"] == "rotation" axis = transformations["angle"].attrs["vector"] assert tuple(transformations["angle"].attrs["offset"]) == (0, 0, 0) assert transformations["angle"].attrs["offset_units"] == "mm" assert transformations["angle"].attrs["depends_on"] == "." rotations.append((axis, angle)) # Get the imageset try: image_range = nx_dials["template"].attrs["range"] except Exception: image_range = None # Create the experiment experiment = Experiment() # Read the models experiment.beam = load_beam(nxmx) experiment.detector = load_detector(nxmx) experiment.goniometer = load_goniometer(nxmx) experiment.scan = load_scan(nxmx) experiment.crystal = load_crystal(nxmx) # Set the image range if image_range is not None and experiment.scan is not None: num = image_range[1] - image_range[0] + 1 assert num == len(experiment.scan) experiment.scan.set_image_range([int(x) for x in image_range]) # Return the experiment list experiment_list.append(experiment) # Convert from nexus beam direction experiment_list = convert_from_nexus_beam_direction( experiment_list, rotations) beam = collections.defaultdict(list) detector = collections.defaultdict(list) goniometer = collections.defaultdict(list) scan = collections.defaultdict(list) crystal = collections.defaultdict(list) for i, ind in enumerate(index): beam[ind[0]].append(i) detector[ind[1]].append(i) goniometer[ind[2]].append(i) scan[ind[3]].append(i) crystal[ind[4]].append(i) # Set all the shared beams for value in beam.values(): b1 = experiment_list[value[0]].beam assert all(experiment_list[v].beam == b1 for v in value[1:]) for v in value[1:]: experiment_list[v].beam = b1 # Set all the shared detectors for value in detector.values(): d1 = experiment_list[value[0]].detector assert all(experiment_list[v].detector == d1 for v in value[1:]) for v in value[1:]: experiment_list[v].detector = d1 # Set all the shared goniometer for value in goniometer.values(): g1 = experiment_list[value[0]].goniometer assert all(experiment_list[v].goniometer == g1 for v in value[1:]) for v in value[1:]: experiment_list[v].goniometer = g1 # Set all the shared scans for value in scan.values(): s1 = experiment_list[value[0]].scan assert all(experiment_list[v].scan == s1 for v in value[1:]) for v in value[1:]: experiment_list[v].scan = s1 # Set all the shared crystals for value in crystal.values(): c1 = experiment_list[value[0]].crystal assert all(experiment_list[v].crystal == c1 for v in value[1:]) for v in value[1:]: experiment_list[v].crystal = c1 return experiment_list
bg = is_bg_pixel[i_panel, j1:j2, i1:i2] # update the background pixel selection with the expanded integration mask is_bg_pixel[i_panel, j1:j2, i1:i2] = ~np.logical_or(~bg, expanded_integration_mask) # <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> # RUN THE TILT PLANE HELPER FUNCTION # 1. Weighted fit of the background tilt plane # 2. Updates prediction reflection table with miller indices, and shoeboxes # 3. Updates prediction reflections with integrations and integration variances # using Leslie 99 # <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> exper = Experiment() exper.detector = DET exper.beam = BEAM exper.crystal = crystal exper.imageset = iset # Exper.imageset if not args.oldway: refls_predict = TiltPlanes.prep_relfs_for_tiltalization(refls_predict, exper=exper) tiltnation = TiltPlanes(panel_imgs=img_data, panel_bg_masks=is_bg_pixel, panel_badpix_masks=None) tiltnation.check_if_refls_are_formatted_for_this_class(refls_predict) tiltnation.make_quick_bad_pixel_proximity_checker(refls_predict) tiltnation.sigma_rdout = sigma_readout tiltnation.adu_per_photon = GAIN tiltnation.delta_Q = args.deltaq #0.085 tiltnation.zinger_zscore = args.Z
# thresh=0, # filter=scipy.ndimage.filters.gaussian_filter, sigma=1) # save the crystal models and other data for later use and debugging reflsA = refls_strong.select( flex.bool(np.logical_and(best == 0, d / .10992 < 5))) reflsB = refls_strong.select( flex.bool(np.logical_and(best == 1, d / .10992 < 5))) eA = Experiment() eA.beam = beamA eA.detector = detector eA.imageset = iset eA.crystal = cryst_model eB = Experiment() eB.beam = beamB eB.detector = detector eB.imageset = iset eB.crystal = cryst_model EL = ExperimentList() EL.append(eA) EL.append(eB) exp_json = os.path.join(out_dir, "expAB_%d.json" % idx) reflA_pkl = os.path.join(out_dir, "reflA_%d.pkl" % idx) reflB_pkl = os.path.join(out_dir, "reflB_%d.pkl" % idx) orientAB.export_as_json(EL, exp_json)
def split_for_scan_range(self, experiments, reference, scan_range): """ Update experiments when scan range is set. """ from dxtbx.model.experiment_list import ExperimentList from dxtbx.model.experiment_list import Experiment # Only do anything is the scan range is set if scan_range is not None and len(scan_range) > 0: # Ensure that all experiments have the same imageset and scan iset = [e.imageset for e in experiments] scan = [e.scan for e in experiments] assert all(x == iset[0] for x in iset) assert all(x == scan[0] for x in scan) # Get the imageset and scan iset = experiments[0].imageset scan = experiments[0].scan # Get the array range if scan is not None: frames_start, frames_end = scan.get_array_range() assert scan.get_num_images() == len(iset) else: frames_start, frames_end = (0, len(iset)) # Create the new lists new_experiments = ExperimentList() new_reference_all = reference.split_by_experiment_id() new_reference = flex.reflection_table() for i in range(len(new_reference_all) - len(experiments)): new_reference_all.append(flex.reflection_table()) assert len(new_reference_all) == len(experiments) # Loop through all the scan ranges and create a new experiment list with # the requested scan ranges. for scan_start, scan_end in scan_range: # Validate the requested scan range if scan_end == scan_start: raise Sorry( "Scan range end must be higher than start; pass {},{} for single image" .format(scan_start, scan_start + 1)) if scan_end < scan_start: raise Sorry("Scan range must be in ascending order") elif scan_start < frames_start or scan_end > frames_end: raise Sorry( "Scan range must be within image range {}..{}".format( frames_start, frames_end)) assert scan_end > scan_start assert scan_start >= frames_start assert scan_end <= frames_end index_start = scan_start - frames_start index_end = index_start + (scan_end - scan_start) assert index_start < index_end assert index_start >= 0 assert index_end <= len(iset) new_iset = iset[index_start:index_end] if scan is None: new_scan = None else: new_scan = scan[index_start:index_end] for i, e1 in enumerate(experiments): e2 = Experiment() e2.beam = e1.beam e2.detector = e1.detector e2.goniometer = e1.goniometer e2.crystal = e1.crystal e2.profile = e1.profile e2.imageset = new_iset e2.scan = new_scan new_reference_all[i]["id"] = flex.int( len(new_reference_all[i]), len(new_experiments)) new_reference.extend(new_reference_all[i]) new_experiments.append(e2) experiments = new_experiments reference = new_reference # Print some information logger.info( "Modified experiment list to integrate over requested scan range" ) for scan_start, scan_end in scan_range: logger.info(" scan_range = %d -> %d" % (scan_start, scan_end)) logger.info("") # Return the experiments return experiments, reference
def split_for_scan_range(self, experiments, reference, scan_range): ''' Update experiments when scan range is set. ''' from dxtbx.model.experiment_list import ExperimentList from dxtbx.model.experiment_list import Experiment from dials.array_family import flex # Only do anything is the scan range is set if scan_range is not None and len(scan_range) > 0: # Ensure that all experiments have the same imageset and scan iset = [e.imageset for e in experiments] scan = [e.scan for e in experiments] assert (all(x == iset[0] for x in iset)) assert (all(x == scan[0] for x in scan)) # Get the imageset and scan iset = experiments[0].imageset scan = experiments[0].scan # Get the array range if scan is not None: frame10, frame11 = scan.get_array_range() assert (scan.get_num_images() == len(iset)) else: frame10, frame11 = (0, len(iset)) # Create the new lists new_experiments = ExperimentList() new_reference_all = reference.split_by_experiment_id() new_reference = flex.reflection_table() for i in range(len(new_reference_all) - len(experiments)): new_reference_all.append(flex.reflection_table()) assert (len(new_reference_all) == len(experiments)) # Loop through all the scan ranges and create a new experiment list with # the requested scan ranges. for frame00, frame01 in scan_range: assert (frame01 > frame00) assert (frame00 >= frame10) assert (frame01 <= frame11) index0 = frame00 - frame10 index1 = index0 + (frame01 - frame00) assert (index0 < index1) assert (index0 >= 0) assert (index1 <= len(iset)) new_iset = iset[index0:index1] if scan is None: new_scan = None else: new_scan = scan[index0:index1] for i, e1 in enumerate(experiments): e2 = Experiment() e2.beam = e1.beam e2.detector = e1.detector e2.goniometer = e1.goniometer e2.crystal = e1.crystal e2.imageset = new_iset e2.scan = new_scan new_reference_all[i]['id'] = flex.int( len(new_reference_all[i]), len(new_experiments)) new_reference.extend(new_reference_all[i]) new_experiments.append(e2) experiments = new_experiments reference = new_reference # Print some information logger.info( 'Modified experiment list to integrate over requested scan range' ) for frame00, frame01 in scan_range: logger.info(' scan_range = %d -> %d' % (frame00, frame01)) logger.info('') # Return the experiments return experiments, reference
# code to go from saved refl table to # other one #def add_rlp(refls, detector, beam): from dials.algorithms.indexing.indexer import indexer_base from dxtbx.model.experiment_list import Experiment, ExperimentList from cxi_xdr_xes.two_color.two_color_indexer import index_reflections_detail # make the 3 experiments e = Experiment() e.beam = beamA e.crystal = optCrystal e.detector = detector e2 = deepcopy(e) e2.beam = beamB e2.crystal = e.crystal e3 = deepcopy(e) beamAB = deepcopy(beamA) waveAB = beamA.get_wavelength()*.5 + beamB.get_wavelength()*.5 beamAB.set_wavelength( waveAB) e3.beam = beamAB e3.crystal = e.crystal el = ExperimentList() el.append(e) el.append(e2) el.append(e3) ####
def run(space_group_info): datablock_json = os.path.join(dials_regression, "indexing_test_data", "i04_weak_data", "datablock_orig.json") datablock = load.datablock(datablock_json, check_format=False)[0] sweep = datablock.extract_imagesets()[0] sweep._indices = sweep._indices[:20] sweep.set_scan(sweep.get_scan()[:20]) import random space_group = space_group_info.group() unit_cell = space_group_info.any_compatible_unit_cell( volume=random.uniform(1e4, 1e6)) crystal_symmetry = crystal.symmetry(unit_cell=unit_cell, space_group=space_group) crystal_symmetry.show_summary() # the reciprocal matrix B = matrix.sqr(unit_cell.fractionalization_matrix()).transpose() U = random_rotation() A = U * B direct_matrix = A.inverse() cryst_model = Crystal(direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group) experiment = Experiment(imageset=sweep, beam=sweep.get_beam(), detector=sweep.get_detector(), goniometer=sweep.get_goniometer(), scan=sweep.get_scan(), crystal=cryst_model) predicted_reflections = flex.reflection_table.from_predictions(experiment) use_fraction = 0.3 use_sel = flex.random_selection( len(predicted_reflections), int(use_fraction * len(predicted_reflections))) predicted_reflections = predicted_reflections.select(use_sel) miller_indices = predicted_reflections['miller_index'] miller_set = miller.set(crystal_symmetry, miller_indices, anomalous_flag=True) predicted_reflections['xyzobs.mm.value'] = predicted_reflections[ 'xyzcal.mm'] predicted_reflections['id'] = flex.int(len(predicted_reflections), 0) from dials.algorithms.indexing.indexer import indexer_base indexer_base.map_centroids_to_reciprocal_space(predicted_reflections, sweep.get_detector(), sweep.get_beam(), sweep.get_goniometer()) # check that local and global indexing worked equally well in absence of errors result = compare_global_local(experiment, predicted_reflections, miller_indices) assert result.misindexed_local == 0 assert result.misindexed_global == 0 a, b, c = map(matrix.col, cryst_model.get_real_space_vectors()) relative_error = 0.02 a *= (1 + relative_error) b *= (1 + relative_error) c *= (1 + relative_error) cryst_model2 = Crystal(a, b, c, space_group=space_group) experiment.crystal = cryst_model2 result = compare_global_local(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors #assert result.misindexed_local < result.misindexed_global assert result.misindexed_local == 0 assert result.correct_local > result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local)) # the reciprocal matrix A = matrix.sqr(cryst_model.get_A()) A = random_rotation(angle_max=0.03) * A direct_matrix = A.inverse() cryst_model2 = Crystal(direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group) experiment.crystal = cryst_model2 result = compare_global_local(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors assert result.misindexed_local <= result.misindexed_global, ( result.misindexed_local, result.misindexed_global) assert result.misindexed_local < 0.01 * result.correct_local assert result.correct_local > result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local))
pass continue print("####\n *_* IndexingWORKED %d *_* \n####" % idx) n_idx += 1 indexed_shots.append(idx) try: np.savetxt(indexed_f, indexed_shots, fmt="%d") except: pass crystalAB = orientAB.refined_experiments.crystals()[0] E = Experiment() E.beam = BEAM E.detector = DET E.imageset = iset E.crystal = crystalAB EL = ExperimentList() EL.append(E) exp_json = os.path.join(out_dir, "exp_%d_%s.json" % (idx, tag) ) refl_pkl = os.path.join(out_dir, "refl_%d_%s.pkl" % (idx, tag)) orientAB.export_as_json( EL, exp_json) utils.save_flex(refls_strong, refl_pkl) t = loader.times[idx] # event time sec, nsec, fid = t.seconds(), t.nanoseconds(), t.fiducial() t_num, _ = utils.make_event_time( sec, nsec, fid) dump = {"crystalAB": crystalAB, "event_time": t_num, "tsec": sec,"tnsec": nsec, "tfid": fid,
def load(entry, exp_index): from dxtbx.model.experiment_list import ExperimentList from dxtbx.model.experiment_list import Experiment print "Loading NXmx" # Check file contains the feature assert ("features" in entry) assert (6 in entry['features'].value) experiment_list = ExperimentList() # Find all the experiments entries = find_nx_mx_entries(entry, ".") if len(entries) > 1: entries = sorted(entries, key=lambda x: x['dials/index'].value) assert (len(entries) == len(exp_index)) for nxmx, name in zip(entries, exp_index): assert (nxmx.name == name) index = [] rotations = [] for name in exp_index: # Get the entry nxmx = entry.file[name] # Get the definition definition = nxmx['definition'] assert (definition.value == 'NXmx') assert (definition.attrs['version'] == 1) # Get dials specific stuff nx_dials = get_nx_dials(nxmx, "dials") # Set index b = nx_dials['index'].attrs['source'] d = nx_dials['index'].attrs['detector'] if "goniometer" in nx_dials['index'].attrs: g = nx_dials['index'].attrs['goniometer'] else: g = None if "scan" in nx_dials['index'].attrs: s = nx_dials['index'].attrs['scan'] else: s = None c = nx_dials['index'].attrs['sample'] index.append((b, d, g, s, c)) # Get the original orientation (dials specific) transformations = get_nx_transformations(nx_dials, "transformations") angle = transformations['angle'].value assert (transformations['angle'].attrs['transformation_type'] == 'rotation') axis = transformations['angle'].attrs['vector'] assert (tuple(transformations['angle'].attrs['offset']) == (0, 0, 0)) assert (transformations['angle'].attrs['offset_units'] == 'mm') assert (transformations['angle'].attrs['depends_on'] == '.') rotations.append((axis, angle)) # Get the tmeplate and imageset try: template = list(nx_dials['template']) image_range = None except Exception: template = nx_dials['template'].value if template == "": template = None if "range" in nx_dials['template'].attrs: image_range = nx_dials['template'].attrs['range'] else: image_range = None # Create the experiment experiment = Experiment() # Read the models experiment.beam = load_beam(nxmx) experiment.detector = load_detector(nxmx) experiment.goniometer = load_goniometer(nxmx) experiment.scan = load_scan(nxmx) experiment.crystal = load_crystal(nxmx) # Set the image range if image_range is not None and experiment.scan is not None: num = image_range[1] - image_range[0] + 1 assert (num == len(experiment.scan)) experiment.scan.set_image_range(image_range) # Return the experiment list experiment_list.append(experiment) # Convert from nexus beam direction experiment_list = convert_from_nexus_beam_direction( experiment_list, rotations) from collections import defaultdict beam = defaultdict(list) detector = defaultdict(list) goniometer = defaultdict(list) scan = defaultdict(list) crystal = defaultdict(list) for i, ind in enumerate(index): beam[ind[0]].append(i) detector[ind[1]].append(i) goniometer[ind[2]].append(i) scan[ind[3]].append(i) crystal[ind[4]].append(i) # Set all the shared beams for key, value in beam.iteritems(): b1 = experiment_list[value[0]].beam assert (all(experiment_list[v].beam == b1 for v in value[1:])) for v in value[1:]: experiment_list[v].beam = b1 # Set all the shared detectors for key, value in detector.iteritems(): d1 = experiment_list[value[0]].detector assert (all(experiment_list[v].detector == d1 for v in value[1:])) for v in value[1:]: experiment_list[v].detector = d1 # Set all the shared goniometer for key, value in goniometer.iteritems(): g1 = experiment_list[value[0]].goniometer assert (all(experiment_list[v].goniometer == g1 for v in value[1:])) for v in value[1:]: experiment_list[v].goniometer = g1 # Set all the shared scans for key, value in scan.iteritems(): s1 = experiment_list[value[0]].scan assert (all(experiment_list[v].scan == s1 for v in value[1:])) for v in value[1:]: experiment_list[v].scan = s1 # Set all the shared crystals for key, value in crystal.iteritems(): c1 = experiment_list[value[0]].crystal assert (all(experiment_list[v].crystal == c1 for v in value[1:])) for v in value[1:]: experiment_list[v].crystal = c1 return experiment_list
iset = dblock.extract_imagesets()[0] if index: orientAB = indexer_two_color(reflections=refls, imagesets=[iset], params=mad_index_params) orientAB.index() C = orientAB.refined_experiments.crystals()[0] utils.save_flex({"C": C}, "C%d.pkl" % shot_idx) from dxtbx.model.experiment_list import Experiment, ExperimentList e = Experiment() e.detector = D e.beam = B e.crystal = C e.imageset = iset el = ExperimentList() el.append(e) orientAB.export_as_json(el, "exp%d.json" % shot_idx) ############## ############# ############## ############## ############## ############## ############## ############# ############# #############
def test_assign_indices(dials_regression, space_group_symbol): experiments_json = os.path.join(dials_regression, "indexing_test_data", "i04_weak_data", "datablock_orig.json") experiments = load.experiment_list(experiments_json, check_format=False) sweep = experiments.imagesets()[0] sweep = sweep[:20] # set random seeds so tests more reliable seed = 54321 random.seed(seed) flex.set_random_seed(seed) space_group_info = sgtbx.space_group_info(symbol=space_group_symbol) space_group = space_group_info.group() unit_cell = space_group_info.any_compatible_unit_cell( volume=random.uniform(1e4, 1e6)) crystal_symmetry = crystal.symmetry(unit_cell=unit_cell, space_group=space_group) crystal_symmetry.show_summary() # the reciprocal matrix B = matrix.sqr(unit_cell.fractionalization_matrix()).transpose() U = random_rotation() A = U * B direct_matrix = A.inverse() cryst_model = Crystal( direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group, ) experiment = Experiment( imageset=sweep, beam=sweep.get_beam(), detector=sweep.get_detector(), goniometer=sweep.get_goniometer(), scan=sweep.get_scan(), crystal=cryst_model, ) predicted_reflections = flex.reflection_table.from_predictions(experiment) use_fraction = 0.3 use_sel = flex.random_selection( len(predicted_reflections), int(use_fraction * len(predicted_reflections))) predicted_reflections = predicted_reflections.select(use_sel) miller_indices = predicted_reflections["miller_index"] predicted_reflections["xyzobs.mm.value"] = predicted_reflections[ "xyzcal.mm"] predicted_reflections["id"] = flex.int(len(predicted_reflections), 0) predicted_reflections.map_centroids_to_reciprocal_space( sweep.get_detector(), sweep.get_beam(), sweep.get_goniometer()) # check that local and global indexing worked equally well in absence of errors result = CompareGlobalLocal(experiment, predicted_reflections, miller_indices) assert result.misindexed_local == 0 assert result.misindexed_global == 0 a, b, c = map(matrix.col, cryst_model.get_real_space_vectors()) relative_error = 0.02 a *= 1 + relative_error b *= 1 + relative_error c *= 1 + relative_error cryst_model2 = Crystal(a, b, c, space_group=space_group) experiment.crystal = cryst_model2 result = CompareGlobalLocal(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors # assert result.misindexed_local < result.misindexed_global assert result.misindexed_local == 0 assert result.correct_local > result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local)) # the reciprocal matrix A = matrix.sqr(cryst_model.get_A()) A = random_rotation(angle_max=0.5) * A direct_matrix = A.inverse() cryst_model2 = Crystal( direct_matrix[0:3], direct_matrix[3:6], direct_matrix[6:9], space_group=space_group, ) experiment.crystal = cryst_model2 result = CompareGlobalLocal(experiment, predicted_reflections, miller_indices) # check that the local indexing did a better job given the errors in the basis vectors assert result.misindexed_local <= result.misindexed_global, ( result.misindexed_local, result.misindexed_global, ) assert result.misindexed_local < 0.01 * result.correct_local assert result.correct_local >= result.correct_global # usually the number misindexed is much smaller than this assert result.misindexed_local < (0.001 * len(result.reflections_local))