def test_compute_delta_cchalf(dials_regression):
    """Test compute delta cchalf on an integrated mtz."""

    filename = os.path.join(
        dials_regression, "delta_cchalf_test_data", "test.XDS_ASCII.mtz"
    )
    params = phil_scope.extract()
    params.nbins = 1

    script = CCHalfFromMTZ(params, filename)
    script.run()

    cchalf_i = script.results_summary["per_dataset_delta_cc_half_values"][
        "delta_cc_half_values"
    ]

    assert abs(100 * script.results_summary["mean_cc_half"] - 94.582) < 1e-3
    assert (
        abs(100 * script.results_summary["mean_cc_half"] - 100 * cchalf_i[1] - 79.587)
        < 1e-3
    )
    assert (
        abs(100 * script.results_summary["mean_cc_half"] - 100 * cchalf_i[0] - 94.238)
        < 1e-3
    )
示例#2
0
def test_exclusion_in_CCHalfFromDials():
    """Test the exclusion of image groups."""
    # Same input as above, but mock DeltaCCHalf algorithm to just test
    # interpretation of results and setting of excluded regions. With the
    # input, test that outlier edges are correctly removed.

    params = phil_scope.extract()
    params.mode = "image_group"
    expts = generated_exp(n=2)
    refls = generated_refl()

    def mock_algorithm(*_):
        """Mock a result from DeltaCCHalf"""
        algo = mock.Mock()
        algo.run.return_value = None
        algo.results_summary = {
            "per_dataset_delta_cc_half_values": {
                "delta_cc_half_values": [-5.0, -2.0, 4.0, -5.0],
                "datasets": [0, 1, 2, 3],
            },
            "dataset_removal": {
                "cutoff_value": -1.0
            },
        }
        return algo

    with mock.patch(
            "dials.algorithms.statistics.cc_half_algorithm.DeltaCCHalf",
            side_effect=mock_algorithm,
    ):
        script = CCHalfFromDials(params, expts, refls)
        script.run()

        assert script.datasetid_to_groups == {
            "0": [],
            "1": [2]
        }  # all but 3 removed
        expts = script.experiments

        assert list(expts.identifiers()) == ["1"]
        assert expts[0].scan.get_valid_image_ranges(
            expts.identifiers()[0]) == [(1, 10)]
        assert script.results_summary["dataset_removal"][
            "experiment_ids_fully_removed"] == [0]
        assert script.results_summary["dataset_removal"][
            "experiments_fully_removed"] == ["0"]
示例#3
0
def test_setup_of_CCHalfFromDials():
    """Test the correct setup in image group mode.

    Test for the case of outliers at the end of images, and image ranges not
    equaling a multiple of the grouping."""

    params = phil_scope.extract()
    params.mode = "image_group"
    expts = generated_exp(n=2)
    refls = generated_refl()

    # Expected behaviour is that the outliers will not be included in the
    # image range, and that all groups will have at least 10 images in.
    script = CCHalfFromDials(params, expts, refls)
    assert script.group_to_datasetid_and_range == {
        0: ("0", (5, 14)),
        1: ("0", (15, 25)),
        2: ("1", (1, 10)),
        3: ("1", (11, 23)),
    }
    assert script.datasetid_to_groups == {"0": [0, 1], "1": [2, 3]}
示例#4
0
    def run(self):
        """Run cycles of scaling and filtering."""
        with ScalingHTMLContextManager(self):
            start_time = time.time()
            results = AnalysisResults()

            for counter in range(
                    1, self.params.filtering.deltacchalf.max_cycles + 1):
                self.run_scaling_cycle()

                if counter == 1:
                    results.initial_expids_and_image_ranges = [
                        (exp.identifier,
                         exp.scan.get_image_range()) if exp.scan else None
                        for exp in self.experiments
                    ]

                delta_cc_params = deltacc_phil_scope.extract()
                delta_cc_params.mode = self.params.filtering.deltacchalf.mode
                delta_cc_params.group_size = (
                    self.params.filtering.deltacchalf.group_size)
                delta_cc_params.stdcutoff = self.params.filtering.deltacchalf.stdcutoff
                logger.info("\nPerforming a round of filtering.\n")

                # need to reduce to single table.
                joined_reflections = flex.reflection_table()
                for table in self.reflections:
                    joined_reflections.extend(table)

                script = deltaccscript(delta_cc_params, self.experiments,
                                       joined_reflections)
                script.run()

                valid_image_ranges = get_valid_image_ranges(self.experiments)
                results.expids_and_image_ranges = [
                    (exp.identifier,
                     valid_image_ranges[i]) if exp.scan else None
                    for i, exp in enumerate(self.experiments)
                ]

                self.experiments = script.experiments
                self.params.dataset_selection.use_datasets = None
                self.params.dataset_selection.exclude_datasets = None

                results = log_cycle_results(results, self, script)
                logger.info(
                    "Cycle %s of filtering, n_reflections removed this cycle: %s",
                    counter,
                    results.get_last_cycle_results()["n_removed"],
                )

                # Test termination conditions
                latest_results = results.get_last_cycle_results()
                if latest_results["n_removed"] == 0:
                    logger.info(
                        "Finishing scaling and filtering as no data removed in this cycle."
                    )
                    if self.params.scaling_options.full_matrix:
                        self.reflections = parse_multiple_datasets(
                            [script.filtered_reflection_table])
                        results = self._run_final_scale_cycle(results)
                    else:
                        self.reflections = [script.filtered_reflection_table]
                    results.finish(termination_reason="no_more_removed")
                    break

                # Need to split reflections for further processing.
                self.reflections = parse_multiple_datasets(
                    [script.filtered_reflection_table])

                if (latest_results["cumul_percent_removed"] >
                        self.params.filtering.deltacchalf.max_percent_removed):
                    logger.info(
                        "Finishing scale and filtering as have now removed more than the limit."
                    )
                    results = self._run_final_scale_cycle(results)
                    results.finish(termination_reason="max_percent_removed")
                    break

                if self.params.filtering.deltacchalf.min_completeness:
                    if (latest_results["merging_stats"]["completeness"] <
                            self.params.filtering.deltacchalf.min_completeness
                        ):
                        logger.info(
                            "Finishing scaling and filtering as completeness now below cutoff."
                        )
                        results = self._run_final_scale_cycle(results)
                        results.finish(
                            termination_reason="below_completeness_limit")
                        break

                if counter == self.params.filtering.deltacchalf.max_cycles:
                    logger.info("Finishing as reached max number of cycles.")
                    results = self._run_final_scale_cycle(results)
                    results.finish(termination_reason="max_cycles")
                    break

                # If not finished then need to create new scaler to try again
                self._create_model_and_scaler()
            self.filtering_results = results
            # Print summary of results
            logger.info(results)
            with open(self.params.filtering.output.scale_and_filter_results,
                      "w") as f:
                json.dump(self.filtering_results.to_dict(), f, indent=2)
            # All done!
            logger.info("\nTotal time taken: %.4fs ", time.time() - start_time)
            logger.info("%s%s%s", "\n", "=" * 80, "\n")