"""
Module online_model.extractor_wrapper
---------------------------------------
Python wrapper to use the online model extractor with some conversion functionality.
.. warning::
    Needs to be run from the technical network or using a cwd with server and local access.
"""
import os
import subprocess
import online_model.constants as const
import online_model.data_converter as dc
from tfs_files import tfs_pandas as tfs
from utils import logging_tools
from plotshop.plot_tfs import plot
LOG = logging_tools.get_logger(__name__)
[docs]def extract_knob_value_and_definition(knob_names, time, cwd="./", server=None):
    """ Extract knob values from online model using the knob name and the time.
    Example Call::
        extract_knob_values("LHCBEAM/2018_global_ats_flat_b1_for_ip5_waist",
                            "2018-10-30 15:00:00.0",
                            cwd="/afs/cern.ch/user/j/jdilly/extractor/",
                            server="cs-ccr-dev3")
    Args:
        knob_names (list): List of knob names to extract
        time: UTC time in ISOformat to extract
        cwd: output directory for results and log (default: current directory)
        server: server to run on (default: runs local)
    """
    knob_file = os.path.join(cwd, const.get_extractor_knobs_filename())
    # first get the trim value and madx_changefile
    _run_knob_extraction(knob_names, time, cwd, server, "trim")
    if not os.path.exists(knob_file):
        raise IOError("Something went wrong while extracting data form online model. See log file.")
    trim, _ = dc.post_trim_extract(knob_file)
    # run again and get the values and deltas
    _run_knob_extraction(knob_names, time, cwd, server, "k")
    df_list = dc.knobs_k_to_tfs(knob_file, trim)
    for knob, df in zip(knob_names, df_list):
        filename = const.get_knob_tfs_filename(knob)
        tfs.write_tfs(os.path.join(cwd, filename), df) 
# Private Functions ############################################################
# Build command
def _run_knob_extraction(knob_names, time, cwd, server, ktype):
    cmd = " ".join([const.get_om_extractor(),
                    "-time", '"{:s}"'.format(dc.convert_utc_time_to_local(time)),
                    "-Knames", '"{:s}"'.format(",".join(knob_names)),
                    "-Ktype", const.get_ktype(ktype)])
    _run_command(cmd, server, cwd)
def _run_overview_extraction(knob_names, time, cwd, server):
    cmd = " ".join([const.get_om_extractor(),
                    "-e",  # extract optics
                    "-oe",  # extract orbit
                    "-time", '"{:s}"'.format(dc.convert_utc_time_to_local(time)),
                    "-Knames", '"{:s}"'.format(",".join(knob_names)),
                    "-Ktype", const.get_ktype("trim")])
    _run_command(cmd, server, cwd)
def _run_for_log(time, cwd, server):
    cmd = " ".join([const.get_om_extractor(),
                    "-time", '"{:s}"'.format(dc.convert_utc_time_to_local(time)),
                    "-oe",  # extract orbit
                    "-Knames", "dummy",  # makes it crash, but knobs will be in logs
                    "-Ktype", const.get_ktype("trim")
                    ])
    _run_command(cmd, server, cwd)
# Run command
def _run_command(cmd, server, cwd):
    if server:
        cmd = "ssh -t -X -o 'StrictHostKeyChecking no' {:s} 'cd {:s} ; {:s}'".format(
            server, cwd, cmd)
    LOG.debug("Running command:\n{}".format(cmd))
    process = subprocess.Popen(cmd, shell=True, cwd=cwd)
    process.wait()
# Output
def _log_df(df):
    LOG.debug("Extracted data summary:")
    s = "{:<20s}: {:s}"
    k = "  {:<30s} = {:g}"
    with logging_tools.unformatted_console_logging():
        LOG.info("")
        LOG.info(s.format("Time (UTC)", df.headers[const.get_time_header()]))
        LOG.info(s.format("Beamprocess", df.headers[const.get_beamprocess_header()]))
        LOG.info(s.format("Optics", df.headers[const.get_optics_header()]))
        LOG.info(s.format("Fill", str(df.headers[const.get_fill_header()])))
        LOG.info(s.format("Trims", ""))
        for idx in df.index:
            LOG.info(k.format(*df.loc[idx, :].values))
        LOG.info("")
def _plot_orbits(cwd, show_plot):
    beams = [1, 2]
    filenames = [os.path.join(cwd, const.get_default_orbit_filename(b)) for b in beams]
    output = os.path.splitext(filenames[0])[0]
    file_labels = ["Beam {:d}".format(b) for b in beams]
    plot(files=filenames,
         y_cols=["X", "Y"],
         y_labels=["Orbit [m]"] * 2,
         file_labels=file_labels,
         figure_per_file=True,
         output=output,
         no_show=not show_plot,
         )