Example #1
0
def _do_clean(main_input, clean_input, bpm_datas, file_date, model_tfs):
    usvs, all_bad_bpms, bpm_ress = {}, {}, {}
    clean_writer = output_handler.CleanedAsciiWritter(main_input, file_date)
    for plane in ("x", "y"):
        bpm_data = bpm_datas[plane]
        bpm_data, bpms_not_in_model = _get_only_model_bpms(bpm_data, model_tfs)
        if bpm_data.empty:
            raise AssertionError("Check BPMs names! None of the BPMs was found in the model!")    
    
        bad_bpms = []

        with timeit(lambda spanned: LOGGER.debug("Time for filtering: %s", spanned)):
            bpm_data, bad_bpms_clean = clean.clean(bpm_data, clean_input, file_date,)
        with timeit(lambda spanned: LOGGER.debug("Time for SVD clean: %s", spanned)):
            bpm_data, bpm_res, bad_bpms_svd, usv = clean.svd_clean(bpm_data, clean_input,)
        bpm_ress[plane] = bpm_res
        bad_bpms.extend(bpms_not_in_model)
        bad_bpms.extend(bad_bpms_clean)
        bad_bpms.extend(bad_bpms_svd)
        all_bad_bpms[plane] = bad_bpms
        setattr(clean_writer, "samples_matrix_" + plane, bpm_data)

        if plane == "x":
            dpp = _calc_dp_over_p(main_input, bpm_data)
        bpm_datas[plane] = bpm_data
        usvs[plane] = usv

    if clean_input.write_clean:
        clean_writer.dpp = dpp
        clean_writer.write()
    return usvs, all_bad_bpms, bpm_ress, dpp
Example #2
0
def _do_harpy(main_input, harpy_input, bpm_datas, usvs, model_tfs, bpm_ress,
              dpp, all_bad_bpms):
    lin_frames = {}
    for plane in ("x", "y"):
        bpm_data, usv = bpm_datas[plane], usvs[plane]
        lin_frames[plane] = pd.DataFrame(
            index=bpm_data.index,
            data=OrderedDict([
                ("NAME", bpm_data.index),
                ("S", model_tfs.set_index("NAME").loc[bpm_data.index, "S"])
            ]))
        with timeit(lambda spanned: LOGGER.debug("Time for orbit_analysis: %s",
                                                 spanned)):
            lin_frames[plane] = _get_orbit_data(lin_frames[plane], bpm_data,
                                                bpm_ress[plane])
        bpm_datas[plane], usvs[plane] = _prepare_data_for_harpy(bpm_data, usv)

    with timeit(lambda spanned: LOGGER.debug("Time for harmonic_analysis: %s",
                                             spanned)):
        harpy_iterator = harpy.harpy(
            harpy_input,
            bpm_datas["x"],
            usvs["x"],
            bpm_datas["y"],
            usvs["y"],
        )
    dpp_amp = None
    lin = {}
    for plane in ("x", "y"):
        harpy_results, spectr, bad_bpms_summaries = harpy_iterator.next()
        lin_frame = lin_frames[plane]
        lin_frame = lin_frame.loc[harpy_results.index].join(harpy_results)
        if harpy_input.is_free_kick:
            bpm_data = bpm_datas[plane]
            lin_frame = _kick_phase_correction(bpm_data, lin_frame, plane)
        if harpy_input.tunez > 0.0 and plane == "x":
            dpp_amp, _, _ = chroma.get_dpoverp_amp(model_tfs, lin_frame,
                                                   bpm_datas["x"])
        lin_frame = _sync_phase(lin_frame, plane)
        lin_frame = _rescale_amps_to_main_line(lin_frame, plane)
        lin_frame = _add_resonances_noise(lin_frame, plane)
        lin_frame = lin_frame.sort_values('S', axis=0, ascending=True)
        headers = _compute_headers(lin_frame, plane, dpp, dpp_amp)
        output_handler.write_harpy_output(main_input, lin_frame, headers,
                                          spectr, plane)
        all_bad_bpms[plane].extend(bad_bpms_summaries)
        lin[plane] = tfs.TfsDataFrame(lin_frame, headers=headers)
    return all_bad_bpms, lin
    def _calc_beta_response(self):
        """ Response Matrix for delta beta.

        Eq. A35 -> Eq. B45 in [#FranchiAnalyticformulasrapid2017]_
        """
        LOG.debug("Calculate Beta Response Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}s".format(t))):
            tw = self._twiss
            adv = self._phase_advances
            el_out = self._elements_out
            k1_el = self._elements_in["K1L"]
            dbeta = dict.fromkeys(["X", "Y"])

            for plane in ["X", "Y"]:
                col_beta = "BET" + plane
                q = tw.Q1 if plane == "X" else tw.Q2
                coeff_sign = -1 if plane == "X" else 1

                pi2tau = 2 * np.pi * tau(adv[plane].loc[k1_el, el_out], q)

                dbeta[plane] = tfs.TfsDataFrame(
                    tw.loc[el_out, col_beta].values[None, :] *
                    tw.loc[k1_el, col_beta].values[:, None] *
                    np.cos(2 * pi2tau.values) * (coeff_sign /
                                                 (2 * np.sin(2 * np.pi * q))),
                    index=k1_el,
                    columns=el_out).transpose()

        return dict_mul(self._direction, dbeta)
Example #4
0
def run_all(main_input, clean_input, harpy_input, optics_input, to_log):
    with timeit(
            lambda spanned: LOGGER.info("Total time for file: %s", spanned)):
        if (not main_input.write_raw and clean_input is None
                and harpy_input is None):
            LOGGER.error("No file has been choosen to be writen!")
            return
        _setup_file_log_handler(main_input)
        LOGGER.debug(to_log)
        tbt_files = [
            turn_by_turn_reader.read_tbt_file(input_file.strip())
            for input_file in main_input.file.strip("\"").split(",")
        ]

        lins = []
        for tbt_file in tbt_files:
            lins.extend([
                run_all_for_file(bunchfile, this_main_input, clean_input,
                                 harpy_input) for this_main_input, bunchfile in
                output_handler.handle_multibunch(main_input, tbt_file)
            ])

        if optics_input is not None:
            inputs = measure_optics.InputFiles(lins)
            iotools.create_dirs(optics_input.outputdir)
            calibrations = measure_optics._copy_calibration_files(
                optics_input.outputdir, optics_input.calibrationdir)
            inputs.calibrate(calibrations)
            measure_optics.measure_optics(inputs, optics_input)
