========
Plotting
========

Requirements
------------
Plotting is enable as soon as a compatible matplotlib version is installed

+-------------------+-----------------------+
|   Python version  | Matplotlib version    |
+===================+=======================+
|   2.7             |  >= 2.1.2             |
+-------------------+-----------------------+
|   3.x             |  >= 3.0.0             |
+-------------------+-----------------------+

Usage
-----

* Plotting is performed by the generic function ``baseplot`` which takes care
  of of slicing the lattice into shorter elements inside the plot region,
  getting the data from a plot-specific function, and calling all necessary
  Matplotlib functions to generate the plot. ``baseplot`` is called as::

        axleft, axright, axsyn = baseplot(ring, plot_function, *args, **kwargs)

* Data generated by a user-defined specific function. This function is called
  by ``baseplot`` as::

        title, left[, right] = plot_function(ring, refpts, *args, **kwargs)

  with::

        ring        Lattice object
        refpts      Points where data is required
        *args       user-defined positional arguments
        **kwargs    user-defined keyword arguments

        title       Plot title or None
        left        Tuple returning the data for the main (left) axis
           left[0]  y-axis label
           left[1]  xdata: (N,) array (s coordinate)
           left[2]  ydata: iterable of (N,) or (N,M) arrays. Lines from a
                    (N, M) array share the same style and label
           left[3]  labels: (optional) iterable of strings as long as ydata

        right       tuple returning the data for the secondary (right) axis
                    (optional)

  This function is independent from any graphics module, so it can be located
  in any at sub-package.

Example
--------

Specific function for plotting beta-functions and dispersion::

    def pldata_beta_disp(ring, refpts, **kwargs):
        """Generates data for plotting beta functions and dispersion"""

        # compute linear optics at the required locations
        data0, _, _, data = linopt(ring, refpts=refpts, get_chrom=True, **kwargs)

        # Extract the plot data
        s_pos = data['s_pos']
        betax = data['beta'][:, 0]
        betaz = data['beta'][:, 1]
        dispersion = data['dispersion'][:, 0]

        # Left axis definition
        left = (r'$\beta$ [m]', s_pos, [betax, betaz],
                [r'$\beta_x$', r'$\beta_z$'])

        # Right axis definition
        right = ('dispersion [m]', s_pos, [dispersion], ['dispersion'])

        return 'Optical functions', left, right

Call sequence::

    axleft, axright, axsyn = baseplot(ring, pldata_beta_disp, dp=0.01)

