Source code for plot_array_layout

#!/usr/bin/python3

"""
Plot array elements (array layouts).

Plot array layouts in ground or UTM coordinate systems from multiple sources.

For the following options, array element positions are retrieved from the model parameter database:

* from the model parameter database using the layout name (e.g., ``-array_layout_name alpha``)

* from the model parameter data, retrieving all layouts for the given site and model version
  (``--plot_all_layouts``)

* from a model parameter file
  (e.g., ``-array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.1.json``)

* from a list of array elements (e.g., ``-array_element_list MSTN-01, MSTN-02``).
  Positions are retrieved from the database.
  * explicit listing: e.g., ``-array_element_list MSTN-01, MSTN05``
  * listing of types: e.g, ``-array_element_list MSTN`` plots all telescopes of type MSTN.

For this option, array element positions are retrieved from the input file:

* from a file containing an astropy table with a list of array elements and their positions
  (e.g., ``-array_layout_file tests/resources/telescope_positions-North-ground.ecsv``)

Plots are saved as pdf and png files in the output directory.

Example of a layout plot:

.. _plot_array_layout_plot:
.. image:: images/plot_array_layout_example.png
    :width: 49 %

Command line arguments
----------------------
figure_name : str
    File name for the output figure.
array_layout_file : str
    File (astropy table compatible) with a list of array elements.
array_layout_name : str
    Name of the layout array (e.g., test_layout, alpha, 4mst, etc.).
    Use 'plot_all' to plot all layouts from the database for the given site and model version.
array_layout_parameter_file : str, optional
    File with array layouts similar in the model parameter file format (typically JSON).
array_layout_name_background: str, optional
    Name of the background layout array (e.g., test_layout, alpha, 4mst, etc.).
array_element_list : list
    List of array elements (e.g., telescopes) to plot (e.g., ``LSTN-01 LSTN-02 MSTN``).
coordinate_system : str, optional
    Coordinate system for the array layout (ground or utm).
show_labels : bool, optional
    Shows the telescope labels in the plot.
axes_range : float, optional
    Range of the both axes in meters.
marker_scaling : float, optional.
    Scaling factor for plotting of array elements, optional.

Examples
--------
Plot "alpha" layout for the North site with model version 6.0.0:

.. code-block:: console

    simtools-plot-array-layout --site North
                               --array_layout_name alpha
                               --model_version=6.0.0

Plot layout with 2 LSTs on top of north alpha layout:

.. code-block:: console

    simtools-plot-array-layout --site North
                               --array_element_list LSTN-01,LSTN-02
                               --model_version=6.0.0
                               --array_layout_name_background alpha

Plot layout from a file with a list of telescopes:

.. code-block:: console

    simtools-plot-array-layout
        --array_layout_file tests/resources/telescope_positions-North-ground.ecsv

Plot layout from a parameter file with a list of telescopes:

.. code-block:: console

    simtools-plot-array-layout
        --array_layout_parameter_file tests/resources/model_parameters/array_layouts-2.0.1.json
        --model_version 6.0.0


Plot all layouts for the North site and model version 6.0.0:

.. code-block:: console

    simtools-plot-array-layout --site North --plot_all_layouts --model_version=6.0.0
"""

import logging
from pathlib import Path

import matplotlib as mpl
import matplotlib.pyplot as plt

import simtools.layout.array_layout_utils as layout_utils
import simtools.utils.general as gen
from simtools.configuration import configurator
from simtools.io_operations import io_handler
from simtools.visualization import visualize
from simtools.visualization.plot_array_layout import plot_array_layout


