def create_response(opt, other_opt):
    """ Entry point for creating pandas-based response matrices.

    The response matrices can be either created by response_madx or TwissResponse.

    Keyword Args:
        Required
        model_dir (str): Path to the model directory.
                         **Flags**: ['-m', '--model_dir']
        outfile_path (str): Name of fullresponse file.
                            **Flags**: ['-o', '--outfile']
        Optional
        creator (str): Create either with madx or analytically from twiss file.
                       **Flags**: --creator
                       **Choices**: ('madx', 'twiss')
                       **Default**: ``madx``
        debug: Print debug information.
               **Flags**: --debug
               **Action**: ``store_true``
        delta_k (float): Delta K1L to be applied to quads for sensitivity matrix (madx-only).
                         **Flags**: ['-k', '--deltak']
                         **Default**: ``2e-05``
        optics_params (str): List of parameters to correct upon (e.g. BBX BBY; twiss-only).
                             **Flags**: --optics_params
        variable_categories: List of the variables classes to use.
                             **Flags**: --variables
                             **Default**: ``['MQM', 'MQT', 'MQTL', 'MQY']``
    """
    with logging_tools.DebugMode(active=opt.debug,
                                 log_file=os.path.join(opt.model_dir, "generate_fullresponse.log")):
        LOG.info("Creating response.")
        accel_cls = manager.get_accel_class(other_opt)
        accel_inst = accel_cls(model_dir=opt.model_dir)
        if opt.optics_file is not None:
            accel_inst.optics_file = opt.optics_file

        if opt.creator == "madx":
            fullresponse = response_madx.generate_fullresponse(
                accel_inst, opt.variable_categories, delta_k=opt.delta_k
            )

        elif opt.creator == "twiss":
            fullresponse = response_twiss.create_response(
                accel_inst, opt.variable_categories, opt.optics_params
            )

        LOG.debug("Saving Response into file '{:s}'".format(opt.outfile_path))
        with open(opt.outfile_path, 'wb') as dump_file:
            pickle.Pickler(dump_file, -1).dump(fullresponse)
Beispiel #2
0
def create_response(opt, other_opt):
    """ Entry point for creating pandas-based response matrices.

    The response matrices can be either created by response_madx or TwissResponse.

    Keyword Args:
        Required
        model_dir (str): Path to the model directory.
                         **Flags**: ['-m', '--model_dir']
        outfile_path (str): Name of fullresponse file.
                            **Flags**: ['-o', '--outfile']
        Optional
        creator (str): Create either with madx or analytically from twiss file.
                       **Flags**: --creator
                       **Choices**: ('madx', 'twiss')
                       **Default**: ``madx``
        debug: Print debug information.
               **Flags**: --debug
               **Action**: ``store_true``
        delta_k (float): Delta K1L to be applied to quads for sensitivity matrix (madx-only).
                         **Flags**: ['-k', '--deltak']
                         **Default**: ``2e-05``
        optics_params (str): List of parameters to correct upon (e.g. BBX BBY; twiss-only).
                             **Flags**: --optics_params
        variable_categories: List of the variables classes to use.
                             **Flags**: --variables
                             **Default**: ``['MQM', 'MQT', 'MQTL', 'MQY']``
    """
    with logging_tools.DebugMode(active=opt.debug,
                                 log_file=os.path.join(
                                     opt.model_dir,
                                     "generate_fullresponse.log")):
        LOG.info("Creating response.")
        accel_cls = manager.get_accel_class(other_opt)
        accel_inst = accel_cls(model_dir=opt.model_dir)
        if opt.optics_file is not None:
            accel_inst.optics_file = opt.optics_file

        if opt.creator == "madx":
            fullresponse = response_madx.generate_fullresponse(
                accel_inst, opt.variable_categories, delta_k=opt.delta_k)

        elif opt.creator == "twiss":
            fullresponse = response_twiss.create_response(
                accel_inst, opt.variable_categories, opt.optics_params)

        LOG.debug("Saving Response into file '{:s}'".format(opt.outfile_path))
        with open(opt.outfile_path, 'wb') as dump_file:
            pickle.Pickler(dump_file, -1).dump(fullresponse)
