Пример #1
0
    def get_parameter_correlation_matrix(self, step, col_select=None):
        """Return the correlation matrix between columns of the Jacobian at
        the specified refinement step. The parameter col_select can be used
        to select subsets of the full number of columns. The column labels
        are also returned as a list of strings"""

        corrmats = self._refinery.get_correlation_matrix_for_step(step)
        if corrmats is None:
            return None, None

        all_labels = self._pred_param.get_param_names()
        from dials.algorithms.refinement.refinement_helpers import string_sel

        if col_select is None:
            col_select = list(range(len(all_labels)))
        sel = string_sel(col_select, all_labels)
        labels = [e for e, s in zip(all_labels, sel) if s]
        num_cols = len(labels)
        if num_cols == 0:
            return None, None

        for k, corrmat in corrmats.items():

            assert corrmat.is_square_matrix()

            idx = flex.bool(sel).iselection()
            sub_corrmat = flex.double(flex.grid(num_cols, num_cols))

            for (i, x) in enumerate(idx):
                for (j, y) in enumerate(idx):
                    sub_corrmat[i, j] = corrmat[x, y]

            corrmats[k] = sub_corrmat

        return (corrmats, labels)
Пример #2
0
def _parameterise_goniometers(options, experiments, analysis):
    gon_params = []
    sv_gon = options.scan_varying and not options.goniometer.force_static
    for igoniometer, goniometer in enumerate(experiments.goniometers()):
        if goniometer is None:
            continue
        # A Goniometer is parameterised with reference to the beam axis.
        # Use the first Beam this Goniometer is associated with.
        exp_ids = experiments.indices(goniometer)
        assoc_models = [(experiments[i].beam, experiments[i].scan)
                        for i in exp_ids]
        beam, scan = assoc_models[0]

        if sv_gon:
            # If a goniometer is scan-varying, then it must always be found
            # alongside the same Scan in any Experiments in which it appears
            if not scan:
                raise DialsRefineConfigError(
                    "A scan-varying goniometer model cannot be created "
                    "because a scan model is missing")
            if not all(s is scan for (g, s) in assoc_models):
                raise DialsRefineConfigError(
                    "A single scan-varying goniometer model cannot be "
                    "refined when associated with more than one scan")
            array_range = scan.get_array_range()
            n_intervals = _set_n_intervals(options.goniometer.smoother,
                                           analysis, scan, exp_ids)
            gon_param = ScanVaryingGoniometerParameterisation(
                goniometer,
                array_range,
                n_intervals,
                beam=beam,
                experiment_ids=exp_ids)
        else:  # force model to be static
            gon_param = GoniometerParameterisation(goniometer,
                                                   beam,
                                                   experiment_ids=exp_ids)

        # Set the model identifier to name the parameterisation
        gon_param.model_identifier = "Goniometer{}".format(igoniometer + 1)

        # get number of fixable units, either parameters or parameter sets in
        # the scan-varying case
        num_gon = getattr(gon_param, "num_sets",
                          getattr(gon_param, "num_total"))()

        fix_list = []
        if options.goniometer.fix_list:
            fix_list.extend(options.goniometer.fix_list)

        if options.goniometer.fix:
            if "all" in options.goniometer.fix:
                gon_param.set_fixed([True] * num_gon)
            if "in_beam_plane" in options.goniometer.fix:
                fix_list.append("Gamma1")
            if "out_beam_plane" in options.goniometer.fix:
                fix_list.append("Gamma2")

        if fix_list:
            names = _filter_parameter_names(gon_param)
            assert len(names) == num_gon
            to_fix = string_sel(fix_list, names, gon_param.model_identifier)
            gon_param.set_fixed(to_fix)

        if gon_param.num_free() > 0:
            gon_params.append(gon_param)

    return gon_params
