summaryrefslogtreecommitdiffstats
path: root/contrib/python/matplotlib/py3/matplotlib/table.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/python/matplotlib/py3/matplotlib/table.py')
-rw-r--r--contrib/python/matplotlib/py3/matplotlib/table.py831
1 files changed, 831 insertions, 0 deletions
diff --git a/contrib/python/matplotlib/py3/matplotlib/table.py b/contrib/python/matplotlib/py3/matplotlib/table.py
new file mode 100644
index 00000000000..d42cdf878d6
--- /dev/null
+++ b/contrib/python/matplotlib/py3/matplotlib/table.py
@@ -0,0 +1,831 @@
+# Original code by:
+# John Gill <[email protected]>
+# Copyright 2004 John Gill and John Hunter
+#
+# Subsequent changes:
+# The Matplotlib development team
+# Copyright The Matplotlib development team
+
+"""
+Tables drawing.
+
+.. note::
+ The table implementation in Matplotlib is lightly maintained. For a more
+ featureful table implementation, you may wish to try `blume
+ <https://github.com/swfiua/blume>`_.
+
+Use the factory function `~matplotlib.table.table` to create a ready-made
+table from texts. If you need more control, use the `.Table` class and its
+methods.
+
+The table consists of a grid of cells, which are indexed by (row, column).
+The cell (0, 0) is positioned at the top left.
+
+Thanks to John Gill for providing the class and table.
+"""
+
+import numpy as np
+
+from . import _api, _docstring
+from .artist import Artist, allow_rasterization
+from .patches import Rectangle
+from .text import Text
+from .transforms import Bbox
+from .path import Path
+
+
+class Cell(Rectangle):
+ """
+ A cell is a `.Rectangle` with some associated `.Text`.
+
+ As a user, you'll most likely not creates cells yourself. Instead, you
+ should use either the `~matplotlib.table.table` factory function or
+ `.Table.add_cell`.
+ """
+
+ PAD = 0.1
+ """Padding between text and rectangle."""
+
+ _edges = 'BRTL'
+ _edge_aliases = {'open': '',
+ 'closed': _edges, # default
+ 'horizontal': 'BT',
+ 'vertical': 'RL'
+ }
+
+ def __init__(self, xy, width, height, *,
+ edgecolor='k', facecolor='w',
+ fill=True,
+ text='',
+ loc=None,
+ fontproperties=None,
+ visible_edges='closed',
+ ):
+ """
+ Parameters
+ ----------
+ xy : 2-tuple
+ The position of the bottom left corner of the cell.
+ width : float
+ The cell width.
+ height : float
+ The cell height.
+ edgecolor : color
+ The color of the cell border.
+ facecolor : color
+ The cell facecolor.
+ fill : bool
+ Whether the cell background is filled.
+ text : str
+ The cell text.
+ loc : {'left', 'center', 'right'}, default: 'right'
+ The alignment of the text within the cell.
+ fontproperties : dict
+ A dict defining the font properties of the text. Supported keys and
+ values are the keyword arguments accepted by `.FontProperties`.
+ visible_edges : str, default: 'closed'
+ The cell edges to be drawn with a line: a substring of 'BRTL'
+ (bottom, right, top, left), or one of 'open' (no edges drawn),
+ 'closed' (all edges drawn), 'horizontal' (bottom and top),
+ 'vertical' (right and left).
+ """
+
+ # Call base
+ super().__init__(xy, width=width, height=height, fill=fill,
+ edgecolor=edgecolor, facecolor=facecolor)
+ self.set_clip_on(False)
+ self.visible_edges = visible_edges
+
+ # Create text object
+ if loc is None:
+ loc = 'right'
+ self._loc = loc
+ self._text = Text(x=xy[0], y=xy[1], clip_on=False,
+ text=text, fontproperties=fontproperties,
+ horizontalalignment=loc, verticalalignment='center')
+
+ @_api.rename_parameter("3.8", "trans", "t")
+ def set_transform(self, t):
+ super().set_transform(t)
+ # the text does not get the transform!
+ self.stale = True
+
+ def set_figure(self, fig):
+ super().set_figure(fig)
+ self._text.set_figure(fig)
+
+ def get_text(self):
+ """Return the cell `.Text` instance."""
+ return self._text
+
+ def set_fontsize(self, size):
+ """Set the text fontsize."""
+ self._text.set_fontsize(size)
+ self.stale = True
+
+ def get_fontsize(self):
+ """Return the cell fontsize."""
+ return self._text.get_fontsize()
+
+ def auto_set_font_size(self, renderer):
+ """Shrink font size until the text fits into the cell width."""
+ fontsize = self.get_fontsize()
+ required = self.get_required_width(renderer)
+ while fontsize > 1 and required > self.get_width():
+ fontsize -= 1
+ self.set_fontsize(fontsize)
+ required = self.get_required_width(renderer)
+
+ return fontsize
+
+ @allow_rasterization
+ def draw(self, renderer):
+ if not self.get_visible():
+ return
+ # draw the rectangle
+ super().draw(renderer)
+ # position the text
+ self._set_text_position(renderer)
+ self._text.draw(renderer)
+ self.stale = False
+
+ def _set_text_position(self, renderer):
+ """Set text up so it is drawn in the right place."""
+ bbox = self.get_window_extent(renderer)
+ # center vertically
+ y = bbox.y0 + bbox.height / 2
+ # position horizontally
+ loc = self._text.get_horizontalalignment()
+ if loc == 'center':
+ x = bbox.x0 + bbox.width / 2
+ elif loc == 'left':
+ x = bbox.x0 + bbox.width * self.PAD
+ else: # right.
+ x = bbox.x0 + bbox.width * (1 - self.PAD)
+ self._text.set_position((x, y))
+
+ def get_text_bounds(self, renderer):
+ """
+ Return the text bounds as *(x, y, width, height)* in table coordinates.
+ """
+ return (self._text.get_window_extent(renderer)
+ .transformed(self.get_data_transform().inverted())
+ .bounds)
+
+ def get_required_width(self, renderer):
+ """Return the minimal required width for the cell."""
+ l, b, w, h = self.get_text_bounds(renderer)
+ return w * (1.0 + (2.0 * self.PAD))
+
+ @_docstring.dedent_interpd
+ def set_text_props(self, **kwargs):
+ """
+ Update the text properties.
+
+ Valid keyword arguments are:
+
+ %(Text:kwdoc)s
+ """
+ self._text._internal_update(kwargs)
+ self.stale = True
+
+ @property
+ def visible_edges(self):
+ """
+ The cell edges to be drawn with a line.
+
+ Reading this property returns a substring of 'BRTL' (bottom, right,
+ top, left').
+
+ When setting this property, you can use a substring of 'BRTL' or one
+ of {'open', 'closed', 'horizontal', 'vertical'}.
+ """
+ return self._visible_edges
+
+ @visible_edges.setter
+ def visible_edges(self, value):
+ if value is None:
+ self._visible_edges = self._edges
+ elif value in self._edge_aliases:
+ self._visible_edges = self._edge_aliases[value]
+ else:
+ if any(edge not in self._edges for edge in value):
+ raise ValueError('Invalid edge param {}, must only be one of '
+ '{} or string of {}'.format(
+ value,
+ ", ".join(self._edge_aliases),
+ ", ".join(self._edges)))
+ self._visible_edges = value
+ self.stale = True
+
+ def get_path(self):
+ """Return a `.Path` for the `.visible_edges`."""
+ codes = [Path.MOVETO]
+ codes.extend(
+ Path.LINETO if edge in self._visible_edges else Path.MOVETO
+ for edge in self._edges)
+ if Path.MOVETO not in codes[1:]: # All sides are visible
+ codes[-1] = Path.CLOSEPOLY
+ return Path(
+ [[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]],
+ codes,
+ readonly=True
+ )
+
+
+CustomCell = Cell # Backcompat. alias.
+
+
+class Table(Artist):
+ """
+ A table of cells.
+
+ The table consists of a grid of cells, which are indexed by (row, column).
+
+ For a simple table, you'll have a full grid of cells with indices from
+ (0, 0) to (num_rows-1, num_cols-1), in which the cell (0, 0) is positioned
+ at the top left. However, you can also add cells with negative indices.
+ You don't have to add a cell to every grid position, so you can create
+ tables that have holes.
+
+ *Note*: You'll usually not create an empty table from scratch. Instead use
+ `~matplotlib.table.table` to create a table from data.
+ """
+ codes = {'best': 0,
+ 'upper right': 1, # default
+ 'upper left': 2,
+ 'lower left': 3,
+ 'lower right': 4,
+ 'center left': 5,
+ 'center right': 6,
+ 'lower center': 7,
+ 'upper center': 8,
+ 'center': 9,
+ 'top right': 10,
+ 'top left': 11,
+ 'bottom left': 12,
+ 'bottom right': 13,
+ 'right': 14,
+ 'left': 15,
+ 'top': 16,
+ 'bottom': 17,
+ }
+ """Possible values where to place the table relative to the Axes."""
+
+ FONTSIZE = 10
+
+ AXESPAD = 0.02
+ """The border between the Axes and the table edge in Axes units."""
+
+ def __init__(self, ax, loc=None, bbox=None, **kwargs):
+ """
+ Parameters
+ ----------
+ ax : `~matplotlib.axes.Axes`
+ The `~.axes.Axes` to plot the table into.
+ loc : str
+ The position of the cell with respect to *ax*. This must be one of
+ the `~.Table.codes`.
+ bbox : `.Bbox` or [xmin, ymin, width, height], optional
+ A bounding box to draw the table into. If this is not *None*, this
+ overrides *loc*.
+
+ Other Parameters
+ ----------------
+ **kwargs
+ `.Artist` properties.
+ """
+
+ super().__init__()
+
+ if isinstance(loc, str):
+ if loc not in self.codes:
+ raise ValueError(
+ "Unrecognized location {!r}. Valid locations are\n\t{}"
+ .format(loc, '\n\t'.join(self.codes)))
+ loc = self.codes[loc]
+ self.set_figure(ax.figure)
+ self._axes = ax
+ self._loc = loc
+ self._bbox = bbox
+
+ # use axes coords
+ ax._unstale_viewLim()
+ self.set_transform(ax.transAxes)
+
+ self._cells = {}
+ self._edges = None
+ self._autoColumns = []
+ self._autoFontsize = True
+ self._internal_update(kwargs)
+
+ self.set_clip_on(False)
+
+ def add_cell(self, row, col, *args, **kwargs):
+ """
+ Create a cell and add it to the table.
+
+ Parameters
+ ----------
+ row : int
+ Row index.
+ col : int
+ Column index.
+ *args, **kwargs
+ All other parameters are passed on to `Cell`.
+
+ Returns
+ -------
+ `.Cell`
+ The created cell.
+
+ """
+ xy = (0, 0)
+ cell = Cell(xy, visible_edges=self.edges, *args, **kwargs)
+ self[row, col] = cell
+ return cell
+
+ def __setitem__(self, position, cell):
+ """
+ Set a custom cell in a given position.
+ """
+ _api.check_isinstance(Cell, cell=cell)
+ try:
+ row, col = position[0], position[1]
+ except Exception as err:
+ raise KeyError('Only tuples length 2 are accepted as '
+ 'coordinates') from err
+ cell.set_figure(self.figure)
+ cell.set_transform(self.get_transform())
+ cell.set_clip_on(False)
+ self._cells[row, col] = cell
+ self.stale = True
+
+ def __getitem__(self, position):
+ """Retrieve a custom cell from a given position."""
+ return self._cells[position]
+
+ @property
+ def edges(self):
+ """
+ The default value of `~.Cell.visible_edges` for newly added
+ cells using `.add_cell`.
+
+ Notes
+ -----
+ This setting does currently only affect newly created cells using
+ `.add_cell`.
+
+ To change existing cells, you have to set their edges explicitly::
+
+ for c in tab.get_celld().values():
+ c.visible_edges = 'horizontal'
+
+ """
+ return self._edges
+
+ @edges.setter
+ def edges(self, value):
+ self._edges = value
+ self.stale = True
+
+ def _approx_text_height(self):
+ return (self.FONTSIZE / 72.0 * self.figure.dpi /
+ self._axes.bbox.height * 1.2)
+
+ @allow_rasterization
+ def draw(self, renderer):
+ # docstring inherited
+
+ # Need a renderer to do hit tests on mouseevent; assume the last one
+ # will do
+ if renderer is None:
+ renderer = self.figure._get_renderer()
+ if renderer is None:
+ raise RuntimeError('No renderer defined')
+
+ if not self.get_visible():
+ return
+ renderer.open_group('table', gid=self.get_gid())
+ self._update_positions(renderer)
+
+ for key in sorted(self._cells):
+ self._cells[key].draw(renderer)
+
+ renderer.close_group('table')
+ self.stale = False
+
+ def _get_grid_bbox(self, renderer):
+ """
+ Get a bbox, in axes coordinates for the cells.
+
+ Only include those in the range (0, 0) to (maxRow, maxCol).
+ """
+ boxes = [cell.get_window_extent(renderer)
+ for (row, col), cell in self._cells.items()
+ if row >= 0 and col >= 0]
+ bbox = Bbox.union(boxes)
+ return bbox.transformed(self.get_transform().inverted())
+
+ def contains(self, mouseevent):
+ # docstring inherited
+ if self._different_canvas(mouseevent):
+ return False, {}
+ # TODO: Return index of the cell containing the cursor so that the user
+ # doesn't have to bind to each one individually.
+ renderer = self.figure._get_renderer()
+ if renderer is not None:
+ boxes = [cell.get_window_extent(renderer)
+ for (row, col), cell in self._cells.items()
+ if row >= 0 and col >= 0]
+ bbox = Bbox.union(boxes)
+ return bbox.contains(mouseevent.x, mouseevent.y), {}
+ else:
+ return False, {}
+
+ def get_children(self):
+ """Return the Artists contained by the table."""
+ return list(self._cells.values())
+
+ def get_window_extent(self, renderer=None):
+ # docstring inherited
+ if renderer is None:
+ renderer = self.figure._get_renderer()
+ self._update_positions(renderer)
+ boxes = [cell.get_window_extent(renderer)
+ for cell in self._cells.values()]
+ return Bbox.union(boxes)
+
+ def _do_cell_alignment(self):
+ """
+ Calculate row heights and column widths; position cells accordingly.
+ """
+ # Calculate row/column widths
+ widths = {}
+ heights = {}
+ for (row, col), cell in self._cells.items():
+ height = heights.setdefault(row, 0.0)
+ heights[row] = max(height, cell.get_height())
+ width = widths.setdefault(col, 0.0)
+ widths[col] = max(width, cell.get_width())
+
+ # work out left position for each column
+ xpos = 0
+ lefts = {}
+ for col in sorted(widths):
+ lefts[col] = xpos
+ xpos += widths[col]
+
+ ypos = 0
+ bottoms = {}
+ for row in sorted(heights, reverse=True):
+ bottoms[row] = ypos
+ ypos += heights[row]
+
+ # set cell positions
+ for (row, col), cell in self._cells.items():
+ cell.set_x(lefts[col])
+ cell.set_y(bottoms[row])
+
+ def auto_set_column_width(self, col):
+ """
+ Automatically set the widths of given columns to optimal sizes.
+
+ Parameters
+ ----------
+ col : int or sequence of ints
+ The indices of the columns to auto-scale.
+ """
+ col1d = np.atleast_1d(col)
+ if not np.issubdtype(col1d.dtype, np.integer):
+ _api.warn_deprecated("3.8", name="col",
+ message="%(name)r must be an int or sequence of ints. "
+ "Passing other types is deprecated since %(since)s "
+ "and will be removed %(removal)s.")
+ return
+ for cell in col1d:
+ self._autoColumns.append(cell)
+
+ self.stale = True
+
+ def _auto_set_column_width(self, col, renderer):
+ """Automatically set width for column."""
+ cells = [cell for key, cell in self._cells.items() if key[1] == col]
+ max_width = max((cell.get_required_width(renderer) for cell in cells),
+ default=0)
+ for cell in cells:
+ cell.set_width(max_width)
+
+ def auto_set_font_size(self, value=True):
+ """Automatically set font size."""
+ self._autoFontsize = value
+ self.stale = True
+
+ def _auto_set_font_size(self, renderer):
+
+ if len(self._cells) == 0:
+ return
+ fontsize = next(iter(self._cells.values())).get_fontsize()
+ cells = []
+ for key, cell in self._cells.items():
+ # ignore auto-sized columns
+ if key[1] in self._autoColumns:
+ continue
+ size = cell.auto_set_font_size(renderer)
+ fontsize = min(fontsize, size)
+ cells.append(cell)
+
+ # now set all fontsizes equal
+ for cell in self._cells.values():
+ cell.set_fontsize(fontsize)
+
+ def scale(self, xscale, yscale):
+ """Scale column widths by *xscale* and row heights by *yscale*."""
+ for c in self._cells.values():
+ c.set_width(c.get_width() * xscale)
+ c.set_height(c.get_height() * yscale)
+
+ def set_fontsize(self, size):
+ """
+ Set the font size, in points, of the cell text.
+
+ Parameters
+ ----------
+ size : float
+
+ Notes
+ -----
+ As long as auto font size has not been disabled, the value will be
+ clipped such that the text fits horizontally into the cell.
+
+ You can disable this behavior using `.auto_set_font_size`.
+
+ >>> the_table.auto_set_font_size(False)
+ >>> the_table.set_fontsize(20)
+
+ However, there is no automatic scaling of the row height so that the
+ text may exceed the cell boundary.
+ """
+ for cell in self._cells.values():
+ cell.set_fontsize(size)
+ self.stale = True
+
+ def _offset(self, ox, oy):
+ """Move all the artists by ox, oy (axes coords)."""
+ for c in self._cells.values():
+ x, y = c.get_x(), c.get_y()
+ c.set_x(x + ox)
+ c.set_y(y + oy)
+
+ def _update_positions(self, renderer):
+ # called from renderer to allow more precise estimates of
+ # widths and heights with get_window_extent
+
+ # Do any auto width setting
+ for col in self._autoColumns:
+ self._auto_set_column_width(col, renderer)
+
+ if self._autoFontsize:
+ self._auto_set_font_size(renderer)
+
+ # Align all the cells
+ self._do_cell_alignment()
+
+ bbox = self._get_grid_bbox(renderer)
+ l, b, w, h = bbox.bounds
+
+ if self._bbox is not None:
+ # Position according to bbox
+ if isinstance(self._bbox, Bbox):
+ rl, rb, rw, rh = self._bbox.bounds
+ else:
+ rl, rb, rw, rh = self._bbox
+ self.scale(rw / w, rh / h)
+ ox = rl - l
+ oy = rb - b
+ self._do_cell_alignment()
+ else:
+ # Position using loc
+ (BEST, UR, UL, LL, LR, CL, CR, LC, UC, C,
+ TR, TL, BL, BR, R, L, T, B) = range(len(self.codes))
+ # defaults for center
+ ox = (0.5 - w / 2) - l
+ oy = (0.5 - h / 2) - b
+ if self._loc in (UL, LL, CL): # left
+ ox = self.AXESPAD - l
+ if self._loc in (BEST, UR, LR, R, CR): # right
+ ox = 1 - (l + w + self.AXESPAD)
+ if self._loc in (BEST, UR, UL, UC): # upper
+ oy = 1 - (b + h + self.AXESPAD)
+ if self._loc in (LL, LR, LC): # lower
+ oy = self.AXESPAD - b
+ if self._loc in (LC, UC, C): # center x
+ ox = (0.5 - w / 2) - l
+ if self._loc in (CL, CR, C): # center y
+ oy = (0.5 - h / 2) - b
+
+ if self._loc in (TL, BL, L): # out left
+ ox = - (l + w)
+ if self._loc in (TR, BR, R): # out right
+ ox = 1.0 - l
+ if self._loc in (TR, TL, T): # out top
+ oy = 1.0 - b
+ if self._loc in (BL, BR, B): # out bottom
+ oy = - (b + h)
+
+ self._offset(ox, oy)
+
+ def get_celld(self):
+ r"""
+ Return a dict of cells in the table mapping *(row, column)* to
+ `.Cell`\s.
+
+ Notes
+ -----
+ You can also directly index into the Table object to access individual
+ cells::
+
+ cell = table[row, col]
+
+ """
+ return self._cells
+
+
+@_docstring.dedent_interpd
+def table(ax,
+ cellText=None, cellColours=None,
+ cellLoc='right', colWidths=None,
+ rowLabels=None, rowColours=None, rowLoc='left',
+ colLabels=None, colColours=None, colLoc='center',
+ loc='bottom', bbox=None, edges='closed',
+ **kwargs):
+ """
+ Add a table to an `~.axes.Axes`.
+
+ At least one of *cellText* or *cellColours* must be specified. These
+ parameters must be 2D lists, in which the outer lists define the rows and
+ the inner list define the column values per row. Each row must have the
+ same number of elements.
+
+ The table can optionally have row and column headers, which are configured
+ using *rowLabels*, *rowColours*, *rowLoc* and *colLabels*, *colColours*,
+ *colLoc* respectively.
+
+ For finer grained control over tables, use the `.Table` class and add it to
+ the axes with `.Axes.add_table`.
+
+ Parameters
+ ----------
+ cellText : 2D list of str, optional
+ The texts to place into the table cells.
+
+ *Note*: Line breaks in the strings are currently not accounted for and
+ will result in the text exceeding the cell boundaries.
+
+ cellColours : 2D list of colors, optional
+ The background colors of the cells.
+
+ cellLoc : {'left', 'center', 'right'}, default: 'right'
+ The alignment of the text within the cells.
+
+ colWidths : list of float, optional
+ The column widths in units of the axes. If not given, all columns will
+ have a width of *1 / ncols*.
+
+ rowLabels : list of str, optional
+ The text of the row header cells.
+
+ rowColours : list of colors, optional
+ The colors of the row header cells.
+
+ rowLoc : {'left', 'center', 'right'}, default: 'left'
+ The text alignment of the row header cells.
+
+ colLabels : list of str, optional
+ The text of the column header cells.
+
+ colColours : list of colors, optional
+ The colors of the column header cells.
+
+ colLoc : {'left', 'center', 'right'}, default: 'left'
+ The text alignment of the column header cells.
+
+ loc : str, optional
+ The position of the cell with respect to *ax*. This must be one of
+ the `~.Table.codes`.
+
+ bbox : `.Bbox` or [xmin, ymin, width, height], optional
+ A bounding box to draw the table into. If this is not *None*, this
+ overrides *loc*.
+
+ edges : substring of 'BRTL' or {'open', 'closed', 'horizontal', 'vertical'}
+ The cell edges to be drawn with a line. See also
+ `~.Cell.visible_edges`.
+
+ Returns
+ -------
+ `~matplotlib.table.Table`
+ The created table.
+
+ Other Parameters
+ ----------------
+ **kwargs
+ `.Table` properties.
+
+ %(Table:kwdoc)s
+ """
+
+ if cellColours is None and cellText is None:
+ raise ValueError('At least one argument from "cellColours" or '
+ '"cellText" must be provided to create a table.')
+
+ # Check we have some cellText
+ if cellText is None:
+ # assume just colours are needed
+ rows = len(cellColours)
+ cols = len(cellColours[0])
+ cellText = [[''] * cols] * rows
+
+ rows = len(cellText)
+ cols = len(cellText[0])
+ for row in cellText:
+ if len(row) != cols:
+ raise ValueError(f"Each row in 'cellText' must have {cols} "
+ "columns")
+
+ if cellColours is not None:
+ if len(cellColours) != rows:
+ raise ValueError(f"'cellColours' must have {rows} rows")
+ for row in cellColours:
+ if len(row) != cols:
+ raise ValueError("Each row in 'cellColours' must have "
+ f"{cols} columns")
+ else:
+ cellColours = ['w' * cols] * rows
+
+ # Set colwidths if not given
+ if colWidths is None:
+ colWidths = [1.0 / cols] * cols
+
+ # Fill in missing information for column
+ # and row labels
+ rowLabelWidth = 0
+ if rowLabels is None:
+ if rowColours is not None:
+ rowLabels = [''] * rows
+ rowLabelWidth = colWidths[0]
+ elif rowColours is None:
+ rowColours = 'w' * rows
+
+ if rowLabels is not None:
+ if len(rowLabels) != rows:
+ raise ValueError(f"'rowLabels' must be of length {rows}")
+
+ # If we have column labels, need to shift
+ # the text and colour arrays down 1 row
+ offset = 1
+ if colLabels is None:
+ if colColours is not None:
+ colLabels = [''] * cols
+ else:
+ offset = 0
+ elif colColours is None:
+ colColours = 'w' * cols
+
+ # Set up cell colours if not given
+ if cellColours is None:
+ cellColours = ['w' * cols] * rows
+
+ # Now create the table
+ table = Table(ax, loc, bbox, **kwargs)
+ table.edges = edges
+ height = table._approx_text_height()
+
+ # Add the cells
+ for row in range(rows):
+ for col in range(cols):
+ table.add_cell(row + offset, col,
+ width=colWidths[col], height=height,
+ text=cellText[row][col],
+ facecolor=cellColours[row][col],
+ loc=cellLoc)
+ # Do column labels
+ if colLabels is not None:
+ for col in range(cols):
+ table.add_cell(0, col,
+ width=colWidths[col], height=height,
+ text=colLabels[col], facecolor=colColours[col],
+ loc=colLoc)
+
+ # Do row labels
+ if rowLabels is not None:
+ for row in range(rows):
+ table.add_cell(row + offset, -1,
+ width=rowLabelWidth or 1e-15, height=height,
+ text=rowLabels[row], facecolor=rowColours[row],
+ loc=rowLoc)
+ if rowLabelWidth == 0:
+ table.auto_set_column_width(-1)
+
+ ax.add_table(table)
+ return table