Example #5
0
def run_all(main_input, clean_input, harpy_input, optics_input, to_log):
    with timeit(lambda spanned: LOGGER.info("Total time for file: %s", spanned)):
        if (not main_input.write_raw and
                clean_input is None and harpy_input is None):
            LOGGER.error("No file has been choosen to be writen!")
            return
        _setup_file_log_handler(main_input)
        LOGGER.debug(to_log)
        tbt_files = [turn_by_turn_reader.read_tbt_file(input_file.strip())
                     for input_file in main_input.file.strip("\"").split(",")]
        
        lins = []
        for tbt_file in tbt_files:
            lins.extend(
                [run_all_for_file(bunchfile, this_main_input, clean_input, harpy_input)
                 for this_main_input, bunchfile in
                 output_handler.handle_multibunch(main_input, tbt_file)]
            )

        if optics_input is not None:
            inputs = measure_optics.InputFiles(lins)
            iotools.create_dirs(optics_input.outputdir)
            calibrations = measure_optics._copy_calibration_files(optics_input.outputdir, optics_input.calibrationdir)
            inputs.calibrate(calibrations)
            measure_optics.measure_optics(inputs, optics_input)
    def _calc_tune_response(self):
        """ Response vectors for Tune.

        Eq. 7 in [#TomasReviewlinearoptics2017]_
        """
        LOG.debug("Calculate Tune Response Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}s".format(t))):
            tw = self._twiss
            k1_el = self._elements_in["K1L"]

            if len(k1_el) > 0:
                dtune = dict.fromkeys(["X", "Y"])

                dtune["X"] = 1 / (4 * np.pi) * tw.loc[k1_el,
                                                      ["BETX"]].transpose()
                dtune["X"].index = ["DQX"]

                dtune["Y"] = -1 / (4 * np.pi) * tw.loc[k1_el,
                                                       ["BETY"]].transpose()
                dtune["Y"].index = ["DQY"]
            else:
                LOG.debug(
                    "  No 'K1L' variables found. Tune Response will be empty.")
                dtune = {
                    "X": tfs.TfsDataFrame(None, index=["DQX"]),
                    "Y": tfs.TfsDataFrame(None, index=["DQY"])
                }

        return dict_mul(self._direction, dtune)
    def _calc_chromatic_term(self):
        """ Calculates the chromatic term which is common to all chromatic equations """
        LOG.debug("Calculating Chromatic Term.")
        self._check_k_columns(["K1L", "K2L", "K2SL"])
        res = self._results_df
        tw = self.twiss_df

        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            mask = (tw['K1L'] != 0) | (tw['K2L'] != 0) | (tw['K2SL'] != 0)
            if "DX" in tw and "DY" in tw:
                LOG.debug(
                    "Dispersion values found in model. Used for chromatic calculations"
                )
                sum_term = tw.loc[mask, 'K1L'] - \
                           (tw.loc[mask, 'K2L'] * tw.loc[mask, 'DX']) + \
                           (tw.loc[mask, 'K2SL'] * tw.loc[mask, 'DY'])
            else:
                LOG.info(
                    "Dispersion values NOT found in model. Using analytic values."
                )
                if "DX" not in res or "DY" not in res:
                    self.calc_linear_dispersion()
                sum_term = tw.loc[mask, 'K1L'] - \
                           (tw.loc[mask, 'K2L'] * res.loc[mask, 'DX']) + \
                           (tw.loc[mask, 'K2SL'] * res.loc[mask, 'DY'])

            res['CHROMX'] = sum_term * tw.loc[mask, 'BETX']
            res['CHROMY'] = sum_term * tw.loc[mask, 'BETY']

        LOG.debug("Chromatic Term Calculated.")
Example #8
0
    def calc_chromatic_beating(self):
        """ Calculate the Chromatic Beating

        Eq. 36 in [#FranchiAnalyticformulasrapid2017]_
        """
        tw = self.twiss_df
        res = self._results_df
        phs_adv = self.get_phase_adv()

        if 'CHROMX' not in res:
            self._calc_chromatic_term()

        LOG.debug("Calculating Chromatic Beating")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            chromx = res['CHROMX'].dropna()
            chromy = res['CHROMY'].dropna()
            res['DBEATX'] = self._chromatic_beating(
                chromx, tau(phs_adv['X'].loc[chromx.index, :], tw.Q1),
                tw.Q1).transpose() - 1
            res['DBEATY'] = -self._chromatic_beating(
                chromy, tau(phs_adv['Y'].loc[chromy.index, :], tw.Q2),
                tw.Q2).transpose() - 1

        LOG.debug("  Pk2Pk chromatic beating DBEATX: {:g}".format(
            res['DBEATX'].max() - res['DBEATX'].min()))
        LOG.debug("  Pk2Pk chromatic beating DBEATY: {:g}".format(
            res['DBEATY'].max() - res['DBEATY'].min()))
        self._log_added('DBEATX', 'DBEATY')
Example #9
0
    def __init__(self, accel_inst, variable_categories, varmap_or_path, at_elements='bpms'):

        LOG.debug("Initializing TwissResponse.")
        with timeit(lambda t: LOG.debug("  Time initializing TwissResponse: {:f}s".format(t))):
            # Get input
            self._twiss = self._get_model_twiss(accel_inst)
            self._variables = accel_inst.get_variables(classes=variable_categories)
            self._var_to_el = self._get_variable_mapping(varmap_or_path)
            self._elements_in = self._get_input_elements()
            self._elements_out = self._get_output_elements(at_elements)
            self._direction = self._get_direction(accel_inst)

            # calculate all phase advances
            self._phase_advances = get_phase_advances(self._twiss)

            # All responses are calcluated as needed, see getters below!
            # slots for response matrices
            self._beta = None
            self._dispersion = None
            self._phase = None
            self._phase_adv = None
            self._tune = None
            self._coupling = None
            self._beta_beat = None
            self._norm_dispersion = None

            # slots for mapped response matrices
            self._coupling_mapped = None
            self._beta_mapped = None
            self._dispersion_mapped = None
            self._phase_mapped = None
            self._phase_adv_mapped = None
            self._tune_mapped = None
            self._beta_beat_mapped = None
            self._norm_dispersion_mapped = None
    def _calc_coupling_response(self):
        """ Response Matrix for coupling.

        Eq. 10 in [#FranchiAnalyticformulasrapid2017]_
        """
        LOG.debug("Calculate Coupling Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}s".format(t))):
            tw = self._twiss
            adv = self._phase_advances
            el_out = self._elements_out
            k1s_el = self._elements_in["K1SL"]
            dcoupl = dict.fromkeys(["1001", "1010"])

            i2pi = 2j * np.pi
            phx = dphi(adv['X'].loc[k1s_el, el_out], tw.Q1).values
            phy = dphi(adv['Y'].loc[k1s_el, el_out], tw.Q2).values
            bet_term = np.sqrt(tw.loc[k1s_el, "BETX"].values *
                               tw.loc[k1s_el, "BETY"].values)

            for plane in ["1001", "1010"]:
                phs_sign = -1 if plane == "1001" else 1
                dcoupl[plane] = tfs.TfsDataFrame(
                    bet_term[:, None] * np.exp(i2pi * (phx + phs_sign * phy)) /
                    (4 * (1 - np.exp(i2pi * (tw.Q1 + phs_sign * tw.Q2)))),
                    index=k1s_el,
                    columns=el_out).transpose()
        return dict_mul(self._direction, dcoupl)
Example #11
0
def _do_harpy(main_input, harpy_input, bpm_datas, usvs, model_tfs, bpm_ress, dpp, all_bad_bpms):
    lin_frames = {}
    for plane in ("x", "y"):
        bpm_data, usv = bpm_datas[plane], usvs[plane]
        lin_frames[plane] = pd.DataFrame(
            index=bpm_data.index,
            data=OrderedDict([
                ("NAME", bpm_data.index),
                ("S", model_tfs.set_index("NAME").loc[bpm_data.index, "S"])
            ])
        )
        with timeit(lambda spanned: LOGGER.debug("Time for orbit_analysis: %s", spanned)):
            lin_frames[plane] = _get_orbit_data(lin_frames[plane], bpm_data, bpm_ress[plane])
        bpm_datas[plane], usvs[plane] = _prepare_data_for_harpy(bpm_data, usv)

    with timeit(lambda spanned: LOGGER.debug("Time for harmonic_analysis: %s", spanned)):
        harpy_iterator = harpy.harpy(
            harpy_input,
            bpm_datas["x"], usvs["x"],
            bpm_datas["y"], usvs["y"],
        )
    dpp_amp = None
    lin = {}
    for plane in ("x", "y"):
        harpy_results, spectr, bad_bpms_summaries = harpy_iterator.next()
        lin_frame = lin_frames[plane]
        lin_frame = lin_frame.loc[harpy_results.index].join(harpy_results)
        if harpy_input.is_free_kick:
            bpm_data = bpm_datas[plane]
            lin_frame = _kick_phase_correction(bpm_data, lin_frame, plane)
        if harpy_input.tunez > 0.0 and plane == "x":
            dpp_amp, _, _ = chroma.get_dpoverp_amp(model_tfs, lin_frame, bpm_datas["x"])
        lin_frame = _sync_phase(lin_frame, plane)
        lin_frame = _rescale_amps_to_main_line(lin_frame, plane)
        lin_frame = _add_resonances_noise(lin_frame, plane)
        lin_frame = lin_frame.sort_values('S', axis=0, ascending=True)
        headers = _compute_headers(lin_frame, plane, dpp, dpp_amp)
        output_handler.write_harpy_output(
            main_input,
            lin_frame,
            headers,
            spectr,
            plane
        )
        all_bad_bpms[plane].extend(bad_bpms_summaries)
        lin[plane] = tfs.TfsDataFrame(lin_frame, headers=headers)
    return all_bad_bpms, lin