Пример #3
0
def _parameterise_crystals(options, experiments, analysis):
    xl_ori_params = []
    xl_uc_params = []
    sv_xl_ori = options.scan_varying and not options.crystal.orientation.force_static
    sv_xl_uc = options.scan_varying and not options.crystal.unit_cell.force_static
    for icrystal, crystal in enumerate(experiments.crystals()):
        # This crystal can only ever appear either in scans or in stills
        # (otherwise it requires a different crystal model)
        exp_ids = experiments.indices(crystal)
        assoc_models = [(experiments[i].goniometer, experiments[i].scan)
                        for i in exp_ids]
        goniometer, scan = assoc_models[0]
        if goniometer is None:
            # There should be no associated goniometer and scan models
            if any(g or s for (g, s) in assoc_models):
                raise DialsRefineConfigError(
                    "A crystal model appears in a mixture of scan and still "
                    "experiments, which is not supported")

        if sv_xl_ori or sv_xl_uc:
            if not all((goniometer, scan)):
                raise DialsRefineConfigError(
                    "A scan-varying crystal model cannot be created because "
                    "a scan or goniometer model is missing")
            # If a crystal is scan-varying, then it must always be found alongside
            # the same Scan and Goniometer in any Experiments in which it appears
            if not all(g is goniometer and s is scan
                       for (g, s) in assoc_models):
                raise DialsRefineConfigError(
                    "A single scan-varying crystal model cannot be refined "
                    "when associated with more than one scan or goniometer")
            array_range = scan.get_array_range()

        # orientation parameterisation
        if sv_xl_ori:
            n_intervals = _set_n_intervals(
                options.crystal.orientation.smoother, analysis, scan, exp_ids)
            xl_ori_param = ScanVaryingCrystalOrientationParameterisation(
                crystal, array_range, n_intervals, experiment_ids=exp_ids)
        else:  # force model to be static
            xl_ori_param = CrystalOrientationParameterisation(
                crystal, experiment_ids=exp_ids)

        # Set the model identifier to name the parameterisation
        xl_ori_param.model_identifier = "Crystal{}".format(icrystal + 1)

        # unit cell parameterisation
        if sv_xl_uc:
            n_intervals = _set_n_intervals(options.crystal.unit_cell.smoother,
                                           analysis, scan, exp_ids)
            set_errors = options.set_scan_varying_errors
            xl_uc_param = ScanVaryingCrystalUnitCellParameterisation(
                crystal,
                array_range,
                n_intervals,
                experiment_ids=exp_ids,
                set_state_uncertainties=set_errors,
            )
        else:  # force model to be static
            xl_uc_param = CrystalUnitCellParameterisation(
                crystal, experiment_ids=exp_ids)

        # Set the model identifier to name the parameterisation
        xl_uc_param.model_identifier = "Crystal{}".format(icrystal + 1)

        # get number of fixable units, either parameters or parameter sets in
        # the scan-varying case
        num_ori = getattr(xl_ori_param, "num_sets",
                          getattr(xl_ori_param, "num_total"))()
        num_uc = getattr(xl_uc_param, "num_sets",
                         getattr(xl_uc_param, "num_total"))()

        ori_fix_list = []
        if options.crystal.orientation.fix_list:
            ori_fix_list.extend(options.crystal.orientation.fix_list)

        cell_fix_list = []
        if options.crystal.unit_cell.fix_list:
            cell_fix_list.extend(options.crystal.unit_cell.fix_list)

        if options.crystal.fix:
            if options.crystal.fix == "all":
                xl_ori_param.set_fixed([True] * num_ori)
                xl_uc_param.set_fixed([True] * num_uc)
            elif options.crystal.fix == "cell":
                xl_uc_param.set_fixed([True] * num_uc)
            elif options.crystal.fix == "orientation":
                xl_ori_param.set_fixed([True] * num_ori)
            else:  # can only get here if refinement.phil is broken
                raise RuntimeError("crystal.fix value not recognised")

        if cell_fix_list:
            names = _filter_parameter_names(xl_uc_param)
            assert len(names) == num_uc
            to_fix = string_sel(cell_fix_list, names,
                                xl_uc_param.model_identifier)
            xl_uc_param.set_fixed(to_fix)

        if ori_fix_list:
            names = _filter_parameter_names(xl_ori_param)
            assert len(names) == num_ori
            to_fix = string_sel(ori_fix_list, names,
                                xl_ori_param.model_identifier)
            xl_ori_param.set_fixed(to_fix)

        if xl_ori_param.num_free() > 0:
            xl_ori_params.append(xl_ori_param)
        if xl_uc_param.num_free() > 0:
            xl_uc_params.append(xl_uc_param)

    return xl_ori_params, xl_uc_params
