def test_eliminate_sys_absent(): refl = flex.reflection_table() refl["miller_index"] = flex.miller_index([(-31, -5, -3), (-25, -3, -3), (0, 1, 0), (-42, -8, -2)]) sgi = sgtbx.space_group_info("C121") uc = sgi.any_compatible_unit_cell(volume=1000) B = scitbx.matrix.sqr(uc.fractionalization_matrix()).transpose() expt = Experiment( crystal=Crystal(B, space_group=sgi.group(), reciprocal=True)) reflections = eliminate_sys_absent([expt], [refl]) assert list(reflections[0]["miller_index"]) == [ (-31, -5, -3), (-25, -3, -3), (-42, -8, -2), ]
def __init__(self, experiments, reflections, params=None): super(cosym, self).__init__( events=["run_cosym", "performed_unit_cell_clustering"]) if params is None: params = phil_scope.extract() self.params = params self._reflections = [] for refl, expt in zip(reflections, experiments): sel = get_selection_for_valid_image_ranges(refl, expt) self._reflections.append(refl.select(sel)) self._experiments, self._reflections = self._filter_min_reflections( experiments, self._reflections) self.ids_to_identifiers_map = {} for table in self._reflections: self.ids_to_identifiers_map.update(table.experiment_identifiers()) self.identifiers_to_ids_map = { value: key for key, value in self.ids_to_identifiers_map.items() } if len(self._experiments) > 1: # perform unit cell clustering identifiers = self._unit_cell_clustering(self._experiments) if len(identifiers) < len(self._experiments): logger.info( "Selecting subset of %i datasets for cosym analysis: %s", len(identifiers), str(identifiers), ) self._experiments, self._reflections = select_datasets_on_identifiers( self._experiments, self._reflections, use_datasets=identifiers) # Map experiments and reflections to minimum cell cb_ops = change_of_basis_ops_to_minimum_cell( self._experiments, params.lattice_symmetry_max_delta, params.relative_length_tolerance, params.absolute_angle_tolerance, ) exclude = [ expt.identifier for expt, cb_op in zip(self._experiments, cb_ops) if not cb_op ] if len(exclude): logger.info( f"Rejecting {len(exclude)} datasets from cosym analysis " f"(couldn't determine consistent cb_op to minimum cell):\n" f"{exclude}", ) self._experiments, self._reflections = select_datasets_on_identifiers( self._experiments, self._reflections, exclude_datasets=exclude) cb_ops = list(filter(None, cb_ops)) # Eliminate reflections that are systematically absent due to centring # of the lattice, otherwise they would lead to non-integer miller indices # when reindexing to a primitive setting self._reflections = eliminate_sys_absent(self._experiments, self._reflections) self._experiments, self._reflections = apply_change_of_basis_ops( self._experiments, self._reflections, cb_ops) # transform models into miller arrays datasets = filtered_arrays_from_experiments_reflections( self.experiments, self.reflections, outlier_rejection_after_filter=False, partiality_threshold=params.partiality_threshold, ) datasets = [ ma.as_anomalous_array().merge_equivalents().array() for ma in datasets ] self.cosym_analysis = CosymAnalysis(datasets, self.params)
def __init__(self, experiments, reflections, uuid_cache_in, params=None, do_plot=False, i_plot=None, output_dir=None): super(dials_cl_cosym_wrapper, self).__init__( events=["run_cosym", "performed_unit_cell_clustering"]) if params is None: params = phil_scope.extract() self.params = params self._reflections = [] for refl, expt in zip(reflections, experiments): sel = get_selection_for_valid_image_ranges(refl, expt) self._reflections.append(refl.select(sel)) self._experiments, self._reflections = self._filter_min_reflections( experiments, self._reflections, uuid_cache_in) self.ids_to_identifiers_map = {} for table in self._reflections: self.ids_to_identifiers_map.update(table.experiment_identifiers()) self.identifiers_to_ids_map = { value: key for key, value in self.ids_to_identifiers_map.items() } if len(self._experiments) > 1: # perform unit cell clustering identifiers = self._unit_cell_clustering(self._experiments) if len(identifiers) < len(self._experiments): logger.info( "Selecting subset of %i datasets for cosym analysis: %s" % (len(identifiers), str(identifiers))) self._experiments, self._reflections = select_datasets_on_identifiers( self._experiments, self._reflections, use_datasets=identifiers) self.uuid_cache = [ self.uuid_cache[int(id)] for id in identifiers ] # Map experiments and reflections to minimum cell cb_ops = change_of_basis_ops_to_minimum_cell( self._experiments, params.lattice_symmetry_max_delta, params.relative_length_tolerance, params.absolute_angle_tolerance, ) in_cb_ops = len(cb_ops) exclude = [ expt.identifier for expt, cb_op in zip(self._experiments, cb_ops) if not cb_op ] if len(exclude): logger.info( "Rejecting {} datasets from cosym analysis "\ "(couldn't determine consistent cb_op to minimum cell):\n"\ "{}".format(len(exclude), exclude) ) self._experiments, self._reflections = select_datasets_on_identifiers( self._experiments, self._reflections, exclude_datasets=exclude) cb_ops = list(filter(None, cb_ops)) ex_cb_ops = len(cb_ops) #Normally we expect that all the cb_ops are the same (applicable for PSI with P63) assertion_dict = {} for cb_op in cb_ops: key_ = cb_op.as_hkl() assertion_dict[key_] = assertion_dict.get(key_, 0) assertion_dict[key_] += 1 if len(assertion_dict) != 1: # unexpected, there is normally only 1 cb operator to minimum cell from libtbx.mpi4py import MPI mpi_rank = MPI.COMM_WORLD.Get_rank() mpi_size = MPI.COMM_WORLD.Get_size() print( "RANK %02d, # experiments %d, after exclusion %d, unexpectedly there are %d unique cb_ops: %s" % (mpi_rank, in_cb_ops, ex_cb_ops, len(assertion_dict), ", ".join([ "%s:%d" % (key, assertion_dict[key]) for key in assertion_dict ]))) # revisit with different use cases later # In fact we need all cb_ops to match because the user might supply # a custom reindexing operator and we need to consistently tranform # it from the conventional basis into the minimum basis. Therefore, # force them all to match, but make sure user is aware. if not params.single_cb_op_to_minimum: raise RuntimeError( 'There are >1 different cb_ops to minimum and \ cosym.single_cb_op_to_minimum is not True') else: best_cb_op_str = max(assertion_dict, key=assertion_dict.get) best_cb_op = None for cb_op in cb_ops: if cb_op.as_hkl() == best_cb_op_str: best_cb_op = cb_op break assert best_cb_op is not None cb_ops = [best_cb_op] * len(cb_ops) self.cb_op_to_minimum = cb_ops # Eliminate reflections that are systematically absent due to centring # of the lattice, otherwise they would lead to non-integer miller indices # when reindexing to a primitive setting self._reflections = eliminate_sys_absent(self._experiments, self._reflections) self._experiments, self._reflections = apply_change_of_basis_ops( self._experiments, self._reflections, cb_ops) # transform models into miller arrays datasets = filtered_arrays_from_experiments_reflections( self.experiments, self.reflections, outlier_rejection_after_filter=False, partiality_threshold=params.partiality_threshold, ) datasets = [ ma.as_anomalous_array().merge_equivalents().array() for ma in datasets ] # opportunity here to subclass as defined above, instead of the dials-implemented version self.cosym_analysis = CosymAnalysis( datasets, self.params, do_plot=do_plot, i_plot=i_plot, plot_fname=self.params.plot.filename, plot_format=self.params.plot.format, output_dir=output_dir, cb_op=cb_ops[0])
def __init__(self, experiments, reflections, uuid_cache_in, params=None, do_plot=False, i_plot=None, output_dir=None): super(dials_cl_cosym_wrapper, self).__init__( events=["run_cosym", "performed_unit_cell_clustering"]) if params is None: params = phil_scope.extract() self.params = params self._reflections = [] for refl, expt in zip(reflections, experiments): sel = get_selection_for_valid_image_ranges(refl, expt) self._reflections.append(refl.select(sel)) self._experiments, self._reflections = self._filter_min_reflections( experiments, self._reflections, uuid_cache_in) self.ids_to_identifiers_map = {} for table in self._reflections: self.ids_to_identifiers_map.update(table.experiment_identifiers()) self.identifiers_to_ids_map = { value: key for key, value in self.ids_to_identifiers_map.items() } if len(self._experiments) > 1: # perform unit cell clustering identifiers = self._unit_cell_clustering(self._experiments) if len(identifiers) < len(self._experiments): logger.info( "Selecting subset of %i datasets for cosym analysis: %s" % (len(identifiers), str(identifiers))) self._experiments, self._reflections = select_datasets_on_identifiers( self._experiments, self._reflections, use_datasets=identifiers) # Map experiments and reflections to minimum cell cb_ops = change_of_basis_ops_to_minimum_cell( self._experiments, params.lattice_symmetry_max_delta, params.relative_length_tolerance, params.absolute_angle_tolerance, ) exclude = [ expt.identifier for expt, cb_op in zip(self._experiments, cb_ops) if not cb_op ] if len(exclude): logger.info( "Rejecting {} datasets from cosym analysis "\ "(couldn't determine consistent cb_op to minimum cell):\n"\ "{}".format(len(exclude), exclude) ) self._experiments, self._reflections = select_datasets_on_identifiers( self._experiments, self._reflections, exclude_datasets=exclude) cb_ops = list(filter(None, cb_ops)) # Eliminate reflections that are systematically absent due to centring # of the lattice, otherwise they would lead to non-integer miller indices # when reindexing to a primitive setting self._reflections = eliminate_sys_absent(self._experiments, self._reflections) self._experiments, self._reflections = apply_change_of_basis_ops( self._experiments, self._reflections, cb_ops) # transform models into miller arrays datasets = filtered_arrays_from_experiments_reflections( self.experiments, self.reflections, outlier_rejection_after_filter=False, partiality_threshold=params.partiality_threshold, ) datasets = [ ma.as_anomalous_array().merge_equivalents().array() for ma in datasets ] # opportunity here to subclass as defined above, instead of the dials-implemented version self.cosym_analysis = CosymAnalysis( datasets, self.params, do_plot=do_plot, i_plot=i_plot, plot_fname=self.params.plot.filename, plot_format=self.params.plot.format, output_dir=output_dir) #Fixed in subclass: parent class apparently erases the knowledge of input-to-minimum cb_ops. # without storing the op in self, we can never trace back to input setting. self.cb_op_to_minimum = cb_ops #Not sure yet, we may be assuming that all the cb_ops are the same (applicable for PSI with P63) assertion_set = set(cb_ops) assert len( assertion_set ) == 1 # guarantees all are the same; revisit with different use cases later