Example #12
0
    def _calc_dispersion_response(self):
        """ Response Matrix for delta normalized dispersion

            Eq. 25-27 in [#FranchiAnalyticformulasrapid2017]_
            But w/o the assumtion :math:`\delta K_1 = 0` from Appendix B.1
        """
        LOG.debug("Calculate Dispersion Response Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            tw = self._twiss
            adv = self._phase_advances
            el_out = self._elements_out
            els_in = self._elements_in

            sign_map = {
                "X": {"K0L": 1, "K1L": -1, "K1SL": 1, },
                "Y": {"K0SL": -1, "K1L": 1, "K1SL": 1, },
            }

            col_disp_map = {
                "X": {"K1L": "DX", "K1SL": "DY", },
                "Y": {"K1L": "DY", "K1SL": "DX", },
            }

            q_map = {"X": tw.Q1, "Y": tw.Q2}
            disp_resp = dict.fromkeys(["{p:s}_{t:s}".format(p=p, t=t)
                                       for p in sign_map for t in sign_map[p]])

            for plane in sign_map:
                q = q_map[plane]
                col_beta = "BET{}".format(plane)
                el_types = sign_map[plane].keys()
                els_per_type = [els_in[el_type] for el_type in el_types]

                coeff = np.sqrt(tw.loc[el_out, col_beta].values) / (2 * np.sin(np.pi * q))

                for el_in, el_type in zip(els_per_type, el_types):
                    coeff_sign = sign_map[plane][el_type]
                    out_str = "{p:s}_{t:s}".format(p=plane, t=el_type)

                    if len(el_in):
                        pi2tau = 2 * np.pi * tau(adv[plane].loc[el_in, el_out], q)
                        bet_term = np.sqrt(tw.loc[el_in, col_beta])

                        try:
                            col_disp = col_disp_map[plane][el_type]
                        except KeyError:
                            pass
                        else:
                            bet_term *= tw.loc[el_in, col_disp]

                        disp_resp[out_str] = (coeff_sign * coeff[None, :] * bet_term[:, None] *
                                              np.cos(pi2tau)
                                              ).transpose()
                    else:
                        LOG.debug(
                            "  No '{:s}' variables found. ".format(el_type) +
                            "Dispersion Response '{:s}' will be empty.".format(out_str))
                        disp_resp[out_str] = tfs.TfsDataFrame(None, index=el_out)
        return dict_mul(self._direction, disp_resp)
Example #13
0
    def calc_cmatrix(self):
        """ Calculates C matrix and Coupling and Gamma from it.
        See [#CalagaBetatroncouplingMerging2005]_
        """
        tw = self.twiss_df
        res = self._results_df

        LOG.debug("Calculating CMatrix.")
        with timeit(lambda t:
                    LOG.debug("  CMatrix calculated in {:f}s".format(t))):

            j = np.array([[0., 1.],
                          [-1., 0.]])
            rs = np.reshape(tw.as_matrix(columns=["R11", "R12",
                                                  "R21", "R22"]),
                            (len(tw), 2, 2))
            cs = np.einsum("ij,kjn,no->kio",
                           -j, np.transpose(rs, axes=(0, 2, 1)), j)
            cs = np.einsum("k,kij->kij", (1 / np.sqrt(1 + np.linalg.det(rs))), cs)

            g11a = 1 / np.sqrt(tw.loc[:, "BETX"])
            g12a = np.zeros(len(tw))
            g21a = tw.loc[:, "ALFX"] / np.sqrt(tw.loc[:, "BETX"])
            g22a = np.sqrt(tw.loc[:, "BETX"])
            gas = np.reshape(np.array([g11a, g12a,
                                       g21a, g22a]).T,
                             (len(tw), 2, 2))

            ig11b = np.sqrt(tw.loc[:, "BETY"])
            ig12b = np.zeros(len(tw))
            ig21b = -tw.loc[:, "ALFY"] / np.sqrt(tw.loc[:, "BETY"])
            ig22b = 1. / np.sqrt(tw.loc[:, "BETY"])
            igbs = np.reshape(np.array([ig11b, ig12b,
                                        ig21b, ig22b]).T,
                              (len(tw), 2, 2))
            cs = np.einsum("kij,kjl,kln->kin", gas, cs, igbs)
            gammas = np.sqrt(1 - np.linalg.det(cs))

            res.loc[:, "GAMMA_C"] = gammas

            res.loc[:, "F1001_C"] = ((cs[:, 0, 0] + cs[:, 1, 1]) * 1j +
                                     (cs[:, 0, 1] - cs[:, 1, 0])) / 4 / gammas
            res.loc[:, "F1010_C"] = ((cs[:, 0, 0] - cs[:, 1, 1]) * 1j +
                                     (-cs[:, 0, 1]) - cs[:, 1, 0]) / 4 / gammas

            res.loc[:, "C11"] = cs[:, 0, 0]
            res.loc[:, "C12"] = cs[:, 0, 1]
            res.loc[:, "C21"] = cs[:, 1, 0]
            res.loc[:, "C22"] = cs[:, 1, 1]

            LOG.debug("  Average coupling amplitude |F1001|: {:g}".format(np.mean(
                np.abs(res.loc[:, "F1001_C"]))))
            LOG.debug("  Average coupling amplitude |F1010|: {:g}".format(np.mean(
                np.abs(res.loc[:, "F1010_C"]))))
            LOG.debug("  Average gamma: {:g}".format(np.mean(
                np.abs(res.loc[:, "GAMMA_C"]))))

        self._log_added('GAMMA_C', 'F1001_C', 'F1010_C', 'C11', 'C12', 'C21', 'C22')
Example #14
0
def _add_coupling(dict_of_tfs):
    """ Adds coupling to the tfs. QUICK FIX VIA LOOP!"""
    with timeit(lambda t: LOG.debug("  Time adding coupling: {:f}s".format(t))):
        for var in dict_of_tfs:
            twopt = TwissOptics(dict_of_tfs[var])
            cpl = twopt.get_coupling("cmatrix")
            dict_of_tfs[var]["1001"] = cpl["F1001"]
            dict_of_tfs[var]["1010"] = cpl["F1010"]
        return dict_of_tfs
Example #15
0
def _add_coupling(dict_of_tfs):
    """ Adds coupling to the tfs. QUICK FIX VIA LOOP!"""
    with timeit(
            lambda t: LOG.debug("  Time adding coupling: {:f}s".format(t))):
        for var in dict_of_tfs:
            twopt = TwissOptics(dict_of_tfs[var], keep_all_elem=True)
            cpl = twopt.get_coupling("cmatrix")
            dict_of_tfs[var]["1001"] = cpl["F1001"]
            dict_of_tfs[var]["1010"] = cpl["F1010"]
        return dict_of_tfs
    def _calc_phase_response(self):
        """ Response Matrix for delta DPhi.

        Eq. 28 in [#FranchiAnalyticformulasrapid2017]_
        Reduced to only delta phase.
        --> w = 0:  DPhi(z,j) = DPhi(x, 0->j)

        This calculation could also be achieved by applying np.cumsum to the DataFrames of
        _calc_phase_adv_response() (tested!), but _calc_phase_response() is about 4x faster.
        """
        LOG.debug("Calculate Phase Response Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}s".format(t))):
            tw = self._twiss
            adv = self._phase_advances
            k1_el = self._elements_in["K1L"]
            el_out = self._elements_out

            if len(k1_el) > 0:
                dmu = dict.fromkeys(["X", "Y"])

                pi = tfs.TfsDataFrame(
                    tw['S'][:, None] <
                    tw['S'][None, :],  # pi(i,j) = s(i) < s(j)
                    index=tw.index,
                    columns=tw.index,
                    dtype=int)

                pi_term = pi.loc[k1_el, el_out].values

                for plane in ["X", "Y"]:
                    col_beta = "BET" + plane
                    q = tw.Q1 if plane == "X" else tw.Q2
                    coeff_sign = 1 if plane == "X" else -1

                    pi2tau = 2 * np.pi * tau(
                        adv[plane].loc[k1_el, [DUMMY_ID] + el_out], q)
                    brackets = (2 * pi_term + (
                        (np.sin(2 * pi2tau.loc[:, el_out].values) -
                         np.sin(2 * pi2tau.loc[:, DUMMY_ID].values[:, None])) /
                        np.sin(2 * np.pi * q)))
                    dmu[plane] = tfs.TfsDataFrame(
                        tw.loc[k1_el, col_beta].values[:, None] * brackets *
                        (coeff_sign / (8 * np.pi)),
                        index=k1_el,
                        columns=el_out).transpose()
            else:
                LOG.debug(
                    "  No 'K1L' variables found. Phase Response will be empty."
                )
                dmu = {
                    "X": tfs.TfsDataFrame(None, index=el_out),
                    "Y": tfs.TfsDataFrame(None, index=el_out)
                }

        return dict_mul(self._direction, dmu)
    def get_response_for(self, obs=None):
        """ Calculates and returns only desired response matrices """

        # calling functions for the getters to call functions only if needed
        def caller(func, plane):
            return func()[plane]

        def disp_caller(func, plane):
            disp = func()
            return response_add(
                *[disp[k] for k in disp.keys() if k.startswith(plane)])

        def tune_caller(func, _unused):
            tune = func()
            res = tune["X"].append(tune["Y"])
            res.index = ["Q1", "Q2"]
            return res

        def couple_caller(func, plane):
            # apply() converts empty DataFrames to Series! Cast them back.
            # Also: take care of minus-sign convention!
            sign = -1 if plane[-1] == "R" else 1
            part_func = np.real if plane[-1] == "R" else np.imag
            return sign * tfs.TfsDataFrame(
                func()[plane[:-1]].apply(part_func).astype(np.float64))

        # to avoid if-elif-elif-...
        obs_map = {
            'Q': (tune_caller, self.get_tune, None),
            'BETX': (caller, self.get_beta, "X"),
            'BETY': (caller, self.get_beta, "Y"),
            'BBX': (caller, self.get_beta_beat, "X"),
            'BBY': (caller, self.get_beta_beat, "Y"),
            'MUX': (caller, self.get_phase, "X"),
            'MUY': (caller, self.get_phase, "Y"),
            'DX': (disp_caller, self.get_dispersion, "X"),
            'DY': (disp_caller, self.get_dispersion, "Y"),
            'NDX': (disp_caller, self.get_norm_dispersion, "X"),
            'NDY': (disp_caller, self.get_norm_dispersion, "Y"),
            'F1001R': (couple_caller, self.get_coupling, "1001R"),
            'F1001I': (couple_caller, self.get_coupling, "1001I"),
            'F1010R': (couple_caller, self.get_coupling, "1010R"),
            'F1010I': (couple_caller, self.get_coupling, "1010I"),
        }

        if obs is None:
            obs = obs_map.keys()

        LOG.debug("Calculating responses for {:s}.".format(obs))
        with timeit(lambda t: LOG.debug("Total time getting responses: {:f}s".
                                        format(t))):
            response = dict.fromkeys(obs)
            for key in obs:
                response[key] = obs_map[key][0](*obs_map[key][1:3])
        return response