Пример #4
0
def _parameterise_detectors(options, experiments, analysis):
    det_params = []
    sv_det = options.scan_varying and not options.detector.force_static
    for idetector, detector in enumerate(experiments.detectors()):
        # keep associated gonio and scan in case we are scan-varying
        exp_ids = experiments.indices(detector)
        assoc_models = [(experiments[i].goniometer, experiments[i].scan)
                        for i in exp_ids]
        goniometer, scan = assoc_models[0]

        if sv_det:
            if not all((goniometer, scan)):
                raise DialsRefineConfigError(
                    "A scan-varying detector model cannot be created "
                    "because a scan or goniometer model is missing")
            # If a detector is scan-varying, then it must always be found alongside
            # the same Scan and Goniometer in any Experiments in which it appears
            if not all(g is goniometer and s is scan
                       for (g, s) in assoc_models):
                raise DialsRefineConfigError(
                    "A single scan-varying detector model cannot be "
                    "refined when associated with more than one scan or goniometer"
                )

            # Additional checks on whether a scan-varying parameterisation is allowed
            if options.detector.panels == "automatic" and len(detector) > 1:
                raise DialsRefineConfigError(
                    "Scan-varying multiple panel detectors are not "
                    "currently supported")
            if options.detector.panels == "multiple":
                raise DialsRefineConfigError(
                    "Scan-varying multiple panel detectors are not "
                    "currently supported")
            if options.detector.panels == "hierarchical":
                raise DialsRefineConfigError(
                    "Scan-varying hierarchical detectors are not "
                    "currently supported")

            array_range = scan.get_array_range()
            n_intervals = _set_n_intervals(options.detector.smoother, analysis,
                                           scan, exp_ids)
            det_param = ScanVaryingDetectorParameterisationSinglePanel(
                detector, array_range, n_intervals, experiment_ids=exp_ids)
        else:
            # Convert automatic into correct specific option
            if options.detector.panels == "automatic":
                if len(detector) > 1:
                    if hasattr(detector, "hierarchy"):
                        options.detector.panels = "hierarchical"
                    else:
                        options.detector.panels = "multiple"
                else:
                    options.detector.panels = "single"

            # Construct parameterisation based on panels choice
            if options.detector.panels == "single":
                if len(detector) > 1:
                    raise DialsRefineConfigError(
                        "A single panel parameterisation cannot be created "
                        "for a multiple panel detector")
                det_param = DetectorParameterisationSinglePanel(
                    detector, experiment_ids=exp_ids)
            elif options.detector.panels == "multiple":
                # Take first associated beam model
                beam = experiments[exp_ids[0]].beam
                det_param = DetectorParameterisationMultiPanel(
                    detector, beam, experiment_ids=exp_ids)
            elif options.detector.panels == "hierarchical":
                try:  # Use hierarchy in parameterisation if the detector has one
                    detector.hierarchy()
                    det_param = DetectorParameterisationHierarchical(
                        detector,
                        experiment_ids=exp_ids,
                        level=options.detector.hierarchy_level,
                    )
                except AttributeError:
                    raise DialsRefineConfigError(
                        "A hierarchical detector parameterisation cannot be "
                        "created for a detector without a hierarchy")

        # Set the model identifier to name the parameterisation
        det_param.model_identifier = "Detector{}".format(idetector + 1)

        # get number of fixable units, either parameters or parameter sets in
        # the scan-varying case
        num_det = getattr(det_param, "num_sets",
                          getattr(det_param, "num_total"))()

        fix_list = []
        if options.detector.fix_list:
            fix_list.extend(options.detector.fix_list)

        if options.detector.fix:
            if options.detector.fix == "all":
                det_param.set_fixed([True] * num_det)
            elif options.detector.fix == "position":
                fix_list.extend(["Dist", "Shift1", "Shift2"])
            elif options.detector.fix == "orientation":
                fix_list.extend(["Tau"])
            elif options.detector.fix == "distance":
                fix_list.extend(["Dist", "Tau2", "Tau3"])
            else:  # can only get here if refinement.phil is broken
                raise RuntimeError("detector.fix value not recognised")

        if fix_list:
            names = _filter_parameter_names(det_param)
            assert len(names) == num_det
            to_fix = string_sel(fix_list, names, det_param.model_identifier)
            det_param.set_fixed(to_fix)

        if det_param.num_free() > 0:
            det_params.append(det_param)

    return det_params