def global_correction(opt, accel_opt):
    """ Do the global correction. Iteratively.

    Keyword Args:
        Required
        meas_dir: Path to the directory containing the measurement files.
                       **Flags**: --meas_dir
        model_dir: Path to the dir containing the model (twiss.dat or twiss_elements.dat) to use.
                             **Flags**: --model_dir
        Optional
        beta_file_name: Prefix of the beta file to use. E.g.: getkmodbeta
                        **Flags**: --beta_file_name
                        **Default**: ``getbeta``
        debug: Print debug information.
               **Flags**: --debug
               **Action**: ``store_true``
        eps (float): (Not implemented yet) Convergence criterion.
                     If :math:`<|\Delta(PARAM \cdot WEIGHT)|> < \epsilon`, stop iteration.
                     **Flags**: --eps
                     **Default**: ``None``
        errorcut (float): Reject BPMs whose error bar is higher than the corresponding input.
                          Input in order of optics_params.
                          **Flags**: --error_cut
        fullresponse_path: Path to the fullresponse binary file.
                           If not given, calculates the response analytically.
                           **Flags**: --fullresponse
        max_iter (int): Maximum number of correction re-iterations to perform.
                        A value of `0` means the correction is calculated once
                        (like in the old days).
                        **Flags**: --max_iter
                        **Default**: ``3``
        method (str): Optimization method to use. (Not implemented yet)
                      **Flags**: --method
                      **Choices**: ['pinv']
                      **Default**: ``pinv``
        modelcut (float): Reject BPMs whose deviation to the model is higher than the
                          correspoding input. Input in order of optics_params.
                          **Flags**: --model_cut
        optics_file: Path to the optics file to use, usually modifiers.madx.
                     If not present will default to model_path/modifiers.madx
                     **Flags**: --optics_file
        optics_params (str): List of parameters to correct upon (e.g. BBX BBY)
                             **Flags**: --optics_params
                             **Default**: ``['MUX', 'MUY', 'BBX', 'BBY', 'NDX', 'Q']``
        output_path: Path to the directory where to write the output files,
                     will default to the --meas input path.
                     **Flags**: --output_dir
                     **Default**: ``None``
        svd_cut (float): Cutoff for small singular values of the pseudo inverse. (Method: 'pinv')
                         Singular values smaller than
                         :math:`rcond \cdot largest_singular_value` are set to zero
                         **Flags**: --svd_cut
                         **Default**: ``0.01``
        use_errorbars: If True, it will take into account the measured errorbars in the correction.
                       **Flags**: --use_errorbars
                       **Action**: ``store_true``
        variable_categories: List of names of the variables classes to use.
                             **Flags**: --variables
                             **Default**: ``['MQM', 'MQT', 'MQTL', 'MQY']``
        virt_flag: If true, it will use virtual correctors.
                   **Flags**: --virt_flag
                   **Action**: ``store_true``
        weights (float): Weights to apply to each measured quantity. Input in order of optics_params.
                         **Flags**: --weights
    """

    LOG.info("Starting Iterative Global Correction.")
    with logging_tools.DebugMode(active=opt.debug,
                                 log_file=os.path.join(opt.model_dir, "iterative_correction.log")):
        not_implemented_params = [k for k in opt.optics_params
                                  if k not in _get_measurement_filters()]
        if any(not_implemented_params):
            raise NotImplementedError("Correct iterative is not equipped for parameters:"
                                      "'{:s}'".format(not_implemented_params))

        # ######### Preparations ######### #

        # check on opt
        opt = _check_opt(opt)
        meth_opt = _get_method_opt(opt)

        # get accelerator class
        accel_cls = manager.get_accel_class(accel_opt)
        accel_inst = accel_cls(model_dir=opt.model_dir)
        if opt.optics_file is not None:
            accel_inst.optics_file = opt.optics_file

        # convert numbers to dictionaries
        w_dict = dict(zip(opt.optics_params, opt.weights))
        mcut_dict = dict(zip(opt.optics_params, opt.modelcut))
        ecut_dict = dict(zip(opt.optics_params, opt.errorcut))

        # read data from files
        vars_list = _get_varlist(accel_cls, opt.variable_categories, opt.virt_flag)
        optics_params, meas_dict = _get_measurment_data(
            opt.optics_params,
            opt.meas_dir, opt.beta_file_name,
            w_dict,
        )
        mcut_dict = _automate_modelcut(mcut_dict, meas_dict, opt.variable_categories)

        if opt.fullresponse_path is not None:
            resp_dict = _load_fullresponse(opt.fullresponse_path, vars_list)
        else:
            resp_dict = response_twiss.create_response(
                accel_inst, opt.variable_categories, optics_params
            )

        # the model in accel_inst is modified later, so save nominal model here to variables
        nominal_model = _maybe_add_coupling_to_model(accel_inst.get_model_tfs(), optics_params)

        # apply filters to data
        meas_dict = _filter_measurement(
            optics_params, meas_dict, nominal_model,
            opt.use_errorbars, w_dict, ecut_dict, mcut_dict
        )
        meas_dict = _append_model_to_measurement(nominal_model, meas_dict, optics_params)
        resp_dict = _filter_response_index(resp_dict, meas_dict, optics_params)
        resp_matrix = _join_responses(resp_dict, optics_params, vars_list)

        # _dump(os.path.join(opt.output_path, "measurement_dict.bin"), meas_dict)
        delta = tfs.TfsDataFrame(0, index=vars_list, columns=["DELTA"])

        # ######### Iteration Phase ######### #

        for iteration in range(opt.max_iter + 1):
            LOG.info("Correction Iteration {:d} of {:d}.".format(iteration, opt.max_iter))

            # ######### Update Model and Response ######### #
            if iteration > 0:
                LOG.debug("Updating model via MADX.")
                corr_model_path = os.path.join(opt.output_path, "twiss_" + str(iteration) + ".dat")

                _create_corrected_model(corr_model_path, opt.change_params_path,
                                        accel_inst, opt.debug)

                corr_model_elements = tfs.read_tfs(corr_model_path, index="NAME")
                corr_model_elements = _maybe_add_coupling_to_model(
                    corr_model_elements, optics_params
                )
                corr_model = corr_model_elements.loc[tfs.get_bpms(corr_model_elements), :]

                meas_dict = _append_model_to_measurement(corr_model, meas_dict, optics_params)
                if opt.update_response:
                    LOG.debug("Updating response.")
                    # please look away for the next two lines.
                    accel_inst._model = corr_model
                    accel_inst._elements = corr_model_elements
                    resp_dict = response_twiss.create_response(
                        accel_inst, opt.variable_categories, optics_params
                    )
                    resp_dict = _filter_response_index(resp_dict, meas_dict, optics_params)
                    resp_matrix = _join_responses(resp_dict, optics_params, vars_list)

            # ######### Actual optimization ######### #
            delta += _calculate_delta(
                resp_matrix, meas_dict, optics_params, vars_list, opt.method, meth_opt)

            writeparams(opt.change_params_path, delta)
            writeparams(opt.change_params_correct_path, -delta)
            LOG.debug("Cumulative delta: {:.5e}".format(
                np.sum(np.abs(delta.loc[:, "DELTA"].values))))

        write_knob(opt.knob_path, delta)
    LOG.info("Finished Iterative Global Correction.")