def _do_clean(main_input, clean_input, bpm_datas, file_date, model_tfs):
    usvs, all_bad_bpms, bpm_ress = {}, {}, {}
    clean_writer = output_handler.CleanedAsciiWritter(main_input, file_date)
    for plane in ("x", "y"):
        bpm_data = bpm_datas[plane]
        bpm_data, bpms_not_in_model = _get_only_model_bpms(bpm_data, model_tfs)
        if bpm_data.empty:
            raise AssertionError(
                "Check BPMs names! None of the BPMs was found in the model!")

        bad_bpms = []
        usv = None

        with timeit(lambda spanned: LOGGER.debug("Time for filtering: %s",
                                                 spanned)):
            bpm_data, bad_bpms_clean = clean.clean(
                bpm_data,
                clean_input,
                file_date,
            )
        with timeit(lambda spanned: LOGGER.debug("Time for SVD clean: %s",
                                                 spanned)):
            bpm_data, bpm_res, bad_bpms_svd, usv = clean.svd_clean(
                bpm_data,
                clean_input,
            )
        bpm_ress[plane] = bpm_res
        bad_bpms.extend(bpms_not_in_model)
        bad_bpms.extend(bad_bpms_clean)
        bad_bpms.extend(bad_bpms_svd)
        all_bad_bpms[plane] = bad_bpms
        setattr(clean_writer, "samples_matrix_" + plane, bpm_data)

        if plane == "x":
            dpp = _calc_dp_over_p(main_input, bpm_data)
        bpm_datas[plane] = bpm_data
        usvs[plane] = usv

    if clean_input.write_clean:
        clean_writer.dpp = dpp
        clean_writer.write()
    return usvs, all_bad_bpms, bpm_ress, dpp
Example #19
0
    def _remove_nonnecessaries(self):
        """ Removies unnecessary entries from model

        Load model into twiss_df first!
        """
        LOG.debug("Removing unnecessary entries:")
        LOG.debug("  Entries total: {:d}".format(self.twiss_df.shape[0]))
        with timeit(lambda t: LOG.debug("  Removed in {:f}s".format(t))):
            cleaned = self.twiss_df.loc[
                regex_in(r"\A(M|BPM)", self.twiss_df.index), :]
        LOG.debug("  Entries left: {:d}".format(cleaned.shape[0]))
        return cleaned
def run_all(main_input, clean_input, harpy_input, to_log):
    with timeit(
            lambda spanned: LOGGER.info("Total time for file: %s", spanned)):
        if (not main_input.write_raw and clean_input is None
                and harpy_input is None):
            LOGGER.error("No file has been choosen to be writen!")
            return
        _setup_file_log_handler(main_input)
        LOGGER.debug(to_log)

        tbt_files = turn_by_turn_reader.read_tbt_file(main_input.file)
        for tbt_file in tbt_files:
            run_all_for_file(tbt_file, main_input, clean_input, harpy_input)
