def _report(self, experiments, reflections): # type: (ExperimentList, flex.reflection_table) -> None """ Run `dials.report` on an experiment list and reflection table. Args: experiments: An experiment list. reflections: The corresponding reflection table. """ info("\nCreating report...") command = ["dials.report", experiments, reflections] result = procrunner.run(command, print_stdout=False, debug=procrunner_debug) debug("result = %s", screen19.prettyprint_dictionary(result)) if result["exitcode"] == 0: info("Successfully completed (%.1f sec)", result["runtime"]) # if sys.stdout.isatty(): # info("Trying to start browser") # try: # import subprocess # d = dict(os.environ) # d["LD_LIBRARY_PATH"] = "" # subprocess.Popen(["xdg-open", "dials-report.html"], env=d) # except Exception as e: # debug("Could not open browser\n%s", str(e)) else: warning("Failed with exit code %d", result["exitcode"]) sys.exit(1)
def _refine_bravais(self, experiments, reflections): # type: (ExperimentList, flex.reflection_table) -> None """ Run `dials.refine_bravais_settings` on an experiments and reflections. Args: experiments: An experiment list.. reflections: The corresponding reflection table. """ info("\nRefining Bravais settings...") command = [ "dials.refine_bravais_settings", experiments, reflections ] result = procrunner.run(command, print_stdout=False, debug=procrunner_debug) debug("result = %s", screen19.prettyprint_dictionary(result)) if result["exitcode"] == 0: m = re.search( r"[-+]{3,}\n[^\n]*\n[-+|]{3,}\n(.*\n)*[-+]{3,}", result["stdout"].decode("utf-8"), ) if m: info(m.group(0)) else: info( "Could not interpret dials.refine_bravais_settings output, " "please check dials.refine_bravais_settings.log") info("Successfully completed (%.1f sec)", result["runtime"]) else: warning("Failed with exit code %d", result["exitcode"]) sys.exit(1)
def _create_profile_model(self): # type: () -> bool """ Run `dials.create_profile_model` on indexed reflections. The indexed experiment list will be overwritten with a copy that includes the profile model but is otherwise identical. Returns: Boolean value indicating whether it was possible to determine a profile model from the data. """ info("\nCreating profile model...") command = [ "dials.create_profile_model", self.params.dials_index.output.experiments, self.params.dials_index.output.reflections, "output = %s" % self.params.dials_index.output.experiments, ] result = procrunner.run(command, print_stdout=False, debug=procrunner_debug) debug("result = %s", screen19.prettyprint_dictionary(result)) self._sigma_m = None if result["exitcode"] == 0: db = ExperimentList.from_file( self.params.dials_index.output.experiments)[0] self._oscillation = db.imageset.get_scan().get_oscillation()[1] self._sigma_m = db.profile.sigma_m() info( u"%d images, %s° oscillation, σ_m=%.3f°", db.imageset.get_scan().get_num_images(), str(self._oscillation), self._sigma_m, ) info("Successfully completed (%.1f sec)", result["runtime"]) return True warning("Failed with exit code %d", result["exitcode"]) return False
def _check_intensities(self, mosaicity_correction=True): # type: (bool) -> None """ Run xia2.overload and plot a histogram of pixel intensities. If `mosaicity_correction` is true, the pixel intensities are approximately adjusted to take account of a systematic defect in the detector count rate correction. See https://github.com/xia2/screen19/wiki#mosaicity-correction Args: mosaicity_correction (optional): default is `True`. """ info("\nTesting pixel intensities...") command = ["xia2.overload", "nproc=%s" % self.nproc, "indexed.expt"] debug("running %s", command) result = procrunner.run(command, print_stdout=False, debug=procrunner_debug) debug("result = %s", screen19.prettyprint_dictionary(result)) info("Successfully completed (%.1f sec)", result["runtime"]) if result["exitcode"] != 0: warning("Failed with exit code %d", result["exitcode"]) sys.exit(1) with open("overload.json") as fh: overload_data = json.load(fh) info("Pixel intensity distribution:") count_sum = 0 hist = {} if "bins" in overload_data: for b in range(overload_data["bin_count"]): if overload_data["bins"][b] > 0: hist[b] = overload_data["bins"][b] count_sum += b * overload_data["bins"][b] else: hist = { int(k): v for k, v in overload_data["counts"].items() if int(k) > 0 } count_sum = sum([k * v for k, v in hist.items()]) average_to_peak = 1 if mosaicity_correction: # Adjust for the detector count rate correction if self._sigma_m: delta_z = self._oscillation / self._sigma_m / math.sqrt(2) average_to_peak = ( math.sqrt(math.pi) * delta_z * math.erf(delta_z) + math.exp(-(delta_z**2)) - 1) / delta_z**2 info("Average-to-peak intensity ratio: %f", average_to_peak) scale = 100 * overload_data["scale_factor"] / average_to_peak info("Determined scale factor for intensities as %f", scale) debug( "intensity histogram: { %s }", ", ".join(["%d:%d" % (k, hist[k]) for k in sorted(hist)]), ) max_count = max(hist.keys()) hist_max = max_count * scale hist_granularity, hist_format = 1, "%.0f" if hist_max < 50: hist_granularity, hist_format = 2, "%.1f" if hist_max < 15: hist_granularity, hist_format = 10, "%.1f" rescaled_hist = {} for x in hist.keys(): rescaled = round(x * scale * hist_granularity) if rescaled > 0: rescaled_hist[rescaled] = hist[x] + rescaled_hist.get( rescaled, 0) hist = rescaled_hist debug( "rescaled histogram: { %s }", ", ".join([(hist_format + ":%d") % (k / hist_granularity, hist[k]) for k in sorted(hist)]), ) screen19.plot_intensities(hist, 1 / hist_granularity, procrunner_debug=procrunner_debug) linear_response_limit = 100 * self.params.maximum_flux.trusted_range_correction marginal_limit = max(70, linear_response_limit) text = "".join(( "Strongest pixel (%d counts) " % max_count, "reaches %.1f%% " % hist_max, "of the detector count rate limit", )) if hist_max > 100: warning("Warning: %s!", text) else: info(text) if ("overload_limit" in overload_data and max_count >= overload_data["overload_limit"]): warning( "Warning: THE DATA CONTAIN REGULAR OVERLOADS!\n" " The photon incidence rate is outside the specified " "limits of the detector.\n" " The built-in detector count rate correction cannot " "adjust for this.\n" " You should aim for count rates below {:.0%} of the " "detector limit.".format( self.params.maximum_flux.trusted_range_correction)) elif hist_max > marginal_limit: warning( "Warning: The photon incidence rate is well outside the " "linear response region of the detector (<{:.0%}).\n" " The built-in detector count rate correction may not be " "able to adjust for this.".format( self.params.maximum_flux.trusted_range_correction)) elif hist_max > linear_response_limit: info("The photon incidence rate is outside the linear response " "region of the detector (<{:.0%}).\n" " The built-in detector count rate correction may be able " "to adjust for this.".format( self.params.maximum_flux.trusted_range_correction)) if not mosaicity_correction: warning( "Warning: Not enough data for proper profile estimation." " The spot intensities are not corrected for mosaicity.\n" " The true photon incidence rate will be higher than the " "given estimate.") info("Total sum of counts in dataset: %d", count_sum)