class LinePlot(AbstractDataPlotter): """ This class uses :mod:`trappy.plotter.Constraint.Constraint` to represent different permutations of input parameters. These constraints are generated by creating an instance of :mod:`trappy.plotter.Constraint.ConstraintManager`. :param run: The input data :type run: :mod:`trappy.run.Run` or :mod:`pandas.DataFrame`, list or single :param column: specifies the name of the column to be plotted. :type column: (str, list(str)) :param templates: TRAPpy events .. note:: This is not required if a :mod:`pandas.DataFrame` is used :type templates: :mod:`trappy.base.Base` :param filters: Filter the column to be plotted as per the specified criteria. For Example: :: filters = { "pid": [ 3338 ], "cpu": [0, 2, 4], } :type filters: dict :param per_line: Used to control the number of graphs in each graph subplot row :type per_line: int :param concat: Draw all the pivots on a single graph :type concat: bool :param fill: Fill the area under the plots :type fill: bool :param permute: Draw one plot for each of the runs specified :type permute: bool :param drawstyle: This argument is forwarded to the matplotlib corresponding :func:`matplotlib.pyplot.plot` call drawing style. .. note:: step plots are not currently supported for filled graphs :param xlim: A tuple representing the upper and lower xlimits :type xlim: tuple :param ylim: A tuple representing the upper and lower ylimits :type ylim: tuple :param style: Created pre-styled graphs loaded from :mod:`trappy.plotter.AttrConf.MPL_STYLE` :type style: bool """ def __init__(self, runs, templates=None, **kwargs): # Default keys, each can be overridden in kwargs self._attr = {} self.runs = runs self.templates = templates self.set_defaults() self._fig = None self._layout = None self._check_data() for key in kwargs: if key in AttrConf.ARGS_TO_FORWARD: self._attr["args_to_forward"][key] = kwargs[key] else: self._attr[key] = kwargs[key] if "column" not in self._attr: raise RuntimeError("Value Column not specified") zip_constraints = not self._attr["permute"] self.c_mgr = ConstraintManager(runs, self._attr["column"], templates, self._attr["pivot"], self._attr["filters"], zip_constraints) self._check_add_scatter() super(LinePlot, self).__init__() def savefig(self, *args, **kwargs): """Save the plot as a PNG fill. This calls into :mod:`matplotlib.figure.savefig` """ if self._fig == None: self.view() self._fig.savefig(*args, **kwargs) def view(self, test=False): """Displays the graph""" if test: self._attr["style"] = True AttrConf.MPL_STYLE["interactive"] = False if self._attr["concat"]: if self._attr["style"]: with plt.rc_context(AttrConf.MPL_STYLE): self._plot_concat() else: self._plot_concat() else: if self._attr["style"]: with plt.rc_context(AttrConf.MPL_STYLE): self._plot(self._attr["permute"]) else: self._plot(self._attr["permute"]) def set_defaults(self): """Sets the default attrs""" self._attr["width"] = AttrConf.WIDTH self._attr["length"] = AttrConf.LENGTH self._attr["per_line"] = AttrConf.PER_LINE self._attr["concat"] = AttrConf.CONCAT self._attr["fill"] = AttrConf.FILL self._attr["filters"] = {} self._attr["style"] = True self._attr["permute"] = False self._attr["pivot"] = AttrConf.PIVOT self._attr["xlim"] = AttrConf.XLIM self._attr["ylim"] = AttrConf.XLIM self._attr["args_to_forward"] = {} self._attr["scatter"] = AttrConf.PLOT_SCATTER def _check_add_scatter(self): """Check if a scatter plot is needed and augment the forwarded args accordingly""" if self._attr["scatter"]: self._attr["args_to_forward"]["linestyle"] = "" self._attr["args_to_forward"]["marker"] = "o" if "point_size" in self._attr: self._attr["args_to_forward"]["markersize"] = \ self._attr["point_size"] def _plot(self, permute): """Internal Method called to draw the plot""" pivot_vals, len_pivots = self.c_mgr.generate_pivots(permute) # Create a 2D Layout self._layout = PlotLayout(self._attr["per_line"], len_pivots, width=self._attr["width"], length=self._attr["length"]) self._fig = self._layout.get_fig() legend_str = [] plot_index = 0 if permute: legend = [None] * self.c_mgr._max_len cmap = ColorMap(self.c_mgr._max_len) else: legend = [None] * len(self.c_mgr) cmap = ColorMap(len(self.c_mgr)) for p_val in pivot_vals: l_index = 0 for constraint in self.c_mgr: if permute: run_idx, pivot = p_val if constraint.run_index != run_idx: continue legend_str.append(constraint._column) l_index = self.c_mgr.get_column_index(constraint) title = constraint.get_data_name() + ":" else: pivot = p_val legend_str.append(str(constraint)) title = "" result = constraint.result if pivot in result: axis = self._layout.get_axis(plot_index) line_2d_list = axis.plot(result[pivot].index, result[pivot].values, color=cmap.cmap(l_index), **self._attr["args_to_forward"]) if self._attr["fill"]: drawstyle = line_2d_list[0].get_drawstyle() # This has been fixed in upstream matplotlib if drawstyle.startswith("steps"): raise UserWarning( "matplotlib does not support fill for step plots" ) xdat, ydat = line_2d_list[0].get_data(orig=False) axis.fill_between(xdat, axis.get_ylim()[0], ydat, facecolor=cmap.cmap(l_index), alpha=AttrConf.ALPHA) legend[l_index] = line_2d_list[0] if self._attr["xlim"] != None: axis.set_xlim(self._attr["xlim"]) if self._attr["ylim"] != None: axis.set_ylim(self._attr["ylim"]) else: axis = self._layout.get_axis(plot_index) axis.plot([], [], **self._attr["args_to_forward"]) l_index += 1 if pivot == AttrConf.PIVOT_VAL: title += ",".join(self._attr["column"]) else: title += "{0}: {1}".format(self._attr["pivot"], pivot) axis.set_title(title) plot_index += 1 for l_idx, legend_line in enumerate(legend): if not legend_line: del legend[l_idx] del legend_str[l_idx] self._fig.legend(legend, legend_str) self._layout.finish(len_pivots) def _plot_concat(self): """Plot all lines on a single figure""" pivot_vals, len_pivots = self.c_mgr.generate_pivots() cmap = ColorMap(len_pivots) self._layout = PlotLayout(self._attr["per_line"], len(self.c_mgr), width=self._attr["width"], length=self._attr["length"]) self._fig = self._layout.get_fig() legend = [None] * len_pivots legend_str = [""] * len_pivots plot_index = 0 for constraint in self.c_mgr: result = constraint.result title = str(constraint) result = constraint.result pivot_index = 0 for pivot in pivot_vals: if pivot in result: axis = self._layout.get_axis(plot_index) line_2d_list = axis.plot(result[pivot].index, result[pivot].values, color=cmap.cmap(pivot_index), **self._attr["args_to_forward"]) if self._attr["xlim"] != None: axis.set_xlim(self._attr["xlim"]) if self._attr["ylim"] != None: axis.set_ylim(self._attr["ylim"]) legend[pivot_index] = line_2d_list[0] if self._attr["fill"]: drawstyle = line_2d_list[0].get_drawstyle() if drawstyle.startswith("steps"): # This has been fixed in upstream matplotlib raise UserWarning( "matplotlib does not support fill for step plots" ) xdat, ydat = line_2d_list[0].get_data(orig=False) axis.fill_between(xdat, axis.get_ylim()[0], ydat, facecolor=cmap.cmap(pivot_index), alpha=AttrConf.ALPHA) if pivot == AttrConf.PIVOT_VAL: legend_str[pivot_index] = self._attr["column"] else: legend_str[pivot_index] = "{0}: {1}".format( self._attr["pivot"], pivot) else: axis = self._layout.get_axis(plot_index) axis.plot([], [], color=cmap.cmap(pivot_index), **self._attr["args_to_forward"]) pivot_index += 1 plot_index += 1 self._fig.legend(legend, legend_str) plot_index = 0 for constraint in self.c_mgr: self._layout.get_axis(plot_index).set_title(str(constraint)) plot_index += 1 self._layout.finish(len(self.c_mgr))
class LinePlot(AbstractDataPlotter): """ This class uses :mod:`trappy.plotter.Constraint.Constraint` to represent different permutations of input parameters. These constraints are generated by creating an instance of :mod:`trappy.plotter.Constraint.ConstraintManager`. :param run: The input data :type run: :mod:`trappy.run.Run` or :mod:`pandas.DataFrame`, list or single :param column: specifies the name of the column to be plotted. :type column: (str, list(str)) :param templates: TRAPpy events .. note:: This is not required if a :mod:`pandas.DataFrame` is used :type templates: :mod:`trappy.base.Base` :param filters: Filter the column to be plotted as per the specified criteria. For Example: :: filters = { "pid": [ 3338 ], "cpu": [0, 2, 4], } :type filters: dict :param per_line: Used to control the number of graphs in each graph subplot row :type per_line: int :param concat: Draw all the pivots on a single graph :type concat: bool :param fill: Fill the area under the plots :type fill: bool :param permute: Draw one plot for each of the runs specified :type permute: bool :param drawstyle: This argument is forwarded to the matplotlib corresponding :func:`matplotlib.pyplot.plot` call drawing style. .. note:: step plots are not currently supported for filled graphs :param xlim: A tuple representing the upper and lower xlimits :type xlim: tuple :param ylim: A tuple representing the upper and lower ylimits :type ylim: tuple :param style: Created pre-styled graphs loaded from :mod:`trappy.plotter.AttrConf.MPL_STYLE` :type style: bool """ def __init__(self, runs, templates=None, **kwargs): # Default keys, each can be overridden in kwargs self._attr = {} self.runs = runs self.templates = templates self.set_defaults() self._fig = None self._layout = None self._check_data() for key in kwargs: if key in AttrConf.ARGS_TO_FORWARD: self._attr["args_to_forward"][key] = kwargs[key] else: self._attr[key] = kwargs[key] if "column" not in self._attr: raise RuntimeError("Value Column not specified") zip_constraints = not self._attr["permute"] self.c_mgr = ConstraintManager( runs, self._attr["column"], templates, self._attr["pivot"], self._attr["filters"], zip_constraints) self._check_add_scatter() super(LinePlot, self).__init__() def savefig(self, *args, **kwargs): """Save the plot as a PNG fill. This calls into :mod:`matplotlib.figure.savefig` """ if self._fig == None: self.view() self._fig.savefig(*args, **kwargs) def view(self, test=False): """Displays the graph""" if test: self._attr["style"] = True AttrConf.MPL_STYLE["interactive"] = False if self._attr["concat"]: if self._attr["style"]: with plt.rc_context(AttrConf.MPL_STYLE): self._plot_concat() else: self._plot_concat() else: if self._attr["style"]: with plt.rc_context(AttrConf.MPL_STYLE): self._plot(self._attr["permute"]) else: self._plot(self._attr["permute"]) def set_defaults(self): """Sets the default attrs""" self._attr["width"] = AttrConf.WIDTH self._attr["length"] = AttrConf.LENGTH self._attr["per_line"] = AttrConf.PER_LINE self._attr["concat"] = AttrConf.CONCAT self._attr["fill"] = AttrConf.FILL self._attr["filters"] = {} self._attr["style"] = True self._attr["permute"] = False self._attr["pivot"] = AttrConf.PIVOT self._attr["xlim"] = AttrConf.XLIM self._attr["ylim"] = AttrConf.XLIM self._attr["args_to_forward"] = {} self._attr["scatter"] = AttrConf.PLOT_SCATTER def _check_add_scatter(self): """Check if a scatter plot is needed and augment the forwarded args accordingly""" if self._attr["scatter"]: self._attr["args_to_forward"]["linestyle"] = "" self._attr["args_to_forward"]["marker"] = "o" if "point_size" in self._attr: self._attr["args_to_forward"]["markersize"] = \ self._attr["point_size"] def _plot(self, permute): """Internal Method called to draw the plot""" pivot_vals, len_pivots = self.c_mgr.generate_pivots(permute) # Create a 2D Layout self._layout = PlotLayout( self._attr["per_line"], len_pivots, width=self._attr["width"], length=self._attr["length"]) self._fig = self._layout.get_fig() legend_str = [] plot_index = 0 if permute: legend = [None] * self.c_mgr._max_len cmap = ColorMap(self.c_mgr._max_len) else: legend = [None] * len(self.c_mgr) cmap = ColorMap(len(self.c_mgr)) for p_val in pivot_vals: l_index = 0 for constraint in self.c_mgr: if permute: run_idx, pivot = p_val if constraint.run_index != run_idx: continue legend_str.append(constraint._column) l_index = self.c_mgr.get_column_index(constraint) title = constraint.get_data_name() + ":" else: pivot = p_val legend_str.append(str(constraint)) title = "" result = constraint.result if pivot in result: axis = self._layout.get_axis(plot_index) line_2d_list = axis.plot( result[pivot].index, result[pivot].values, color=cmap.cmap(l_index), **self._attr["args_to_forward"]) if self._attr["fill"]: drawstyle = line_2d_list[0].get_drawstyle() # This has been fixed in upstream matplotlib if drawstyle.startswith("steps"): raise UserWarning("matplotlib does not support fill for step plots") xdat, ydat = line_2d_list[0].get_data(orig=False) axis.fill_between(xdat, axis.get_ylim()[0], ydat, facecolor=cmap.cmap(l_index), alpha=AttrConf.ALPHA) legend[l_index] = line_2d_list[0] if self._attr["xlim"] != None: axis.set_xlim(self._attr["xlim"]) if self._attr["ylim"] != None: axis.set_ylim(self._attr["ylim"]) else: axis = self._layout.get_axis(plot_index) axis.plot([], [], **self._attr["args_to_forward"]) l_index += 1 if pivot == AttrConf.PIVOT_VAL: title += ",".join(self._attr["column"]) else: title += "{0}: {1}".format(self._attr["pivot"], pivot) axis.set_title(title) plot_index += 1 for l_idx, legend_line in enumerate(legend): if not legend_line: del legend[l_idx] del legend_str[l_idx] self._fig.legend(legend, legend_str) self._layout.finish(len_pivots) def _plot_concat(self): """Plot all lines on a single figure""" pivot_vals, len_pivots = self.c_mgr.generate_pivots() cmap = ColorMap(len_pivots) self._layout = PlotLayout(self._attr["per_line"], len(self.c_mgr), width=self._attr["width"], length=self._attr["length"]) self._fig = self._layout.get_fig() legend = [None] * len_pivots legend_str = [""] * len_pivots plot_index = 0 for constraint in self.c_mgr: result = constraint.result title = str(constraint) result = constraint.result pivot_index = 0 for pivot in pivot_vals: if pivot in result: axis = self._layout.get_axis(plot_index) line_2d_list = axis.plot( result[pivot].index, result[pivot].values, color=cmap.cmap(pivot_index), **self._attr["args_to_forward"]) if self._attr["xlim"] != None: axis.set_xlim(self._attr["xlim"]) if self._attr["ylim"] != None: axis.set_ylim(self._attr["ylim"]) legend[pivot_index] = line_2d_list[0] if self._attr["fill"]: drawstyle = line_2d_list[0].get_drawstyle() if drawstyle.startswith("steps"): # This has been fixed in upstream matplotlib raise UserWarning("matplotlib does not support fill for step plots") xdat, ydat = line_2d_list[0].get_data(orig=False) axis.fill_between(xdat, axis.get_ylim()[0], ydat, facecolor=cmap.cmap(pivot_index), alpha=AttrConf.ALPHA) if pivot == AttrConf.PIVOT_VAL: legend_str[pivot_index] = self._attr["column"] else: legend_str[pivot_index] = "{0}: {1}".format(self._attr["pivot"], pivot) else: axis = self._layout.get_axis(plot_index) axis.plot( [], [], color=cmap.cmap(pivot_index), **self._attr["args_to_forward"]) pivot_index += 1 plot_index += 1 self._fig.legend(legend, legend_str) plot_index = 0 for constraint in self.c_mgr: self._layout.get_axis(plot_index).set_title(str(constraint)) plot_index += 1 self._layout.finish(len(self.c_mgr))
class LinePlot(AbstractDataPlotter): """The plots are plotted by default against the dataframe index The column="col_name" specifies the name of the column to be plotted filters = { "pid": [ 3338 ], "cpu": [0, 2, 4], } The above filters will filter the column to be plotted as per the specified criteria. per_line input is used to control the number of graphs in each graph subplot row concat, Draws all the graphs on a single plot permute, draws one plot for each of the runs specified """ def __init__(self, runs, templates=None, **kwargs): # Default keys, each can be overridden in kwargs self._attr = {} self.runs = runs self.templates = templates self.set_defaults() self._fig = None self._layout = None self._check_data() for key in kwargs: if key in AttrConf.ARGS_TO_FORWARD: self._attr["args_to_forward"][key] = kwargs[key] else: self._attr[key] = kwargs[key] if "column" not in self._attr: raise RuntimeError("Value Column not specified") zip_constraints = not self._attr["permute"] self.c_mgr = ConstraintManager(runs, self._attr["column"], templates, self._attr["pivot"], self._attr["filters"], zip_constraints) super(LinePlot, self).__init__() def savefig(self, *args, **kwargs): if self._fig == None: self.view() self._fig.savefig(*args, **kwargs) def view(self, test=False): """Displays the graph""" if test: self._attr["style"] = True AttrConf.MPL_STYLE["interactive"] = False if self._attr["concat"]: if self._attr["style"]: with plt.rc_context(AttrConf.MPL_STYLE): self._plot_concat() else: self._plot_concat() else: if self._attr["style"]: with plt.rc_context(AttrConf.MPL_STYLE): self._plot(self._attr["permute"]) else: self._plot(self._attr["permute"]) def set_defaults(self): """Sets the default attrs""" self._attr["width"] = AttrConf.WIDTH self._attr["length"] = AttrConf.LENGTH self._attr["per_line"] = AttrConf.PER_LINE self._attr["concat"] = AttrConf.CONCAT self._attr["fill"] = AttrConf.FILL self._attr["filters"] = {} self._attr["style"] = True self._attr["permute"] = False self._attr["pivot"] = AttrConf.PIVOT self._attr["xlim"] = AttrConf.XLIM self._attr["ylim"] = AttrConf.XLIM self._attr["args_to_forward"] = {} def _plot(self, permute): """Internal Method called to draw the plot""" pivot_vals, len_pivots = self.c_mgr.generate_pivots(permute) # Create a 2D Layout self._layout = PlotLayout(self._attr["per_line"], len_pivots, width=self._attr["width"], length=self._attr["length"]) self._fig = self._layout.get_fig() legend_str = [] plot_index = 0 if permute: legend = [None] * self.c_mgr._max_len cmap = ColorMap(self.c_mgr._max_len) else: legend = [None] * len(self.c_mgr) cmap = ColorMap(len(self.c_mgr)) for p_val in pivot_vals: l_index = 0 for constraint in self.c_mgr: if permute: run_idx, pivot = p_val if constraint.run_index != run_idx: continue legend_str.append(constraint._column) l_index = self.c_mgr.get_column_index(constraint) title = constraint.get_data_name() + ":" else: pivot = p_val legend_str.append(str(constraint)) title = "" result = constraint.result if pivot in result: axis = self._layout.get_axis(plot_index) line_2d_list = axis.plot(result[pivot].index, result[pivot].values, color=cmap.cmap(l_index), **self._attr["args_to_forward"]) if self._attr["fill"]: drawstyle = line_2d_list[0].get_drawstyle() # This has been fixed in upstream matplotlib if drawstyle.startswith("steps"): raise UserWarning( "matplotlib does not support fill for step plots" ) xdat, ydat = line_2d_list[0].get_data(orig=False) axis.fill_between(xdat, axis.get_ylim()[0], ydat, facecolor=cmap.cmap(l_index), alpha=AttrConf.ALPHA) legend[l_index] = line_2d_list[0] if self._attr["xlim"] != None: axis.set_xlim(self._attr["xlim"]) if self._attr["ylim"] != None: axis.set_ylim(self._attr["ylim"]) else: axis = self._layout.get_axis(plot_index) axis.plot([], [], **self._attr["args_to_forward"]) l_index += 1 if pivot == AttrConf.PIVOT_VAL: title += ",".join(self._attr["column"]) else: title += "{0}: {1}".format(self._attr["pivot"], pivot) axis.set_title(title) plot_index += 1 for l_idx, legend_line in enumerate(legend): if not legend_line: del legend[l_idx] del legend_str[l_idx] self._fig.legend(legend, legend_str) self._layout.finish(len_pivots) def _plot_concat(self): """Plot all lines on a single figure""" pivot_vals, len_pivots = self.c_mgr.generate_pivots() cmap = ColorMap(len_pivots) self._layout = PlotLayout(self._attr["per_line"], len(self.c_mgr), width=self._attr["width"], length=self._attr["length"]) self._fig = self._layout.get_fig() legend = [None] * len_pivots legend_str = [""] * len_pivots plot_index = 0 for constraint in self.c_mgr: result = constraint.result title = str(constraint) result = constraint.result pivot_index = 0 for pivot in pivot_vals: if pivot in result: axis = self._layout.get_axis(plot_index) line_2d_list = axis.plot(result[pivot].index, result[pivot].values, color=cmap.cmap(pivot_index), **self._attr["args_to_forward"]) if self._attr["xlim"] != None: axis.set_xlim(self._attr["xlim"]) if self._attr["ylim"] != None: axis.set_ylim(self._attr["ylim"]) legend[pivot_index] = line_2d_list[0] if self._attr["fill"]: drawstyle = line_2d_list[0].get_drawstyle() if drawstyle.startswith("steps"): # This has been fixed in upstream matplotlib raise UserWarning( "matplotlib does not support fill for step plots" ) xdat, ydat = line_2d_list[0].get_data(orig=False) axis.fill_between(xdat, axis.get_ylim()[0], ydat, facecolor=cmap.cmap(pivot_index), alpha=AttrConf.ALPHA) if pivot == AttrConf.PIVOT_VAL: legend_str[pivot_index] = self._attr["column"] else: legend_str[pivot_index] = "{0}: {1}".format( self._attr["pivot"], pivot) else: axis = self._layout.get_axis(plot_index) axis.plot([], [], color=cmap.cmap(pivot_index), **self._attr["args_to_forward"]) pivot_index += 1 plot_index += 1 self._fig.legend(legend, legend_str) plot_index = 0 for constraint in self.c_mgr: self._layout.get_axis(plot_index).set_title(str(constraint)) plot_index += 1 self._layout.finish(len(self.c_mgr))