Example #21
0
    def _calc_phase_advance_response(self):
        """ Response Matrix for delta DPhi.

        Eq. 28 in [#FranchiAnalyticformulasrapid2017]_
        Reduced to only phase advances between consecutive elements,
        as the 3D-Matrix of all elements exceeds memory space
        (~11000^3 = 1331 Giga Elements)
        --> w = j-1:  DPhi(z,j) = DPhi(x, (j-1)->j)
        """
        LOG.debug("Calculate Phase Advance Response Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}s".format(t))):
            tw = self._twiss
            adv = self._phase_advances
            k1_el = self._elements_in["K1L"]

            el_out_all = [DUMMY_ID] + self._elements_out  # Add MU[XY] = 0.0 to the start
            el_out = el_out_all[1:]  # in these we are actually interested
            el_out_mm = el_out_all[0:-1]  # elements--

            if len(k1_el) > 0:
                dmu = dict.fromkeys(["X", "Y"])

                pi = tfs.TfsDataFrame(tw['S'][:, None] < tw['S'][None, :],  # pi(i,j) = s(i) < s(j)
                                      index=tw.index, columns=tw.index, dtype=int)

                pi_term = (pi.loc[k1_el, el_out].values -
                           pi.loc[k1_el, el_out_mm].values +
                           np.diag(pi.loc[el_out, el_out_mm].values)[None, :])

                for plane in ["X", "Y"]:
                    col_beta = "BET" + plane
                    q = tw.Q1 if plane == "X" else tw.Q2
                    coeff_sign = 1 if plane == "X" else -1

                    pi2tau = 2 * np.pi * tau(adv[plane].loc[k1_el, el_out_all], q)
                    brackets = (2 * pi_term +
                                ((np.sin(2 * pi2tau.loc[:, el_out].values) -
                                  np.sin(2 * pi2tau.loc[:, el_out_mm].values))
                                 / np.sin(2 * np.pi * q)
                                 ))
                    dmu[plane] = tfs.TfsDataFrame(
                        tw.loc[k1_el, col_beta].values[:, None] * brackets
                        * (coeff_sign / (8 * np.pi)),
                        index=k1_el, columns=el_out).transpose()
            else:
                LOG.debug("  No 'K1L' variables found. Phase Response will be empty.")
                dmu = {"X": tfs.TfsDataFrame(None, index=el_out),
                       "Y": tfs.TfsDataFrame(None, index=el_out)}

        return dict_mul(self._direction, dmu)
def evaluate_for_variables(accel_inst,
                           variable_categories,
                           order=4,
                           num_proc=multiprocessing.cpu_count(),
                           temp_dir=None):
    """ Generate a dictionary containing response matrices for
        beta, phase, dispersion, tune and coupling and saves it to a file.

        Args:
            accel_inst : Accelerator Instance.
            variable_categories (list): Categories of the variables/knobs to use. (from .json)
            order (int or tuple): Max or [min, max] of K-value order to use.
            num_proc (int): Number of processes to use in parallel.
            temp_dir (str): temporary directory. If ``None``, uses model_dir.
    """
    LOG.debug("Generating Fullresponse via Mad-X.")
    with timeit(lambda t: LOG.debug(
            "  Total time generating fullresponse: {:f}s".format(t))):
        if not temp_dir:
            temp_dir = accel_inst.model_dir
        create_dirs(temp_dir)

        variables = accel_inst.get_variables(classes=variable_categories)
        if len(variables) == 0:
            raise ValueError(
                "No variables found! Make sure your categories are valid!")

        # try:
        #     variables = variables.tolist()
        # except AttributeError:
        #     pass

        num_proc = num_proc if len(variables) > num_proc else len(variables)
        process_pool = multiprocessing.Pool(processes=num_proc)

        k_values = _get_orders(order)

        try:
            _generate_madx_jobs(accel_inst, variables, k_values, num_proc,
                                temp_dir)
            _call_madx(process_pool, temp_dir, num_proc)
            mapping = _load_madx_results(variables, k_values, process_pool,
                                         temp_dir)
        except IOError:
            raise IOError("MADX was unable to compute the mapping.")
        finally:
            _clean_up(variables, temp_dir, num_proc)
    return mapping
Example #23
0
    def _calc_dispersion_response(self):
        """ Response Matrix for delta dispersion

            Eq. 25-27 in [#FranchiAnalyticformulasrapid2017]_
        """
        LOG.debug("Calculate Dispersion Response Matrix")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            tw = self._twiss
            adv = self._phase_advances
            el_out = self._elements_out
            els_in = self._elements_in

            disp_resp = dict.fromkeys(["X_K0L", "X_K1SL", "Y_K0SL", "Y_K1SL"])

            for plane in ["X", "Y"]:
                q = tw.Q1 if plane == "X" else tw.Q2
                type_plane = ("K0L" if plane == "X" else "K0SL", "K1SL")
                el_in_plane = (els_in[type_plane[0]], els_in[type_plane[1]])
                col_beta = "BET" + plane
                col_disp = "DY" if plane == "X" else "DX"

                if any((len(el_in_plane[0]), len(el_in_plane[1]))):
                    coeff = np.sqrt(tw.loc[el_out, col_beta].values) / (
                        2 * np.sin(np.pi * q))

                for el_in, el_type in zip(el_in_plane, type_plane):
                    coeff_sign = -1 if el_type == "K0SL" else 1
                    out_str = "{p:s}_{t:s}".format(p=plane, t=el_type)

                    if len(el_in):
                        pi2tau = 2 * np.pi * tau(adv[plane].loc[el_in, el_out],
                                                 q)
                        bet_term = np.sqrt(tw.loc[el_in, col_beta].values)
                        if el_type == "K1SL":
                            bet_term *= tw.loc[el_in, col_disp].values
                        disp_resp[out_str] = tfs.TfsDataFrame(
                            coeff_sign * coeff[None, :] * bet_term[:, None] *
                            np.cos(pi2tau),
                            index=el_in,
                            columns=el_out).transpose()
                    else:
                        LOG.debug(
                            "  No '{:s}' variables found. ".format(el_type) +
                            "Dispersion Response '{:s}' will be empty.".format(
                                out_str))
                        disp_resp[out_str] = tfs.TfsDataFrame(None,
                                                              index=el_out)
        return dict_mul(self._direction, disp_resp)
Example #24
0
def create_response(accel_inst, vars_categories, optics_params):
    """ Wrapper to create response via TwissResponse """
    LOG.debug("Creating response via TwissResponse.")

    varmap_path = check_varmap_file(accel_inst, vars_categories)

    with timeit(lambda t:
                LOG.debug("Total time getting TwissResponse: {:f}s".format(t))):
        tr = TwissResponse(accel_inst, vars_categories, varmap_path)
        response = tr.get_response_for(optics_params)

    if not any([resp.size for resp in response.values()]):
        raise ValueError("Responses are all empty. " +
                         "Are variables {:s} ".format(tr.get_variable_names()) +
                         "correct for '{:s}'?".format(optics_params)
                         )
    return response
Example #25
0
    def _calc_chromatic_term(self):
        """ Calculates the chromatic term which is common to all chromatic equations """
        LOG.debug("Calculating Chromatic Term.")
        res = self._results_df
        tw = self.twiss_df

        #TODO: Decide wether DX, DY from Model or from calc

        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            mask = (tw['K1L'] != 0) | (tw['K2L'] != 0) | (tw['K2SL'] != 0)
            sum_term = tw.loc[mask, 'K1L'] - \
                       (tw.loc[mask, 'K2L'] * tw.loc[mask, 'DX']) + \
                       (tw.loc[mask, 'K2SL'] * tw.loc[mask, 'DY'])
            res['CHROMX'] = sum_term * tw.loc[mask, 'BETX']
            res['CHROMY'] = sum_term * tw.loc[mask, 'BETY']

        LOG.debug("Chromatic Term Calculated.")
