Source code for trappy.plotter.PlotLayout

#    Copyright 2015-2016 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""This module implements functionality related to
the arrangement of the plots on the underlying
plotting backend.
"""

import matplotlib.pyplot as plt
from trappy.plotter import AttrConf


[docs]class PlotLayout(object): """ :param cols: The number of columns to draw :type cols: int :param num_plots: The total number of plots :type num_plots: int The linear co-ordinate system :math:`[0, N_{plots}]` is mapped to a 2-D coordinate system with math:`N_{rows}` and :math:`N_{cols}` such that: .. math:: N_{rows} = \\frac{N_{cols}}{N_{plots}} """ def __init__(self, cols, num_plots, **kwargs): self.cols = cols self._attr = {} self.num_plots = num_plots self._single_plot = False if self.num_plots == 0: raise RuntimeError("No plots for the given constraints") if self.num_plots < self.cols: self.cols = self.num_plots self.rows = (self.num_plots / self.cols) # Avoid Extra Allocation (shows up in savefig!) if self.num_plots % self.cols != 0: self.rows += 1 self.usecol = False self.userow = False self._set_defaults() for key in kwargs: self._attr[key] = kwargs[key] # Scale the plots if there is a single plot and # Set boolean variables if num_plots == 1: self._single_plot = True self._scale_plot() elif self.rows == 1: self.usecol = True elif self.cols == 1: self.userow = True self._scale_plot() self._attr["figure"], self._attr["axes"] = plt.subplots( self.rows, self.cols, figsize=( self._attr["width"] * self.cols, self._attr["length"] * self.rows)) if self._attr['title']: self._attr["figure"].suptitle( self._attr['title'], fontsize=AttrConf.TITLE_SIZE, horizontalalignment='center') def _scale_plot(self): """Scale the graph in one plot per line use case""" self._attr["width"] = int(self._attr["width"] * 2.5) self._attr["length"] = int(self._attr["length"] * 1.25) def _set_defaults(self): """set the default attrs""" self._attr["width"] = AttrConf.WIDTH self._attr["length"] = AttrConf.LENGTH
[docs] def get_2d(self, linear_val): """Convert Linear to 2D coordinates :param linear_val: The value in 1-D co-ordinate :type linear_val: int :return: Converted 2-D tuple """ if self.usecol: return linear_val % self.cols if self.userow: return linear_val % self.rows val_x = linear_val % self.cols val_y = linear_val / self.cols return val_y, val_x
[docs] def finish(self, plot_index): """Delete the empty cells :param plot_index: Linear index at which the last plot was created. This is used to delete the leftover empty plots that were generated. :type plot_index: int """ while plot_index < (self.rows * self.cols): self._attr["figure"].delaxes( self._attr["axes"][ self.get_2d(plot_index)]) plot_index += 1
[docs] def get_axis(self, plot_index): """Get the axes for the plots :param plot_index: The index for which the axis is required. This internally is mapped to a 2-D co-ordinate :return: :mod:`matplotlib.axes.Axes` instance is returned """ if self._single_plot: return self._attr["axes"] else: return self._attr["axes"][self.get_2d(plot_index)]
[docs] def get_fig(self): """Return the matplotlib figure object :return: :mod:`matplotlib.figure` """ return self._attr["figure"]