def _parse(label, description, usage=None):
    """
    Parse command line configuration.

    Parameters
    ----------
    label : str
        Label describing the application.
    description : str
        Description of the application.
    usage : str
        Example on how to use the application.

    Returns
    -------
    CommandLineParser
        Command line parser object.
    """
    config = configurator.Configurator(label=label, description=description, usage=usage)

    config.parser.add_argument(
        "--figure_name",
        help="Name of the output figure to be saved into as a pdf.",
        type=str,
        required=False,
        default=None,
    )
    config.parser.add_argument(
        "--show_labels",
        help="Plot array element labels.",
        action="store_true",
        required=False,
        default=False,
    )
    config.parser.add_argument(
        "--marker_scaling",
        help="Scaling factor for the markers.",
        type=float,
        required=False,
        default=1.0,
    )
    config.parser.add_argument(
        "--coordinate_system",
        help="Coordinate system for the array layout.",
        type=str,
        required=False,
        default="ground",
        choices=["ground", "utm"],
    )
    config.parser.add_argument(
        "--axes_range",
        help="Range of the both axes in meters.",
        type=float,
        required=False,
        default=None,
    )
    config.parser.add_argument(
        "--array_layout_name_background",
        help="Name of the background layout array (e.g., test_layout, alpha, 4mst, etc.).",
        type=str,
        required=False,
        default=None,
    )
    return config.initialize(
        db_config=True,
        simulation_model=[
            "site",
            "model_version",
            "layout",
            "layout_file",
            "plot_all_layouts",
            "layout_parameter_file",
        ],
    )


[docs] def read_layouts(args_dict, db_config, logger): """ Read array layouts from the database or parameter file. Parameters ---------- args_dict : dict Dictionary with command line arguments. db_config : dict Database configuration. logger : logging.Logger Logger instance. Returns ------- list List of array layouts. """ if args_dict["array_layout_name"] is not None or args_dict["plot_all_layouts"]: logger.info("Plotting array from DB using layout array name(s).") layouts = layout_utils.get_array_layouts_from_db( args_dict["array_layout_name"], args_dict["site"], args_dict["model_version"], db_config, args_dict["coordinate_system"], ) if isinstance(layouts, list): return layouts return [layouts] if args_dict["array_layout_parameter_file"] is not None: logger.info("Plotting array from parameter file(s).") return layout_utils.get_array_layouts_from_parameter_file( args_dict["array_layout_parameter_file"], args_dict["model_version"], db_config, args_dict["coordinate_system"], ) if args_dict["array_layout_file"] is not None: logger.info("Plotting array from telescope table file(s).") return layout_utils.get_array_layouts_from_file(args_dict["array_layout_file"]) if args_dict["array_element_list"] is not None: logger.info("Plotting array from list of array elements.") return layout_utils.get_array_layouts_using_telescope_lists_from_db( [args_dict["array_element_list"]], args_dict["site"], args_dict["model_version"], db_config, args_dict["coordinate_system"], ) return []
[docs] def main(): """Plot array layout application.""" label = Path(__file__).stem args_dict, db_config = _parse( label, ( "Plots array layout." "Use '--array_layout_name plot_all' to plot all layouts for the given site " "and model version." ), ) logger = logging.getLogger() logger.setLevel(gen.get_log_level_from_user(args_dict["log_level"])) io_handler_instance = io_handler.IOHandler() layouts = read_layouts(args_dict, db_config, logger) if args_dict.get("array_layout_name_background"): background_layout = layout_utils.get_array_layouts_from_db( args_dict["array_layout_name_background"], args_dict["site"], args_dict["model_version"], db_config, args_dict["coordinate_system"], )["array_elements"] else: background_layout = None mpl.use("Agg") for layout in layouts: fig_out = plot_array_layout( telescopes=layout["array_elements"], show_tel_label=args_dict["show_labels"], axes_range=args_dict["axes_range"], marker_scaling=args_dict["marker_scaling"], background_telescopes=background_layout, ) site_string = "" if layout.get("site") is not None: site_string = f"_{layout['site']}" elif args_dict["site"] is not None: site_string = f"_{args_dict['site']}" coordinate_system_string = ( f"_{args_dict['coordinate_system']}" if args_dict["coordinate_system"] not in layout["name"] else "" ) plot_file_name = args_dict["figure_name"] or ( f"array_layout_{layout['name']}{site_string}{coordinate_system_string}" ) visualize.save_figure( fig_out, io_handler_instance.get_output_directory(label, sub_dir="application-plots") / plot_file_name, dpi=400, ) plt.close()
if __name__ == "__main__": main()