Example #26
0
def generate_fullresponse(accel_inst,
                          variable_categories,
                          delta_k=0.00002,
                          num_proc=multiprocessing.cpu_count(),
                          temp_dir=None):
    """ Generate a dictionary containing response matrices for
        beta, phase, dispersion, tune and coupling and saves it to a file.

        Args:
            accel_inst : Accelerator Instance.
            variable_categories (list): Categories of the variables/knobs to use. (from .json)
            delta_k (float): delta K1L to be applied to quads for sensitivity matrix
            num_proc (int): Number of processes to use in parallel.
            temp_dir (str): temporary directory. If ``None``, uses folder of original_jobfile.
    """
    LOG.debug("Generating Fullresponse via Mad-X.")
    with timeit(lambda t: LOG.debug(
            "  Total time generating fullresponse: {:f}s".format(t))):
        if not temp_dir:
            temp_dir = accel_inst.model_dir
        create_dirs(temp_dir)

        variables = accel_inst.get_variables(classes=variable_categories)
        if len(variables) == 0:
            raise ValueError(
                "No variables found! Make sure your categories are valid!")

        # try:
        #     variables = variables.tolist()
        # except AttributeError:
        #     pass

        num_proc = num_proc if len(variables) > num_proc else len(variables)
        process_pool = multiprocessing.Pool(processes=num_proc)

        incr_dict = _generate_madx_jobs(accel_inst, variables, delta_k,
                                        num_proc, temp_dir)
        _call_madx(process_pool, temp_dir, num_proc)
        _clean_up(temp_dir, num_proc)

        var_to_twiss = _load_madx_results(variables, process_pool, incr_dict,
                                          temp_dir)
        fullresponse = _create_fullresponse_from_dict(var_to_twiss)

    return fullresponse
Example #27
0
    def calc_linear_chromaticity(self):
        """ Calculate the Linear Chromaticity

        Eq. 31 in [#FranchiAnalyticformulasrapid2017]_
        """
        res = self._results_df

        if 'CHROMX' not in res:
            self._calc_chromatic_term()

        LOG.debug("Calculating Linear Chromaticity")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            DQ1 = -1 / (4 * np.pi) * res['CHROMX'].dropna().sum(axis="index")
            DQ2 = 1 / (4 * np.pi) * res['CHROMY'].dropna().sum(axis="index")

        self._results_df.DQ1 = DQ1
        self._results_df.DQ2 = DQ2
        LOG.debug("  Q'x: {:f}".format(DQ1))
        LOG.debug("  Q'y: {:f}".format(DQ2))

        self._log_added('DQ1', 'DQ2')
Example #28
0
def generate_fullresponse(accel_inst, variable_categories,
                          delta_k=0.00002, num_proc=multiprocessing.cpu_count(),
                          temp_dir=None):
    """ Generate a dictionary containing response matrices for
        beta, phase, dispersion, tune and coupling and saves it to a file.

        Args:
            accel_inst : Accelerator Instance.
            variable_categories (list): Categories of the variables/knobs to use. (from .json)
            delta_k (float): delta K1L to be applied to quads for sensitivity matrix
            num_proc (int): Number of processes to use in parallel.
            temp_dir (str): temporary directory. If ``None``, uses folder of original_jobfile.
    """
    LOG.debug("Generating Fullresponse via Mad-X.")
    with timeit(lambda t: LOG.debug("  Total time generating fullresponse: {:f}s".format(t))):
        if not temp_dir:
            temp_dir = accel_inst.model_dir
        create_dirs(temp_dir)

        variables = accel_inst.get_variables(classes=variable_categories)
        if len(variables) == 0:
            raise ValueError("No variables found! Make sure your categories are valid!")

        # try:
        #     variables = variables.tolist()
        # except AttributeError:
        #     pass

        num_proc = num_proc if len(variables) > num_proc else len(variables)
        process_pool = multiprocessing.Pool(processes=num_proc)

        incr_dict = _generate_madx_jobs(accel_inst, variables,
                                        delta_k, num_proc, temp_dir)
        _call_madx(process_pool, temp_dir, num_proc)
        _clean_up(temp_dir, num_proc)

        var_to_twiss = _load_madx_results(variables, process_pool, incr_dict, temp_dir)
        fullresponse = _create_fullresponse_from_dict(var_to_twiss)

    return fullresponse
Example #29
0
def evaluate_for_variables(accel_inst, variable_categories, order=4,
                           num_proc=multiprocessing.cpu_count(),
                           temp_dir=None):
    """ Generate a dictionary containing response matrices for
        beta, phase, dispersion, tune and coupling and saves it to a file.

        Args:
            accel_inst : Accelerator Instance.
            variable_categories (list): Categories of the variables/knobs to use. (from .json)
            order (int or tuple): Max or [min, max] of K-value order to use.
            num_proc (int): Number of processes to use in parallel.
            temp_dir (str): temporary directory. If ``None``, uses model_dir.
    """
    LOG.debug("Generating Fullresponse via Mad-X.")
    with timeit(lambda t: LOG.debug("  Total time generating fullresponse: {:f}s".format(t))):
        if not temp_dir:
            temp_dir = accel_inst.model_dir
        create_dirs(temp_dir)

        variables = accel_inst.get_variables(classes=variable_categories)
        if len(variables) == 0:
            raise ValueError("No variables found! Make sure your categories are valid!")

        # try:
        #     variables = variables.tolist()
        # except AttributeError:
        #     pass

        num_proc = num_proc if len(variables) > num_proc else len(variables)
        process_pool = multiprocessing.Pool(processes=num_proc)

        k_values = _get_orders(order)

        try:
            _generate_madx_jobs(accel_inst, variables, k_values, num_proc, temp_dir)
            _call_madx(process_pool, temp_dir, num_proc)
            mapping = _load_madx_results(variables, k_values, process_pool, temp_dir)
        finally:
            _clean_up(variables, temp_dir, num_proc)
    return mapping
def create_response(accel_inst, vars_categories, optics_params):
    """ Wrapper to create response via TwissResponse """
    LOG.debug("Creating response via TwissResponse.")
    vars_list = accel_inst.get_variables(classes=vars_categories)
    if len(vars_list) == 0:
        raise ValueError(
            "No variables found! Make sure your categories are valid!")

    varmap_path = check_varmap_file(accel_inst, vars_categories)

    with timeit(lambda t: LOG.debug("Total time getting TwissResponse: {:f}s".
                                    format(t))):
        sign = 1 if accel_inst.get_beam() == 1 else -1
        tr = TwissResponse(varmap_path, accel_inst.get_elements_tfs(),
                           vars_list, sign)
        response = tr.get_response_for(optics_params)

    if not any([resp.size for resp in response.values()]):
        raise ValueError("Responses are all empty. " +
                         "Are variables {:s} ".format(vars_list) +
                         "correct for '{:s}'?".format(optics_params))
    return response
Example #31
0
def get_phase_advances(twiss_df):
    """
    Calculate phase advances between all elements
    :return: Matrices similar to DPhi(i,j) = Phi(j) - Phi(i)
    """
    LOG.debug("Calculating Phase Advances:")
    phase_advance_dict = dict.fromkeys(['X', 'Y'])
    with timeit(lambda t: LOG.debug("  Phase Advances calculated in {:f}s".
                                    format(t))):
        for plane in ['X', 'Y']:
            colmn_phase = "MU" + plane

            phases_mdl = twiss_df.loc[twiss_df.index, colmn_phase]
            # Same convention as in [1]: DAdv(i,j) = Phi(j) - Phi(i)
            phase_advances = pd.DataFrame(
                (phases_mdl[None, :] - phases_mdl[:, None]),
                index=twiss_df.index,
                columns=twiss_df.index)
            # Do not calculate dphi and tau here.
            # only slices of phase_advances as otherwise super slow
            phase_advance_dict[plane] = phase_advances
    return phase_advance_dict
