def exercise_spots_xds(): txt = """\ 1104.20 1290.27 2.20 632. -4 -3 -1 912.22 1303.37 3.49 346. 0 0 0 1427.55 1339.93 3.34 259. 7 3 -1 1380.54 1187.54 3.58 243. 4 3 4 1222.32 1220.09 3.95 241. -1 0 2 1491.71 1322.33 2.72 237. 9 4 0 1053.50 1227.71 2.87 221. -6 -4 1 """ f = open_tmp_file(suffix="SPOTS.XDS", mode="wb") f.write(txt) f.close() spots_in = spot_xds.reader() spots_in.read_file(f.name) assert approx_equal( spots_in.centroid, [[1104.2, 1290.27, 2.2], [912.22, 1303.37, 3.49], [1427.55, 1339.93, 3.34], [1380.54, 1187.54, 3.58], [1222.32, 1220.09, 3.95], [1491.71, 1322.33, 2.72], [1053.5, 1227.71, 2.87]]) assert approx_equal( spots_in.intensity, [632.0, 346.0, 259.0, 243.0, 241.0, 237.0, 221.0]) assert approx_equal( spots_in.miller_index, [[-4, -3, -1], [0, 0, 0], [7, 3, -1], [4, 3, 4], [-1, 0, 2], [9, 4, 0], [-6, -4, 1]]) spots_out = spot_xds.writer( spots_in.centroid, spots_in.intensity, spots_in.miller_index) f = open_tmp_file(suffix="SPOTS.XDS", mode="wb") f.close() spots_out.write_file(filename=f.name) spots_in = spot_xds.reader() spots_in.read_file(f.name) assert approx_equal(spots_in.centroid, spots_out.centroids) assert approx_equal(spots_in.intensity, spots_out.intensities) assert approx_equal(spots_in.miller_index, spots_out.miller_indices) # now without miller indices spots_out = spot_xds.writer(spots_in.centroid, spots_in.intensity) f = open_tmp_file(suffix="SPOTS.XDS", mode="wb") f.close() spots_out.write_file(filename=f.name) spots_in = spot_xds.reader() spots_in.read_file(f.name) assert approx_equal(spots_in.centroid, spots_out.centroids) assert approx_equal(spots_in.intensity, spots_out.intensities) assert len(spots_in.miller_index) == 0
def exercise_spots_xds(): txt = """\ 1104.20 1290.27 2.20 632. -4 -3 -1 912.22 1303.37 3.49 346. 0 0 0 1427.55 1339.93 3.34 259. 7 3 -1 1380.54 1187.54 3.58 243. 4 3 4 1222.32 1220.09 3.95 241. -1 0 2 1491.71 1322.33 2.72 237. 9 4 0 1053.50 1227.71 2.87 221. -6 -4 1 """ f = open_tmp_file(suffix="SPOTS.XDS", mode="wb") f.write(txt) f.close() spots_in = spot_xds.reader() spots_in.read_file(f.name) assert approx_equal(spots_in.centroid, [[1104.2, 1290.27, 2.2], [912.22, 1303.37, 3.49], [1427.55, 1339.93, 3.34], [1380.54, 1187.54, 3.58], [1222.32, 1220.09, 3.95], [1491.71, 1322.33, 2.72], [1053.5, 1227.71, 2.87]]) assert approx_equal(spots_in.intensity, [632.0, 346.0, 259.0, 243.0, 241.0, 237.0, 221.0]) assert approx_equal(spots_in.miller_index, [[-4, -3, -1], [0, 0, 0], [7, 3, -1], [4, 3, 4], [-1, 0, 2], [9, 4, 0], [-6, -4, 1]]) spots_out = spot_xds.writer(spots_in.centroid, spots_in.intensity, spots_in.miller_index) f = open_tmp_file(suffix="SPOTS.XDS", mode="wb") f.close() spots_out.write_file(filename=f.name) spots_in = spot_xds.reader() spots_in.read_file(f.name) assert approx_equal(spots_in.centroid, spots_out.centroids) assert approx_equal(spots_in.intensity, spots_out.intensities) assert approx_equal(spots_in.miller_index, spots_out.miller_indices) # now without miller indices spots_out = spot_xds.writer(spots_in.centroid, spots_in.intensity) f = open_tmp_file(suffix="SPOTS.XDS", mode="wb") f.close() spots_out.write_file(filename=f.name) spots_in = spot_xds.reader() spots_in.read_file(f.name) assert approx_equal(spots_in.centroid, spots_out.centroids) assert approx_equal(spots_in.intensity, spots_out.intensities) assert len(spots_in.miller_index) == 0
def main(xparm_file, spot_file): import dxtbx from dxtbx.serialize.xds import to_crystal models = dxtbx.load(xparm_file) crystal_model = to_crystal(xparm_file) from dxtbx.model.experiment.experiment_list import Experiment, ExperimentList experiment = Experiment(beam=models.get_beam(), detector=models.get_detector(), goniometer=models.get_goniometer(), scan=models.get_scan(), crystal=crystal_model) detector = experiment.detector beam = experiment.beam goniometer = experiment.goniometer scan = experiment.scan from iotbx.xds import spot_xds spot_xds_handle = spot_xds.reader() spot_xds_handle.read_file(spot_file) from cctbx.array_family import flex centroids_px = flex.vec3_double(spot_xds_handle.centroid) miller_indices = flex.miller_index(spot_xds_handle.miller_index) # only those reflections that were actually indexed centroids_px = centroids_px.select(miller_indices != (0,0,0)) miller_indices = miller_indices.select(miller_indices != (0,0,0)) ub = crystal_model.get_A() d_spacings = [1.0 / (ub * mi).length() for mi in miller_indices] print max(d_spacings) # Convert Pixel coordinate into mm/rad x, y, z = centroids_px.parts() x_mm, y_mm = detector[0].pixel_to_millimeter(flex.vec2_double(x, y)).parts() z_rad = scan.get_angle_from_array_index(z, deg=False) centroids_mm = flex.vec3_double(x_mm, y_mm, z_rad) # then convert detector position to reciprocal space position # based on code in dials/algorithms/indexing/indexer2.py s1 = detector[0].get_lab_coord(flex.vec2_double(x_mm, y_mm)) s1 = s1/s1.norms() * (1/beam.get_wavelength()) S = s1 - beam.get_s0() reciprocal_space_points = S.rotate_around_origin( goniometer.get_rotation_axis(), -z_rad) d_spacings = 1/reciprocal_space_points.norms() dmax = flex.max(d_spacings) print dmax
def __call__(self, params, options): ''' Import the spot.xds file. ''' from iotbx.xds import spot_xds from dials.util.command_line import Command from dials.array_family import flex # Read the SPOT.XDS file Command.start('Reading SPOT.XDS') handle = spot_xds.reader() handle.read_file(self._spot_xds) centroid = handle.centroid intensity = handle.intensity try: miller_index = handle.miller_index except AttributeError: miller_index = None Command.end('Read {0} spots from SPOT.XDS file.'.format(len(centroid))) # Create the reflection list Command.start('Creating reflection list') table = flex.reflection_table() table['id'] = flex.int(len(centroid), 0) table['panel'] = flex.size_t(len(centroid), 0) if miller_index: table['miller_index'] = flex.miller_index(miller_index) table['xyzobs.px.value'] = flex.vec3_double(centroid) table['intensity.sum.value'] = flex.double(intensity) Command.end('Created reflection list') # Remove invalid reflections Command.start('Removing invalid reflections') if miller_index and params.remove_invalid: flags = flex.bool([h != (0, 0, 0) for h in table['miller_index']]) table = table.select(flags) Command.end('Removed invalid reflections, %d remaining' % len(table)) # Fill empty standard columns if params.add_standard_columns: Command.start('Adding standard columns') rt = flex.reflection_table.empty_standard(len(table)) rt.update(table) table = rt # set variances to unity table['xyzobs.mm.variance'] = flex.vec3_double( len(table), (1, 1, 1)) table['xyzobs.px.variance'] = flex.vec3_double( len(table), (1, 1, 1)) Command.end('Standard columns added') # Output the table to pickle file if params.output.filename is None: params.output.filename = 'spot_xds.pickle' Command.start('Saving reflection table to %s' % params.output.filename) table.as_pickle(params.output.filename) Command.end('Saved reflection table to %s' % params.output.filename)
def __call__(self, params, options): """ Import the spot.xds file. """ from iotbx.xds import spot_xds from dials.util.command_line import Command # Read the SPOT.XDS file Command.start("Reading SPOT.XDS") handle = spot_xds.reader() handle.read_file(self._spot_xds) centroid = handle.centroid intensity = handle.intensity try: miller_index = handle.miller_index except AttributeError: miller_index = None Command.end("Read {} spots from SPOT.XDS file.".format(len(centroid))) # Create the reflection list Command.start("Creating reflection list") table = flex.reflection_table() table["id"] = flex.int(len(centroid), 0) table["panel"] = flex.size_t(len(centroid), 0) if miller_index: table["miller_index"] = flex.miller_index(miller_index) table["xyzobs.px.value"] = flex.vec3_double(centroid) table["intensity.sum.value"] = flex.double(intensity) Command.end("Created reflection list") # Remove invalid reflections Command.start("Removing invalid reflections") if miller_index and params.remove_invalid: flags = flex.bool([h != (0, 0, 0) for h in table["miller_index"]]) table = table.select(flags) Command.end("Removed invalid reflections, %d remaining" % len(table)) # Fill empty standard columns if params.add_standard_columns: Command.start("Adding standard columns") rt = flex.reflection_table.empty_standard(len(table)) rt.update(table) table = rt # set variances to unity table["xyzobs.mm.variance"] = flex.vec3_double( len(table), (1, 1, 1)) table["xyzobs.px.variance"] = flex.vec3_double( len(table), (1, 1, 1)) Command.end("Standard columns added") # Output the table to pickle file if params.output.filename is None: params.output.filename = "spot_xds.refl" Command.start("Saving reflection table to %s" % params.output.filename) table.as_file(params.output.filename) Command.end("Saved reflection table to %s" % params.output.filename)
def __call__(self, params, options): ''' Import the spot.xds file. ''' from iotbx.xds import spot_xds from dials.util.command_line import Command from dials.array_family import flex # Read the SPOT.XDS file Command.start('Reading SPOT.XDS') handle = spot_xds.reader() handle.read_file(self._spot_xds) centroid = handle.centroid intensity = handle.intensity try: miller_index = handle.miller_index except AttributeError: miller_index = None Command.end('Read {0} spots from SPOT.XDS file.'.format(len(centroid))) # Create the reflection list Command.start('Creating reflection list') table = flex.reflection_table() table['id'] = flex.int(len(centroid), 0) table['panel'] = flex.size_t(len(centroid), 0) if miller_index: table['miller_index'] = flex.miller_index(miller_index) table['xyzobs.px.value'] = flex.vec3_double(centroid) table['intensity.sum.value'] = flex.double(intensity) Command.end('Created reflection list') # Remove invalid reflections Command.start('Removing invalid reflections') if miller_index and params.remove_invalid: flags = flex.bool([h != (0, 0, 0) for h in table['miller_index']]) table = table.select(flags) Command.end('Removed invalid reflections, %d remaining' % len(table)) # Fill empty standard columns if params.add_standard_columns: Command.start('Adding standard columns') rt = flex.reflection_table.empty_standard(len(table)) rt.update(table) table = rt # set variances to unity table['xyzobs.mm.variance'] = flex.vec3_double(len(table), (1,1,1)) table['xyzobs.px.variance'] = flex.vec3_double(len(table), (1,1,1)) Command.end('Standard columns added') # Output the table to pickle file if params.output.filename is None: params.output.filename = 'spot_xds.pickle' Command.start('Saving reflection table to %s' % params.output.filename) table.as_pickle(params.output.filename) Command.end('Saved reflection table to %s' % params.output.filename)
def xds_check_indexer_solution(xparm_file, spot_file): '''Read XPARM file from XDS IDXREF (assumes that this is in the putative correct symmetry, not P1! and test centring operations if present. Note that a future version will boost to the putative correct symmetry (or an estimate of it) and try this if it is centred. Returns tuple (space_group_number, cell).''' from scitbx import matrix from dxtbx.serialize.xds import to_crystal as xparm_to_crystal cm = xparm_to_crystal(xparm_file) sg = cm.get_space_group() spacegroup = sg.type().hall_symbol() space_group_number = sg.type().number() A_inv = matrix.sqr(cm.get_A()).inverse() cell = cm.get_unit_cell().parameters() import dxtbx models = dxtbx.load(xparm_file) detector = models.get_detector() beam = models.get_beam() goniometer = models.get_goniometer() scan = models.get_scan() from iotbx.xds import spot_xds spot_xds_handle = spot_xds.reader() spot_xds_handle.read_file(spot_file) from cctbx.array_family import flex centroids_px = flex.vec3_double(spot_xds_handle.centroid) miller_indices = flex.miller_index(spot_xds_handle.miller_index) # Convert Pixel coordinate into mm/rad x, y, z = centroids_px.parts() x_mm, y_mm = detector[0].pixel_to_millimeter(flex.vec2_double(x, y)).parts() z_rad = scan.get_angle_from_array_index(z, deg=False) centroids_mm = flex.vec3_double(x_mm, y_mm, z_rad) # then convert detector position to reciprocal space position # based on code in dials/algorithms/indexing/indexer2.py s1 = detector[0].get_lab_coord(flex.vec2_double(x_mm, y_mm)) s1 = s1 / s1.norms() * (1 / beam.get_wavelength()) S = s1 - beam.get_s0() # XXX what about if goniometer fixed rotation is not identity? reciprocal_space_points = S.rotate_around_origin( goniometer.get_rotation_axis(), -z_rad) # now index the reflections hkl_float = tuple(A_inv) * reciprocal_space_points hkl_int = hkl_float.iround() # check if we are within 0.1 lattice spacings of the closest # lattice point - a for a random point this will be about 0.8% of # the time... differences = hkl_float - hkl_int.as_vec3_double() dh, dk, dl = [flex.abs(d) for d in differences.parts()] tolerance = 0.1 sel = (dh < tolerance) and (dk < tolerance) and (dl < tolerance) is_sys_absent = sg.is_sys_absent( flex.miller_index(list(hkl_int.select(sel)))) total = is_sys_absent.size() absent = is_sys_absent.count(True) present = total - absent # now, if the number of absences is substantial, need to consider # transforming this to a primitive basis Debug.write('Absent: %d vs. Present: %d Total: %d' % \ (absent, present, total)) # now see if this is compatible with a centred lattice or suggests # a primitive basis is correct sd = math.sqrt(absent) if (absent - 3 * sd) / total < 0.008: # everything is peachy return s2l(space_group_number), tuple(cell) # ok if we are here things are not peachy, so need to calculate the # spacegroup number without the translation operators sg_new = sg.build_derived_group(True, False) space_group_number_primitive = sg_new.type().number() # also determine the best setting for the new cell ... symm = crystal.symmetry(unit_cell=cell, space_group=sg_new) rdx = symm.change_of_basis_op_to_best_cell() symm_new = symm.change_basis(rdx) cell_new = symm_new.unit_cell().parameters() return s2l(space_group_number_primitive), tuple(cell_new)
def _index_finish(self): """Perform the indexer post-processing as required.""" # ok, in here now ask if this solution was sensible! if not self.get_indexer_user_input_lattice(): lattice = self._indxr_lattice cell = self._indxr_cell lattice2, cell2 = xds_check_indexer_solution( os.path.join(self.get_working_directory(), "XPARM.XDS"), os.path.join(self.get_working_directory(), "SPOT.XDS"), ) logger.debug("Centring analysis: %s => %s", lattice, lattice2) doubled_lattice = False for j in range(3): if int(round(cell2[j] / cell[j])) == 2: doubled_lattice = True axes = "A", "B", "C" logger.debug("Lattice axis doubled: %s", axes[j]) if ( self._idxref_subtree_problem and (lattice2 != lattice) ) or doubled_lattice: # hmm.... looks like we don't agree on the correct result... # update the putative correct result as input logger.debug("Detected pseudocentred lattice") logger.debug( "Inserting solution: %s " % lattice2 + "%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f" % cell2 ) self._indxr_replace(lattice2, cell2) logger.debug("Set lattice: %s", lattice2) logger.debug("Set cell: %f %f %f %f %f %f" % cell2) # then rerun self.set_indexer_done(False) return # finally read through SPOT.XDS and XPARM.XDS to get an estimate # of the low resolution limit - this should be pretty straightforward # since what I want is the resolution of the lowest resolution indexed # spot.. spot_file = os.path.join(self.get_working_directory(), "SPOT.XDS") experiment = self.get_indexer_experiment_list()[0] crystal_model = experiment.crystal spot_xds_handle = spot_xds.reader() spot_xds_handle.read_file(spot_file) miller_indices = flex.miller_index(spot_xds_handle.miller_index) # only those reflections that were actually indexed miller_indices = miller_indices.select(miller_indices != (0, 0, 0)) ub = matrix.sqr(crystal_model.get_A()) dmax = 1.05 * flex.max(1 / (ub.elems * miller_indices.as_vec3_double()).norms()) logger.debug("Low resolution limit assigned as: %.2f", dmax) self._indxr_low_resolution = dmax
def xds_check_indexer_solution(xparm_file, spot_file): '''Read XPARM file from XDS IDXREF (assumes that this is in the putative correct symmetry, not P1! and test centring operations if present. Note that a future version will boost to the putative correct symmetry (or an estimate of it) and try this if it is centred. Returns tuple (space_group_number, cell).''' from dxtbx.serialize.xds import to_crystal as xparm_to_crystal cm = xparm_to_crystal(xparm_file) sg = cm.get_space_group() spacegroup = sg.type().hall_symbol() space_group_number = sg.type().number() A_inv = cm.get_A().inverse() cell = cm.get_unit_cell().parameters() import dxtbx models = dxtbx.load(xparm_file) detector = models.get_detector() beam = models.get_beam() goniometer = models.get_goniometer() scan = models.get_scan() from iotbx.xds import spot_xds spot_xds_handle = spot_xds.reader() spot_xds_handle.read_file(spot_file) from cctbx.array_family import flex centroids_px = flex.vec3_double(spot_xds_handle.centroid) miller_indices = flex.miller_index(spot_xds_handle.miller_index) # Convert Pixel coordinate into mm/rad x, y, z = centroids_px.parts() x_mm, y_mm = detector[0].pixel_to_millimeter(flex.vec2_double(x, y)).parts() z_rad = scan.get_angle_from_array_index(z, deg=False) centroids_mm = flex.vec3_double(x_mm, y_mm, z_rad) # then convert detector position to reciprocal space position # based on code in dials/algorithms/indexing/indexer2.py s1 = detector[0].get_lab_coord(flex.vec2_double(x_mm, y_mm)) s1 = s1/s1.norms() * (1/beam.get_wavelength()) S = s1 - beam.get_s0() # XXX what about if goniometer fixed rotation is not identity? reciprocal_space_points = S.rotate_around_origin( goniometer.get_rotation_axis(), -z_rad) # now index the reflections hkl_float = tuple(A_inv) * reciprocal_space_points hkl_int = hkl_float.iround() # check if we are within 0.1 lattice spacings of the closest # lattice point - a for a random point this will be about 0.8% of # the time... differences = hkl_float - hkl_int.as_vec3_double() dh, dk, dl = [flex.abs(d) for d in differences.parts()] tolerance = 0.1 sel = (dh < tolerance) and (dk < tolerance) and (dl < tolerance) is_sys_absent = sg.is_sys_absent( flex.miller_index(list(hkl_int.select(sel)))) total = is_sys_absent.size() absent = is_sys_absent.count(True) present = total - absent # now, if the number of absences is substantial, need to consider # transforming this to a primitive basis Debug.write('Absent: %d vs. Present: %d Total: %d' % \ (absent, present, total)) # now see if this is compatible with a centred lattice or suggests # a primitive basis is correct sd = math.sqrt(absent) if (absent - 3 * sd) / total < 0.008: # everything is peachy return s2l(space_group_number), tuple(cell) # ok if we are here things are not peachy, so need to calculate the # spacegroup number without the translation operators sg_new = sg.build_derived_group(True, False) space_group_number_primitive = sg_new.type().number() # also determine the best setting for the new cell ... symm = crystal.symmetry(unit_cell = cell, space_group = sg_new) rdx = symm.change_of_basis_op_to_best_cell() symm_new = symm.change_basis(rdx) cell_new = symm_new.unit_cell().parameters() return s2l(space_group_number_primitive), tuple(cell_new)
def _index_finish(self): '''Perform the indexer post-processing as required.''' # ok, in here now ask if this solution was sensible! if not self.get_indexer_user_input_lattice(): lattice = self._indxr_lattice cell = self._indxr_cell lattice2, cell2 = xds_check_indexer_solution( os.path.join(self.get_working_directory(), 'XPARM.XDS'), os.path.join(self.get_working_directory(), 'SPOT.XDS')) Debug.write('Centring analysis: %s => %s' % \ (lattice, lattice2)) doubled_lattice = False for j in range(3): if int(round(cell2[j] / cell[j])) == 2: doubled_lattice = True axes = 'A', 'B', 'C' Debug.write('Lattice axis doubled: %s' % axes[j]) if (self._idxref_subtree_problem and (lattice2 != lattice)) or \ doubled_lattice: # hmm.... looks like we don't agree on the correct result... # update the putative correct result as input Debug.write('Detected pseudocentred lattice') Debug.write('Inserting solution: %s ' % lattice2 + '%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f' % cell2) self._indxr_replace(lattice2, cell2) Debug.write('Set lattice: %s' % lattice2) Debug.write('Set cell: %f %f %f %f %f %f' % \ cell2) # then rerun self.set_indexer_done(False) return # finally read through SPOT.XDS and XPARM.XDS to get an estimate # of the low resolution limit - this should be pretty straightforward # since what I want is the resolution of the lowest resolution indexed # spot.. spot_file = os.path.join(self.get_working_directory(), 'SPOT.XDS') experiment = self.get_indexer_experiment_list()[0] detector = experiment.detector beam = experiment.beam goniometer = experiment.goniometer scan = experiment.scan crystal_model = experiment.crystal from iotbx.xds import spot_xds spot_xds_handle = spot_xds.reader() spot_xds_handle.read_file(spot_file) from cctbx.array_family import flex centroids_px = flex.vec3_double(spot_xds_handle.centroid) miller_indices = flex.miller_index(spot_xds_handle.miller_index) # only those reflections that were actually indexed centroids_px = centroids_px.select(miller_indices != (0,0,0)) miller_indices = miller_indices.select(miller_indices != (0,0,0)) ub = crystal_model.get_A() dmax = 1.05 * flex.max(1/(ub.elems * miller_indices.as_vec3_double()).norms()) Debug.write('Low resolution limit assigned as: %.2f' % dmax) self._indxr_low_resolution = dmax return
def _index_finish(self): '''Perform the indexer post-processing as required.''' # ok, in here now ask if this solution was sensible! if not self.get_indexer_user_input_lattice(): lattice = self._indxr_lattice cell = self._indxr_cell lattice2, cell2 = xds_check_indexer_solution( os.path.join(self.get_working_directory(), 'XPARM.XDS'), os.path.join(self.get_working_directory(), 'SPOT.XDS')) Debug.write('Centring analysis: %s => %s' % \ (lattice, lattice2)) doubled_lattice = False for j in range(3): if int(round(cell2[j] / cell[j])) == 2: doubled_lattice = True axes = 'A', 'B', 'C' Debug.write('Lattice axis doubled: %s' % axes[j]) if (self._idxref_subtree_problem and (lattice2 != lattice)) or \ doubled_lattice: # hmm.... looks like we don't agree on the correct result... # update the putative correct result as input Debug.write('Detected pseudocentred lattice') Debug.write('Inserting solution: %s ' % lattice2 + '%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f' % cell2) self._indxr_replace(lattice2, cell2) Debug.write('Set lattice: %s' % lattice2) Debug.write('Set cell: %f %f %f %f %f %f' % \ cell2) # then rerun self.set_indexer_done(False) return # finally read through SPOT.XDS and XPARM.XDS to get an estimate # of the low resolution limit - this should be pretty straightforward # since what I want is the resolution of the lowest resolution indexed # spot.. spot_file = os.path.join(self.get_working_directory(), 'SPOT.XDS') experiment = self.get_indexer_experiment_list()[0] detector = experiment.detector beam = experiment.beam goniometer = experiment.goniometer scan = experiment.scan crystal_model = experiment.crystal from iotbx.xds import spot_xds spot_xds_handle = spot_xds.reader() spot_xds_handle.read_file(spot_file) from cctbx.array_family import flex centroids_px = flex.vec3_double(spot_xds_handle.centroid) miller_indices = flex.miller_index(spot_xds_handle.miller_index) # only those reflections that were actually indexed centroids_px = centroids_px.select(miller_indices != (0, 0, 0)) miller_indices = miller_indices.select(miller_indices != (0, 0, 0)) from scitbx import matrix ub = matrix.sqr(crystal_model.get_A()) dmax = 1.05 * flex.max( 1 / (ub.elems * miller_indices.as_vec3_double()).norms()) Debug.write('Low resolution limit assigned as: %.2f' % dmax) self._indxr_low_resolution = dmax return