Пример #5
0
def _parameterise_beams(options, experiments, analysis):
    beam_params = []
    sv_beam = options.scan_varying and not options.beam.force_static
    for ibeam, beam in enumerate(experiments.beams()):
        # The Beam is parameterised with reference to a goniometer axis (or None).
        # Use the first (if any) Goniometers this Beam is associated with.
        exp_ids = experiments.indices(beam)
        assoc_models = [(experiments[i].goniometer, experiments[i].scan)
                        for i in exp_ids]
        goniometer, scan = assoc_models[0]

        if sv_beam:
            if not all((goniometer, scan)):
                raise DialsRefineConfigError(
                    "A scan-varying beam model cannot be created because "
                    "a scan or goniometer model is missing")
            # If a beam is scan-varying, then it must always be found alongside
            # the same Scan and Goniometer in any Experiments in which it appears
            if not all(g is goniometer and s is scan
                       for (g, s) in assoc_models):
                raise DialsRefineConfigError(
                    "A single scan-varying beam model cannot be refined "
                    "when associated with more than one scan or goniometer")
            array_range = scan.get_array_range()
            n_intervals = _set_n_intervals(options.beam.smoother, analysis,
                                           scan, exp_ids)
            beam_param = ScanVaryingBeamParameterisation(
                beam,
                array_range,
                n_intervals,
                goniometer=goniometer,
                experiment_ids=exp_ids,
            )
        else:
            # Parameterise scan static beam, passing the goniometer
            beam_param = BeamParameterisation(beam,
                                              goniometer,
                                              experiment_ids=exp_ids)

        # Set the model identifier to name the parameterisation
        beam_param.model_identifier = "Beam{}".format(ibeam + 1)

        # get number of fixable units, either parameters or parameter sets in
        # the scan-varying case
        num_beam = getattr(beam_param, "num_sets",
                           getattr(beam_param, "num_total"))()

        fix_list = []
        if options.beam.fix_list:
            fix_list.extend(options.beam.fix_list)

        if options.beam.fix:
            if "all" in options.beam.fix:
                beam_param.set_fixed([True] * num_beam)
            if "in_spindle_plane" in options.beam.fix:
                fix_list.append("Mu1")
            if "out_spindle_plane" in options.beam.fix:
                fix_list.append("Mu2")
            if "wavelength" in options.beam.fix:
                fix_list.append("nu")

        if fix_list:
            names = _filter_parameter_names(beam_param)
            assert len(names) == num_beam
            to_fix = string_sel(fix_list, names, beam_param.model_identifier)
            beam_param.set_fixed(to_fix)

        if beam_param.num_free() > 0:
            beam_params.append(beam_param)

    return beam_params