Example #32
0
    def _sort_element_types(self):
        """ Sorts Elements by types

        Load model into twiss_df first!
        """
        LOG.debug("Sorting Elements into types:")
        tw = self.twiss_df
        with timeit(lambda t: LOG.debug("  Sorted in {:f}s".format(t))):
            return {
                'BPM': regex_in(r'\ABPM', tw.index),
                'MB': regex_in(r'\AMB[^S]', tw.index),
                'MBS': regex_in(r'\AMBS', tw.index),
                'MQ': regex_in(r'\AMQ[^ST]', tw.index),
                'MQS': regex_in(r'\AMQS', tw.index),
                'MQT': regex_in(r'\AMQT', tw.index),
                'MS': regex_in(r'\AMS[^S]', tw.index),
                'MSS': regex_in(r'\AMSS', tw.index),
                'MO': regex_in(r'\AMO[^S]', tw.index),
                'MOS': regex_in(r'\AMOS', tw.index),
                'MCB': regex_in(r'\AMCB', tw.index),
                'MCS': regex_in(r'\AMCS', tw.index),
                'MCO': regex_in(r'\AMCO', tw.index),
                'MCD': regex_in(r'\AMCD', tw.index),
            }
Example #33
0
    def calc_ac_dipole_driving_terms(self, order_or_terms, spectral_line, plane, ac_tunes, acd_name):
        """ Calculates the Hamiltonian Terms under Forced Motion.
        
        Args:
            order_or_terms: int, string or list of strings
                If an int is given all Resonance Driving Terms up to this order
                will be calculated.
                The strings are assumed to be the desired driving term names, e.g. "F1001"
            spectral_line: tuple
                Needed to determine what phase advance is needed before and
                after AC dipole location, depends on detal+ and delta-.
                Sample input: (2,-1)
            plane: string
                Either 'H' or 'V' to determine phase term of
                AC dipole before and after ACD location.
            ac_tunes: tuple
                Contains horizontal and vertical AC dipole tunes, i.e. (0.302, 0.33)
        """
        if isinstance(order_or_terms, int):
            rdt_list = get_all_rdts(order_or_terms)
        elif not isinstance(order_or_terms, list):
            rdt_list = [order_or_terms]
        else:
            rdt_list = order_or_terms

        LOG.debug("Calculating RDTs: {:s}.".format(str(rdt_list)[1:-1]))
        with timeit(lambda t:
                    LOG.debug("  RDTs calculated in {:f}s".format(t))):

            i2pi = 2j * np.pi
            tw = self.twiss_df
            LOG.debug('STARTING phase advance calculation...')
            phs_adv = self.get_phase_adv()
            LOG.debug('phase advance calculation done...')
            res = self._results_df

            for rdt in rdt_list:
                assertion(len(rdt) == 5 and rdt[0].upper() == 'F',
                          ValueError("'{:s}' does not seem to be a valid RDT name.".format(rdt)))

                conj_rdt = ''.join(['F', rdt[2], rdt[1], rdt[4], rdt[3]])

                if conj_rdt in self._results_df:
                    res[rdt.upper()] = np.conjugate(self._results_df[conj_rdt])
                else:
                    j, k, l, m = int(rdt[1]), int(rdt[2]), int(rdt[3]), int(rdt[4])
                    n = j + k + l + m

                    assertion(n >= 2, ValueError(
                        "The RDT-order has to be >1 but was {:d} for {:s}".format(n, rdt)))

                    if (l + m) % 2 == 0:
                        src = 'K' + str(n-1) + 'L'
                        sign = -(1j ** (l+m))
                    else:
                        src = 'K' + str(n-1) + 'SL'
                        sign = -(1j ** (l+m+1))

                    if spectral_line[1] < 0:
                        c, d = 0, abs(spectral_line[1])
                    elif spectral_line[1] > 0:
                        c, d = abs(spectral_line[1]), 0
                    elif spectral_line[1] == 0:
                        c, d = 0, 0
                    
                    qx_min = ac_tunes[0]-tw.Q1
                    qy_min = ac_tunes[1]-tw.Q2
                    qx_plus = ac_tunes[0]+tw.Q1
                    qy_plus = ac_tunes[1]+tw.Q2
                    
                    if plane == 'H':
                        if spectral_line[0] == (k-j+1):
                            a, b = 0, 0 
                        elif spectral_line[0] == -(k-j+1):
                            a, b = j-1, k
                        else:
                            LOG.warning("Line of different order than main driving term")
                        
                        if spectral_line[1] == (m-l):
                            c, d = 0, 0 
                        elif spectral_line[1] == -(m-l):
                            c, d = l, m
                        else:
                            LOG.warning("Line of different order than main driving term")
                        
                        acd_ph = np.exp(i2pi * (
                                (k - j + 1 + a - b) * qx_min +
                                (b - a) * qx_plus +
                                (m - l + c - d) * qy_min +
                                (d - c) * qy_plus
                        ))
                        # acd_ph = np.exp(i2pi*( (k-j+1)*Qx_min + (m-l)*Qy_min ))
                        denom1 = 1./(factorial(j) * factorial(k) * factorial(l) * factorial(m) *
                                     2**n)
                        denom2 = 1./(1. - np.exp(-i2pi * (-tw.Q1 + spectral_line[0] * ac_tunes[0] +
                                                          spectral_line[1] * ac_tunes[1]))
                                     )
                        # denom2 = 1./(1. - np.exp(i2pi * ((j-k)*tw.Q1 + (l-m)*tw.Q2 )))

                    elif plane == 'V':
                        if spectral_line[0] == (k-j):
                            a, b = 0, 0 
                        elif spectral_line[0] == -(k-j):
                            a, b = j-1, k
                        else:
                            LOG.warning("Line of different order than main driving term")
                        
                        if spectral_line[1] == (m-l+1):
                            a, b = 0, 0 
                        elif spectral_line[1] == -(m-l+1):
                            a, b = j-1, k
                        else:
                            LOG.warning("Line of different order than main driving term")
                        
                        acd_ph = np.exp(i2pi * (
                                (k - j + a - b) * qx_min +
                                (b - a) * qx_plus +
                                (m - l + 1 + c - d) * qy_min +
                                (d - c) * qy_plus
                        ))
                        denom1 = 1./(factorial(j) * factorial(k) * factorial(l) * factorial(m) *
                                     2**n)
                        denom2 = 1./(1. - np.exp(i2pi * (-tw.Q2 + spectral_line[0] * ac_tunes[0] +
                                                         spectral_line[1] * ac_tunes[1]))
                                     )

                    try:
                        mask_in = (tw[src] != 0) | (tw.index == acd_name)
                        if sum(mask_in) == 0:
                            raise KeyError
                    except KeyError:
                        # either src is not in tw or all k's are zero.
                        LOG.warning("  All {:s} == 0. RDT '{:s}' will be zero.".format(src, rdt))
                        res.loc[:, rdt.upper()] = 0
                    else:
                        # the next three lines determine the main order of speed, hence
                        # - mask as much as possible
                        # - additions are faster than multiplications (-> applymap last)
                        phx = dphi(phs_adv['X'].loc[mask_in, :], tw.Q1)
                        phy = dphi(phs_adv['Y'].loc[mask_in, :], tw.Q2)
                        
                        phs_acd = pd.DataFrame(columns=phs_adv['X'].loc[mask_in, :].columns,
                                               index=phs_adv['X'].loc[mask_in, :].index)
                        phs_acd[:] = acd_ph
                        mk_acd = phs_adv['X'].loc[mask_in, :] > 0
                        phs_acd.where(mk_acd, 1., inplace=True) 

                        phase_term = ((j-k) * phx + (l-m) * phy).applymap(lambda p: np.exp(i2pi*p))
                        total_phase_term = phase_term.multiply(phs_acd)

                        beta_term = tw.loc[mask_in, src] * \
                                    tw.loc[mask_in, 'BETX'] ** ((j+k) / 2.) * \
                                    tw.loc[mask_in, 'BETY'] ** ((l+m) / 2.)
                        
                        res.loc[:, rdt.upper().replace('F','HAC')] = sign * total_phase_term.multiply(
                            beta_term, axis="index").sum(axis=0).transpose() * denom1

                        res.loc[:, rdt.upper().replace('F','FAC')] = sign * total_phase_term.multiply(
                            beta_term, axis="index").sum(axis=0).transpose() * denom1 * denom2

                        LOG.debug("  Average RDT amplitude |{:s}|: {:g}".format(rdt, np.mean(
                            np.abs(res.loc[:, rdt.upper()]))))

        self._log_added(*rdt_list)
