def correct_intensities_for_dac_attenuation( experiment: Experiment, reflections: flex.reflection_table, dac_norm: Vector, thickness: float, density: float = 3.51, ) -> None: """ Boost integrated intensities to account for attenuation by a diamond anvil cell. Take an experiment object and reflection table containing integrated but unscaled diffraction data, boost the integrated reflection intensities to correct for the estimated attenuation due to the passage of the incident and diffracted beams through the diamond anvils. Args: experiment: An experiment from integrated data. reflections: A table of reflections from integrated data. dac_norm: A 3-vector representing the normal to the anvil surfaces in the laboratory frame when the goniometer is at zero datum, i.e. the axes are all at 0°. The vector is assumed to be normalised. thickness: The thickness of each diamond anvil (assumed equal). density: The density of the anvil material in g·cm⁻³ (units chosen for consistency with the NIST tables of X-ray mass attenuation coefficients, https://dx.doi.org/10.18434/T4D01F). Defaults to a typical value for synthetic diamond. """ # Select only those reflections whose intensities after integration ought to be # meaningful. sel = reflections.get_flags(reflections.flags.integrated, all=False) sel = sel.iselection() refls_sel = reflections.select(sel) correction = attenuation_correction(experiment, refls_sel, dac_norm, thickness, density) # We need only correct non-null values for each integration method. prf_subsel = refls_sel.get_flags(refls_sel.flags.integrated_prf) sum_subsel = refls_sel.get_flags(refls_sel.flags.integrated_sum) # Correct the measured intensities and variances for this attenuation. methods = {"prf": prf_subsel, "sum": sum_subsel} quantities = {"value": correction, "variance": flex.pow2(correction)} for method, subsel in methods.items(): setting_subsel = sel.select(subsel) for quantity, factor in quantities.items(): col = f"intensity.{method}.{quantity}" corrected = (refls_sel[col] * factor).select(subsel) try: reflections[col].set_selected(setting_subsel, corrected) except KeyError: pass
def preprocess( experiments: ExperimentList, observed: flex.reflection_table, params: phil.scope_extract, ) -> Tuple[List[flex.reflection_table], phil.scope_extract, List[str]]: reflections = observed.split_by_experiment_id() if len(reflections) != len(experiments): # spots may not have been found on every image. In this case, the length # of the list of reflection tables will be less than the length of experiments. # Add in empty items to the list, so that this can be reported on no_refls = set(range(len(experiments))).difference(set(observed["id"])) for i in no_refls: reflections.insert(i, None) if len(experiments) != len(reflections): raise ValueError( f"Unequal number of reflection tables {len(reflections)} and experiments {len(experiments)}" ) # Calculate necessary quantities for refl, experiment in zip(reflections, experiments): if refl: elist = ExperimentList([experiment]) refl["imageset_id"] = flex.int(refl.size(), 0) # needed for centroid_px_to_mm refl.centroid_px_to_mm(elist) refl.map_centroids_to_reciprocal_space(elist) # Determine the max cell if applicable if (params.indexing.max_cell is Auto) and (not params.indexing.known_symmetry.unit_cell): if params.individual_log_verbosity <= 2: # suppress the max cell debug log logging.getLogger("dials.algorithms.indexing.max_cell").setLevel( logging.INFO) max_cells = [] for refl in reflections: if refl: try: max_cells.append(find_max_cell(refl).max_cell) except (DialsIndexError, AssertionError): pass if not max_cells: raise ValueError("Unable to find a max cell for any images") logger.info(f"Setting max cell to {max(max_cells):.1f} " + "\u212B") params.indexing.max_cell = max(max_cells) # Determine which methods to try method_list = params.method if "real_space_grid_search" in method_list: if not params.indexing.known_symmetry.unit_cell: logger.info( "No unit cell given, real_space_grid_search will not be used") method_list.remove("real_space_grid_search") methods = ", ".join(method_list) pl = "s" if (len(method_list) > 1) else "" logger.info(f"Attempting indexing with {methods} method{pl}") return reflections, params, method_list
def sum_integrate_and_update_table( reflections: reflection_table, image_volume: MultiPanelImageVolume = None) -> reflection_table: """Perform 3D summation integration and update a reflection table. Arguments: reflections: The reflections to integrate Returns: The integrated reflections """ # Integrate and return the reflections if image_volume is None: intensity = reflections["shoebox"].summed_intensity() else: intensity = sum_image_volume(reflections, image_volume) reflections["intensity.sum.value"] = intensity.observed_value() reflections["intensity.sum.variance"] = intensity.observed_variance() reflections["background.sum.value"] = intensity.background_value() reflections["background.sum.variance"] = intensity.background_variance() success = intensity.observed_success() reflections.set_flags(success, reflections.flags.integrated_sum) return success
def filter_reflection_table(reflection_table: flex.reflection_table, intensity_choice: List[str], *args: Any, **kwargs: Any) -> flex.reflection_table: """Filter the data and delete unneeded intensity columns. A list of which intensities to filter on e.g "sum", "scale", "profile" or allowed combinations. If a combination is given, only those reflections which have valid reflections for the multiple intensity types are retained. Strict checks are made that the requested intensity choice(s) has the required data in the reflection table. Args: reflection_table: a single reflection table object intensity_choice[List]: a list of the which intensities to filter on Returns: A reflection table filtered based on the arguments (of reduced size compared to the input table.) Raises: ValueError: if invalid intensity_choice given, if one step of filtering causes no reflections to remain, if no profile reflections remain after filtering and the choice is "profile". """ if not isinstance(intensity_choice, list): raise ValueError("intensity_choice must be List[str]") if intensity_choice == ["scale"]: reducer: Type[FilterForExportAlgorithm] = ScaleIntensityReducer elif intensity_choice == ["sum"]: reducer = SumIntensityReducer elif intensity_choice == ["profile"]: reducer = PrfIntensityReducer elif all(i in intensity_choice for i in ["sum", "scale", "profile"]): reducer = AllSumPrfScaleIntensityReducer elif all(i in intensity_choice for i in ["sum", "profile"]): reducer = SumAndPrfIntensityReducer elif all(i in intensity_choice for i in ["sum | profile"]): reducer = SumORPrfIntensityReducer elif all(i in intensity_choice for i in ["sum", "scale"]): reducer = SumAndScaleIntensityReducer else: raise ValueError(( "Unrecognised intensity choice for filter_reflection_table,\n" "value read: {}\n" "must be one of: 'scale', 'profile', 'sum', 'profile sum', \n" " 'sum scale', 'profile sum scale'\n" "(if parsing from command line, multiple choices passed as e.g. profile+sum" ).format(intensity_choice)) # Validate that the reflection table has the columns we need required_columns_lookup = { "scale": {"inverse_scale_factor", "intensity.scale.value"}, "profile": {"intensity.prf.value"}, "sum": {"intensity.sum.value"}, } for intensity_kind, required_columns in required_columns_lookup.items(): if intensity_kind in intensity_choice: missing_columns = required_columns - set(reflection_table.keys()) if missing_columns: raise ValueError( "Cannot export intensity kind '{}'; missing column(s): {}". format(intensity_kind, ", ".join(missing_columns))) # Do the filtering, but with an exception for the case of no profile fitted # reflections - in this case, try to reprocess without profile fitted. try: reflection_table = reducer.filter_for_export(reflection_table, *args, **kwargs) except NoProfilesException as e: logger.warning(e, exc_info=True) if "profile" in intensity_choice: intensity_choice.remove("profile") else: intensity_choice = None if intensity_choice: logger.info( "Attempting to reprocess with intensity choice: %s", " + ".join(i for i in intensity_choice), ) reflection_table = filter_reflection_table(reflection_table, intensity_choice, *args, **kwargs) else: raise ValueError( "Unable to process data due to absence of profile fitted reflections" ) return reflection_table