Example #34
0
    def calc_linear_dispersion(self, bpms_only=False):
        """ Calculate the Linear Disperion.

        Eq. 24 in [#FranchiAnalyticformulasrapid2017]_
        """
        tw = self.twiss_df
        phs_adv = self.get_phase_adv()
        res = self._results_df
        coeff_fun = self._linear_dispersion_coeff
        sum_fun = self._linear_dispersion_sum

        # Calculate
        LOG.debug("Calculate Linear Dispersion")
        with timeit(lambda t: LOG.debug("  Time needed: {:f}".format(t))):
            # sources
            k0_mask = tw['K0L'] != 0
            k0s_mask = tw['K0SL'] != 0
            k1s_mask = tw['K1SL'] != 0

            mx_mask = k0_mask | k1s_mask  # magnets contributing to Dx,j (-> Dy,m)
            my_mask = k0s_mask | k1s_mask  # magnets contributing to Dy,j (-> Dx,m)

            if not any(mx_mask | my_mask):
                LOG.warning(
                    "  No linear dispersion contributions found. Values will be NaN."
                )
                res['DX'] = np.nan
                res['DY'] = np.nan
                return

            # results
            if bpms_only:
                res_mask = self._elements["BPM"]
            else:
                res_mask = np.ones(res.shape[0], dtype=bool)

            # create temporary DataFrame for magnets with coefficients already in place
            df = tfs.TfsDataFrame(index=tw.index).join(
                coeff_fun(tw.loc[:, 'BETX'],
                          tw.Q1)).join(coeff_fun(tw.loc[:, 'BETY'], tw.Q2))
            df.columns = ['COEFFX', 'COEFFY']

            LOG.debug("  Calculate uncoupled linear dispersion")
            df.loc[my_mask, 'DX'] = df.loc[my_mask, 'COEFFX'] * \
                                    sum_fun(tw.loc[mx_mask, 'K0L'],
                                            0,
                                            0,
                                            tw.loc[mx_mask, 'BETX'],
                                            tau(phs_adv['X'].loc[mx_mask, my_mask], tw.Q1)
                                            ).transpose()
            df.loc[mx_mask, 'DY'] = df.loc[mx_mask, 'COEFFY'] * \
                                    sum_fun(-tw.loc[my_mask, 'K0SL'],  # MINUS!
                                            0,
                                            0,
                                            tw.loc[my_mask, 'BETY'],
                                            tau(phs_adv['Y'].loc[my_mask, mx_mask], tw.Q2)
                                            ).transpose()

            LOG.debug("  Calculate full linear dispersion values")
            res.loc[res_mask, 'DX'] = df.loc[res_mask, 'COEFFX'] * \
                                sum_fun(tw.loc[mx_mask, 'K0L'],
                                        tw.loc[mx_mask, 'K1SL'],
                                        df.loc[mx_mask, 'DY'],
                                        tw.loc[mx_mask, 'BETX'],
                                        tau(phs_adv['X'].loc[mx_mask, res_mask], tw.Q1)
                                        ).transpose()
            res.loc[res_mask, 'DY'] = df.loc[res_mask, 'COEFFY'] * \
                                sum_fun(-tw.loc[my_mask, 'K0SL'],  # MINUS!
                                        tw.loc[my_mask, 'K1SL'],
                                        df.loc[my_mask, 'DX'],
                                        tw.loc[my_mask, 'BETY'],
                                        tau(phs_adv['Y'].loc[my_mask, res_mask], tw.Q2)
                                        ).transpose()

        LOG.debug("  Average linear dispersion Dx: {:g}".format(
            np.mean(res['DX'])))
        LOG.debug("  Average linear dispersion Dy: {:g}".format(
            np.mean(res['DY'])))
        self._log_added('DX', 'DY')
Example #35
0
    def calc_rdts(self, order):
        """ Calculates the Resonance Driving Terms.
        
        Eq. A8 in [#FranchiAnalyticformulasrapid2017]_

        Args:
            order: int, string or list of strings
                If an int is given all Resonance Driving Terms up to this order
                will be calculated.
                The strings are assumed to be the desired driving term names, e.g. "F1001"
        """
        if isinstance(order, int):
            order = get_all_rdts(order)
        elif not isinstance(order, list):
            order = [order]

        LOG.debug("Calculating RDTs: {:s}.".format(str(order)[1:-1]))
        with timeit(
                lambda t: LOG.debug("  RDTs calculated in {:f}s".format(t))):

            i2pi = 2j * np.pi
            tw = self.twiss_df
            phs_adv = self.get_phase_adv()
            res = self._results_df

            for rdt in order:
                assertion(
                    len(rdt) == 5 and rdt[0].upper() == 'F',
                    ValueError(
                        "'{:s}' does not seem to be a valid RDT name.".format(
                            rdt)))

                conj_rdt = ''.join(['F', rdt[2], rdt[1], rdt[4], rdt[3]])

                if conj_rdt in self._results_df:
                    res[rdt.upper()] = np.conjugate(self._results_df[conj_rdt])
                else:
                    j, k, l, m = int(rdt[1]), int(rdt[2]), int(rdt[3]), int(
                        rdt[4])
                    n = j + k + l + m

                    assertion(
                        n >= 2,
                        ValueError(
                            "The RDT-order has to be >1 but was {:d} for {:s}".
                            format(n, rdt)))

                    denom = 1. / (factorial(j) * factorial(k) * factorial(l) *
                                  factorial(m) * 2**n *
                                  (1. - np.exp(i2pi * ((j - k) * tw.Q1 +
                                                       (l - m) * tw.Q2))))

                    if (l + m) % 2 == 0:
                        src = 'K' + str(n - 1) + 'L'
                        sign = -(1j**(l + m))
                    else:
                        src = 'K' + str(n - 1) + 'SL'
                        sign = -(1j**(l + m + 1))

                    k_mask = tw[src] != 0
                    el_mask = self._elements_mapped[src] | k_mask

                    if sum(k_mask) > 0:
                        # the next three lines determine the main order of speed, hence
                        # - mask as much as possible
                        # - additions are faster than multiplications (-> applymap last)
                        phx = dphi(phs_adv['X'].loc[k_mask, el_mask], tw.Q1)
                        phy = dphi(phs_adv['Y'].loc[k_mask, el_mask], tw.Q2)
                        phase_term = (
                            (j - k) * phx +
                            (l - m) * phy).applymap(lambda p: np.exp(i2pi * p))

                        beta_term = tw.loc[k_mask, src] * \
                                    tw.loc[k_mask, 'BETX'] ** ((j+k) / 2.) * \
                                    tw.loc[k_mask, 'BETY'] ** ((l+m) / 2.)

                        res.loc[el_mask,
                                rdt.upper()] = sign * phase_term.multiply(
                                    beta_term, axis="index").sum(
                                        axis=0).transpose() * denom

                        LOG.debug(
                            "  Average RDT amplitude |{:s}|: {:g}".format(
                                rdt,
                                np.mean(np.abs(res.loc[el_mask,
                                                       rdt.upper()]))))
                    else:
                        LOG.debug(
                            "  All {:s} == 0. RDT '{:s}' will be zero.".format(
                                src, rdt))
                        res.loc[el_mask, rdt.upper()] = 0

        self._log_added(*order)