kwplot package

Submodules

Module contents

KWPlot - The Kitware Plot Module

This module is a small wrapper around matplotlib and seaborn that simplifies develoepr workflow when working with code that might be run in IPython or in a script. This is primarilly handled by the kwplot.auto_backends module, which exposes the functions: kwplot.autompl(), kwplot.autoplt(), and kwplot.autosns() for auto-initialization of matplotlib, pyplot, and seaborn.

A very common anti-pattern in developer code is importing matplotlib.pyplot at the top level of your module. This is a mistake because importing pyplot has side-effects which can cause problems if executed at a module level (i.e. they happen at import time! Anyone using your library will have to deal with these consequences )

To mitigate this we recommend only using pyplot inside of the scope of the functions that need it.

Importing kwplot itself has no import-time side effects, so it is safe to put it as a module level import, however, plotting is often an optional feature of any library, so we still recomend putting that code inside the functions that need it.

The general code flow looks like this, inside your function run:

import kwplot
kwplot.autompl()

# Pyplot is now initialized do matplotlib or pyplot stuff
...

This checks if you are running interactively in IPython, if so try to use a Qt backend. If not, then try to use a headless Agg backend.

You can also do

import kwplot
# These also call autompl in the backend, and return either the seaborn or
# pyplot modules, so you dont have to import them in your code. When
# running seaborn, this will also call ``sns.set()`` for you.
sns = kwplot.autosns()
plt = kwplot.autoplt()
...

In addition to this auto-backend feature, kwplot also exposes useful helper methods for common drawing operations.

There is also a small CLI that can be used to view multispectral or uint16 images.

class kwplot.BackendContext(backend)[source]

Bases: object

Context manager that ensures a specific backend, but then reverts after the context has ended.

Because this changes the backend after pyplot has initialized, there is a chance for odd behavior to occur. Please submit and issue if you experience this and can document the environment that caused it.

CommandLine

# Checks
xdoctest -m kwplot.auto_backends BackendContext --check

Example

>>> # xdoctest +REQUIRES(--check)
>>> from kwplot.auto_backends import *  # NOQA
>>> import matplotlib as mpl
>>> import kwplot
>>> print(mpl.get_backend())
>>> #kwplot.autompl(force='auto')
>>> #print(mpl.get_backend())
>>> #fig1 = kwplot.figure(fnum=3)
>>> #print(mpl.get_backend())
>>> with BackendContext('agg'):
>>>     print(mpl.get_backend())
>>>     fig2 = kwplot.figure(fnum=4)
>>> print(mpl.get_backend())
class kwplot.Color(color, alpha=None, space=None)[source]

Bases: NiceRepr

Used for converting a single color between spaces and encodings. This should only be used when handling small numbers of colors(e.g. 1), don’t use this to represent an image.

move to colorutil?

Parameters

space (str) – colorspace of wrapped color. Assume RGB if not specified and it cannot be inferred

CommandLine

xdoctest -m ~/code/kwimage/kwimage/im_color.py Color

Example

>>> print(Color('g'))
>>> print(Color('orangered'))
>>> print(Color('#AAAAAA').as255())
>>> print(Color([0, 255, 0]))
>>> print(Color([1, 1, 1.]))
>>> print(Color([1, 1, 1]))
>>> print(Color(Color([1, 1, 1])).as255())
>>> print(Color(Color([1., 0, 1, 0])).ashex())
>>> print(Color([1, 1, 1], alpha=255))
>>> print(Color([1, 1, 1], alpha=255, space='lab'))
ashex(space=None)[source]
as255(space=None)[source]
as01(space=None)[source]

self = mplutil.Color(‘red’) mplutil.Color(‘green’).as01(‘rgba’)

classmethod named_colors()[source]
Returns

names of colors that Color accepts

Return type

List[str]

Example

>>> import kwimage
>>> named_colors = kwimage.Color.named_colors()
>>> color_lut = {name: kwimage.Color(name).as01() for name in named_colors}
>>> # xdoctest: +REQUIRES(module:kwplot)
>>> import kwplot
>>> kwplot.autompl()
>>> canvas = kwplot.make_legend_img(color_lut)
>>> kwplot.imshow(canvas)
classmethod distinct(num, existing=None, space='rgb', legacy='auto', exclude_black=True, exclude_white=True)[source]

Make multiple distinct colors

References

https://stackoverflow.com/questions/470690/how-to-automatically-generate-n-distinct-colors

Example

>>> # xdoctest: +REQUIRES(module:matplotlib)
>>> from kwimage.im_color import *  # NOQA
>>> from kwimage.im_color import _draw_color_swatch
>>> import kwimage
>>> colors1 = kwimage.Color.distinct(10, legacy=False)
>>> swatch1 = _draw_color_swatch(colors1, cellshape=9)
>>> colors2 = kwimage.Color.distinct(10, existing=colors1)
>>> swatch2 = _draw_color_swatch(colors1 + colors2, cellshape=9)
>>> # xdoctest: +REQUIRES(module:kwplot)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(swatch1, pnum=(1, 2, 1), fnum=1)
>>> kwplot.imshow(swatch2, pnum=(1, 2, 2), fnum=1)
classmethod random(pool='named')[source]
distance(other, space='lab')[source]

Distance between self an another color

Example

import kwimage self = kwimage.Color((0.16304347826086973, 0.0, 1.0)) other = kwimage.Color(‘purple’)

hard_coded_colors = {

‘a’: (1.0, 0.0, 0.16), ‘b’: (1.0, 0.918918918918919, 0.0), ‘c’: (0.0, 1.0, 0.0), ‘d’: (0.0, 0.9239130434782604, 1.0), ‘e’: (0.16304347826086973, 0.0, 1.0)

}

# Find grays names = kwimage.Color.named_colors() grays = {} for name in names:

color = kwimage.Color(name) r, g, b = color.as01() if r == g and g == b:

grays[name] = (r, g, b)

print(ub.repr2(ub.sorted_vals(grays), nl=-1))

for k, v in hard_coded_colors.items():

self = kwimage.Color(v) distances = [] for name in names:

other = kwimage.Color(name) dist = self.distance(other) distances.append(dist)

idxs = ub.argsort(distances)[0:5] dists = list(ub.take(distances, idxs)) names = list(ub.take(names, idxs)) print(‘k = {!r}’.format(k)) print(‘names = {!r}’.format(names)) print(‘dists = {!r}’.format(dists))

class kwplot.PlotNums(nRows=None, nCols=None, nSubplots=None, start=0)[source]

Bases: object

Convinience class for dealing with plot numberings (pnums)

This is useful in the case where you want a certain number of subplots, but you might swap the order in which those subplots are called. This class introduces the idea of either getting the “next” subplot, or getting one at a specific instance. The total number of subplots can be modified in just a single place in the code (the arguments to the PlotNums constructor) instead of each instance where you would specify a pnum normally.

Example

>>> import ubelt as ub
>>> pnum_ = PlotNums(nRows=2, nCols=2)
>>> # Indexable
>>> print(pnum_[0])
(2, 2, 1)
>>> # Iterable
>>> print(ub.repr2(list(pnum_), nl=0, nobr=1))
(2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 2, 4)
>>> # Callable (iterates through a default iterator)
>>> print(pnum_())
(2, 2, 1)
>>> print(pnum_())
(2, 2, 2)
kwplot.all_figures()[source]

Return a list of all open figures

Returns

list of all figures

Return type

List[mpl.figure.Figure]

kwplot.autompl(verbose=0, recheck=False, force=None)[source]

Uses platform heuristics to automatically set the matplotlib backend. If no display is available it will be set to agg, otherwise we will try to use the cross-platform Qt5Agg backend.

Parameters
  • verbose (int, default=0) – verbosity level

  • recheck (bool, default=False) – if False, this function will not run if it has already been called (this can save a significant amount of time).

  • force (str, default=None) – backend to force to or “auto”

CommandLine

# Checks
export QT_DEBUG_PLUGINS=1
xdoctest -m kwplot.auto_backends autompl --check
KWPLOT_UNSAFE=1 xdoctest -m kwplot.auto_backends autompl --check
KWPLOT_UNSAFE=0 xdoctest -m kwplot.auto_backends autompl --check

Example

>>> # xdoctest +REQUIRES(--check)
>>> plt = autoplt(verbose=1)
>>> plt.figure()

References

https://stackoverflow.com/questions/637005/check-if-x-server-is-running

kwplot.autoplt(verbose=0, recheck=False, force=None)[source]

Like autompl, but also returns the matplotlib.pyplot module for convenience.

Returns

ModuleType

kwplot.autosns(verbose=0, recheck=False, force=None)[source]

Like autompl, but also calls seaborn.set() and returns the seaborn module for convenience.

Returns

ModuleType

kwplot.close_figures(figures=None)[source]

Close specified figures. If no figures are specified, close all figure.

Parameters

figures (List[mpl.figure.Figure]) – list of figures to close

kwplot.distinct_colors(N, brightness=0.878, randomize=True, hue_range=(0.0, 1.0), cmap_seed=None)[source]
Parameters
  • N (int)

  • brightness (float)

Returns

RGB_tuples

Return type

list

Todo

  • [ ] This is VERY old code that needs massive cleanup.

CommandLine

python -m color_funcs --test-distinct_colors --N 2 --show --hue-range=0.05,.95
python -m color_funcs --test-distinct_colors --N 3 --show --hue-range=0.05,.95
python -m color_funcs --test-distinct_colors --N 4 --show --hue-range=0.05,.95
python -m .color_funcs --test-distinct_colors --N 3 --show --no-randomize
python -m .color_funcs --test-distinct_colors --N 4 --show --no-randomize
python -m .color_funcs --test-distinct_colors --N 6 --show --no-randomize
python -m .color_funcs --test-distinct_colors --N 20 --show

References

http://blog.jianhuashao.com/2011/09/generate-n-distinct-colors.html

CommandLine

python -m .color_funcs --exec-distinct_colors --show
python -m .color_funcs --exec-distinct_colors --show --no-randomize --N 50
python -m .color_funcs --exec-distinct_colors --show --cmap_seed=foobar
kwplot.distinct_markers(num, style='astrisk', total=None, offset=0)[source]

Creates distinct marker codes (as best as possible)

Parameters
  • num (int) – number of markers to make

  • style (str) – mplt style code

  • total (int) – alternative to num

  • offset (float) – angle offset

Returns

marker codes

Return type

List[Tuple]

Example

>>> import kwplot
>>> plt = kwplot.autoplt()
>>> style = 'astrisk'
>>> marker_list = kwplot.distinct_markers(10, style)
>>> print('marker_list = {}'.format(ub.repr2(marker_list, nl=1)))
>>> x_data = np.arange(0, 3)
>>> for count, (marker) in enumerate(marker_list):
>>>     plt.plot(x_data, [count] * len(x_data), marker=marker, markersize=10, linestyle='', label=str(marker))
>>> plt.legend()
>>> kwplot.show_if_requested()
kwplot.draw_boxes(boxes, alpha=None, color='blue', labels=None, centers=False, fill=False, ax=None, lw=2)[source]
Parameters
  • boxes (kwimage.Boxes)

  • labels (List[str]) – of labels

  • alpha (List[float]) – alpha for each box

  • centers (bool) – draw centers or not

  • lw (float) – linewidth

Example

>>> import kwimage
>>> bboxes = kwimage.Boxes([[.1, .1, .6, .3], [.3, .5, .5, .6]], 'xywh')
>>> draw_boxes(bboxes)
>>> #kwplot.autompl()
kwplot.draw_boxes_on_image(img, boxes, color='blue', thickness=1, box_format=None, colorspace='rgb')[source]

Draws boxes on an image.

Parameters
  • img (ndarray) – image to copy and draw on

  • boxes (nh.util.Boxes) – boxes to draw

  • colorspace (str) – string code of the input image colorspace

Example

>>> import kwimage
>>> import numpy as np
>>> img = np.zeros((10, 10, 3), dtype=np.uint8)
>>> color = 'dodgerblue'
>>> thickness = 1
>>> boxes = kwimage.Boxes([[1, 1, 8, 8]], 'ltrb')
>>> img2 = draw_boxes_on_image(img, boxes, color, thickness)
>>> assert tuple(img2[1, 1]) == (30, 144, 255)
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()  # xdoc: +SKIP
>>> kwplot.figure(doclf=True, fnum=1)
>>> kwplot.imshow(img2)
kwplot.draw_clf_on_image(im, classes, tcx=None, probs=None, pcx=None, border=1)[source]

Draws classification label on an image.

Works best with image chips sized between 200x200 and 500x500

Parameters
  • im (ndarray) – the image

  • classes (Sequence | CategoryTree) – list of class names

  • tcx (int, default=None) – true class index if known

  • probs (ndarray) – predicted class probs for each class

  • pcx (int, default=None) – predicted class index. (if None but probs is specified uses argmax of probs)

Example

>>> # xdoctest: +REQUIRES(module:torch)
>>> import torch
>>> import kwarray
>>> import kwimage
>>> rng = kwarray.ensure_rng(0)
>>> im = (rng.rand(300, 300) * 255).astype(np.uint8)
>>> classes = ['cls_a', 'cls_b', 'cls_c']
>>> tcx = 1
>>> probs = rng.rand(len(classes))
>>> probs[tcx] = 0
>>> probs = torch.FloatTensor(probs).softmax(dim=0).numpy()
>>> im1_ = kwimage.draw_clf_on_image(im, classes, tcx, probs)
>>> probs[tcx] = .9
>>> probs = torch.FloatTensor(probs).softmax(dim=0).numpy()
>>> im2_ = kwimage.draw_clf_on_image(im, classes, tcx, probs)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(im1_, colorspace='rgb', pnum=(1, 2, 1), fnum=1, doclf=True)
>>> kwplot.imshow(im2_, colorspace='rgb', pnum=(1, 2, 2), fnum=1)
>>> kwplot.show_if_requested()
kwplot.draw_line_segments(pts1, pts2, ax=None, **kwargs)[source]

draws N line segments between N pairs of points

Parameters
  • pts1 (ndarray) – Nx2

  • pts2 (ndarray) – Nx2

  • ax (None) – (default = None)

  • **kwargs – lw, alpha, colors

Example

>>> import numpy as np
>>> import kwplot
>>> pts1 = np.array([(.1, .8), (.6, .8)])
>>> pts2 = np.array([(.6, .7), (.4, .1)])
>>> kwplot.figure(fnum=None)
>>> draw_line_segments(pts1, pts2)
>>> # xdoc: +REQUIRES(--show)
>>> import matplotlib.pyplot as plt
>>> ax = plt.gca()
>>> ax.set_xlim(0, 1)
>>> ax.set_ylim(0, 1)
>>> kwplot.show_if_requested()
kwplot.draw_points(xy, color='blue', class_idxs=None, classes=None, ax=None, alpha=None, radius=1, **kwargs)[source]
Parameters

xy (ndarray) – of points.

Example

>>> from kwplot.mpl_draw import *  # NOQA
>>> import kwimage
>>> xy = kwimage.Points.random(10).xy
>>> draw_points(xy, radius=0.01)
>>> draw_points(xy, class_idxs=np.random.randint(0, 3, 10),
>>>         radius=0.01, classes=['a', 'b', 'c'], color='classes')
kwplot.draw_text_on_image(img, text, org=None, return_info=False, **kwargs)[source]

Draws multiline text on an image using opencv

Parameters
  • img (ndarray | None | dict) – Generally a numpy image to draw on (inplace). Otherwise a canvas will be constructed such that the text will fit. The user may specify a dictionary with keys width and height to have more control over the constructed canvas.

  • text (str) – text to draw

  • org (Tuple[int, int]) – The x, y location of the text string “anchor” in the image as specified by halign and valign. For instance, If valign=’bottom’, halign=’left’, this is the bottom left corner.

  • return_info (bool, default=False) – if True, also returns information about the positions the text was drawn on.

  • **kwargs – color (tuple): default blue thickness (int): defaults to 2 fontFace (int): defaults to cv2.FONT_HERSHEY_SIMPLEX fontScale (float): defaults to 1.0 valign (str, default=’bottom’):

    either top, center, or bottom. NOTE: this default may change to “top” in the future.

    halign (str, default=’left’):

    either left, center, or right

    border (dict | int):

    If specified as an integer, draws a black border with that given thickness. If specified as a dictionary, draws a border with color specified parameters.

    “color”: border color, defaults to “black”. “thickness”: border thickness, defaults to 1.

Returns

the image that was drawn on

Return type

ndarray

Note

The image is modified inplace. If the image is non-contiguous then this returns a UMat instead of a ndarray, so be carefull with that.

References

https://stackoverflow.com/questions/27647424/ https://stackoverflow.com/questions/51285616/opencvs-gettextsize-and-puttext-return-wrong-size-and-chop-letters-with-low

Example

>>> import kwimage
>>> img = kwimage.grab_test_image(space='rgb')
>>> img2 = kwimage.draw_text_on_image(img.copy(), 'FOOBAR', org=(0, 0), valign='top')
>>> assert img2.shape == img.shape
>>> assert np.any(img2 != img)
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(img2)
>>> kwplot.show_if_requested()

Example

>>> import kwimage
>>> # Test valign
>>> img = kwimage.grab_test_image(space='rgb', dsize=(500, 500))
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(0, 0), valign='top', border=2)
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(150, 0), valign='center', border=2)
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(300, 0), valign='bottom', border=2)
>>> # Test halign
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(250, 100), halign='right', border=2)
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(250, 250), halign='center', border=2)
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(250, 400), halign='left', border=2)
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(img2)
>>> kwplot.show_if_requested()

Example

>>> # Ensure the function works with float01 or uint255 images
>>> import kwimage
>>> img = kwimage.grab_test_image(space='rgb')
>>> img = kwimage.ensure_float01(img)
>>> img2 = kwimage.draw_text_on_image(img, 'FOOBAR\nbazbiz\nspam', org=(0, 0), valign='top', border=2)

Example

>>> # Test dictionary border
>>> import kwimage
>>> img = kwimage.draw_text_on_image(None, 'hello\neveryone', org=(100, 100), valign='top', halign='center', border={'color': 'green', 'thickness': 9})
>>> #img = kwimage.draw_text_on_image(None, 'hello\neveryone', org=(0, 0), valign='top')
>>> #img = kwimage.draw_text_on_image(None, 'hello', org=(0, 60), valign='top', halign='center', border=0)
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(img)
>>> kwplot.show_if_requested()

Example

>>> # Test dictionary image
>>> import kwimage
>>> img = kwimage.draw_text_on_image({'width': 300}, 'good\nPropogate', org=(150, 0), valign='top', halign='center', border={'color': 'green', 'thickness': 0})
>>> print('img.shape = {!r}'.format(img.shape))
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(img)
>>> kwplot.show_if_requested()

Example

>>> import ubelt as ub
>>> import kwimage
>>> grid = list(ub.named_product({
>>>     'halign': ['left', 'center', 'right', None],
>>>     'valign': ['top', 'center', 'bottom', None],
>>>     'border': [0, 3]
>>> }))
>>> canvases = []
>>> text = 'small-line\na-much-much-much-bigger-line\nanother-small\n.'
>>> for kw in grid:
>>>     header = kwimage.draw_text_on_image({}, ub.repr2(kw, compact=1), color='blue')
>>>     canvas = kwimage.draw_text_on_image({'color': 'white'}, text, org=None, **kw)
>>>     canvases.append(kwimage.stack_images([header, canvas], axis=0, bg_value=(255, 255, 255), pad=5))
>>> # xdoc: +REQUIRES(--show)
>>> canvas = kwimage.stack_images_grid(canvases, pad=10, bg_value=(255, 255, 255))
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(canvas)
>>> kwplot.show_if_requested()
kwplot.ensure_fnum(fnum)[source]
kwplot.figure(fnum=None, pnum=(1, 1, 1), title=None, figtitle=None, doclf=False, docla=False, projection=None, **kwargs)[source]

http://matplotlib.org/users/gridspec.html

Parameters
  • fnum (int) – fignum = figure number

  • pnum (int, str, or tuple(int, int, int)) – plotnum = plot tuple

  • title (str) – (default = None)

  • figtitle (None) – (default = None)

  • docla (bool) – (default = False)

  • doclf (bool) – (default = False)

Returns

fig

Return type

mpl.figure.Figure

Example

>>> import kwplot
>>> kwplot.autompl()
>>> import matplotlib.pyplot as plt
>>> fnum = 1
>>> fig = figure(fnum, (2, 2, 1))
>>> fig.gca().text(0.5, 0.5, "ax1", va="center", ha="center")
>>> fig = figure(fnum, (2, 2, 2))
>>> fig.gca().text(0.5, 0.5, "ax2", va="center", ha="center")
>>> show_if_requested()

Example

>>> import kwplot
>>> kwplot.autompl()
>>> import matplotlib.pyplot as plt
>>> fnum = 1
>>> fig = figure(fnum, (2, 2, 1))
>>> fig.gca().text(0.5, 0.5, "ax1", va="center", ha="center")
>>> fig = figure(fnum, (2, 2, 2))
>>> fig.gca().text(0.5, 0.5, "ax2", va="center", ha="center")
>>> fig = figure(fnum, (2, 4, (1, slice(1, None))))
>>> fig.gca().text(0.5, 0.5, "ax3", va="center", ha="center")
>>> show_if_requested()
kwplot.imshow(img, fnum=None, pnum=None, xlabel=None, title=None, figtitle=None, ax=None, norm=None, cmap=None, data_colorbar=False, colorspace='rgb', interpolation='nearest', alpha=None, show_ticks=False, **kwargs)[source]
Parameters
  • img (ndarray) – image data. Height, Width, and Channel dimensions can either be in standard (H, W, C) format or in (C, H, W) format. If C in [3, 4], we assume data is in the rgb / rgba colorspace by default.

  • colorspace (str) – if the data is 3-4 channels, this indicates the colorspace 1 channel data is assumed grayscale. 4 channels assumes alpha.

  • interpolation (str) – either nearest (default), bicubic, bilinear

  • norm (bool) – if True, normalizes the image intensities to fit in a colormap.

  • cmap (mpl.colors.Colormap | None) – color map used if data is not starndard image data

  • data_colorbar (bool) – if True, displays a color scale indicating how colors map to image intensities.

  • fnum (int | None) – figure number

  • pnum (tuple | None) – plot number

  • xlabel (str | None) – sets the label for the x axis

  • title (str | None) – set axes title (if ax is not given)

  • figtitle (str | None) – set figure title (if ax is not given)

  • ax (mpl.axes.Axes | None) – axes to draw on (alternative to fnum and pnum)

  • **kwargs – docla, doclf, projection

Returns

(fig, ax)

Return type

tuple

kwplot.legend(loc='best', fontproperties=None, size=None, fc='w', alpha=1, ax=None, handles=None)[source]
Parameters
  • loc (str) – (default = ‘best’) one of ‘best’, ‘upper right’, ‘upper left’, ‘lower left’, ‘lower right’, ‘right’, ‘center left’, ‘center right’, ‘lower center’, or ‘upper center’.

  • fontproperties (None) – (default = None)

  • size (None) – (default = None)

kwplot.make_conv_images(conv, color=None, norm_per_feat=True)[source]

Convert convolutional weights to a list of visualize-able images

Parameters
  • conv (torch.nn.Conv2d) – a torch convolutional layer

  • color (bool) – if True output images are colorized

  • norm_per_feat (bool) – if True normalizes over each feature separately, otherwise normalizes all features together.

Return type

ndarray

Todo

  • [ ] better normalization options

Example

>>> # xdoctest: +REQUIRES(module:torch)
>>> conv = torch.nn.Conv2d(3, 9, (5, 7))
>>> weights_tohack = conv.weight[0:7].data.numpy()
>>> weights_flat = make_conv_images(conv, norm_per_feat=False)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwimage
>>> import kwplot
>>> stacked = kwimage.stack_images_grid(weights_flat, chunksize=5, overlap=-1)
>>> kwplot.imshow(stacked)
>>> kwplot.show_if_requested()
kwplot.make_heatmask(probs, cmap='plasma', with_alpha=1.0, space='rgb', dsize=None)[source]

Colorizes a single-channel intensity mask (with an alpha channel)

Parameters
  • probs (ndarray) – 2D probability map with values between 0 and 1

  • cmap (str) – mpl colormap

  • with_alpha (float) – between 0 and 1, uses probs as the alpha multipled by this number.

  • space (str) – output colorspace

  • dsize (tuple) – if not None, then output is resized to W,H=dsize

SeeAlso:

kwimage.overlay_alpha_images

Example

>>> # xdoc: +REQUIRES(module:matplotlib)
>>> from kwimage.im_draw import *  # NOQA
>>> probs = np.tile(np.linspace(0, 1, 10), (10, 1))
>>> heatmask = make_heatmask(probs, with_alpha=0.8, dsize=(100, 100))
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.imshow(heatmask, fnum=1, doclf=True, colorspace='rgb')
>>> kwplot.show_if_requested()
kwplot.make_legend_img(label_to_color, dpi=96, shape=(200, 200), mode='line', transparent=False)[source]

Makes an image of a categorical legend

Parameters

label_to_color (Dict[str, kwimage.Color]) – mapping from string label to the color.

CommandLine

xdoctest -m kwplot.mpl_make make_legend_img --show

Example

>>> # xdoctest: +REQUIRES(module:kwplot)
>>> import kwplot
>>> import kwimage
>>> label_to_color = {
>>>     'blue': kwimage.Color('blue').as01(),
>>>     'red': kwimage.Color('red').as01(),
>>>     'green': 'green',
>>>     'yellow': 'yellow',
>>>     'orangered': 'orangered',
>>> }
>>> img = make_legend_img(label_to_color, transparent=True)
>>> # xdoctest: +REQUIRES(--show)
>>> kwplot.autompl()
>>> kwplot.imshow(img)
>>> kwplot.show_if_requested()
kwplot.make_orimask(radians, mag=None, alpha=1.0)[source]

Makes a colormap in HSV space where the orientation changes color and mag changes the saturation/value.

Parameters
  • radians (ndarray) – orientation in radians

  • mag (ndarray) – magnitude (must be normalized between 0 and 1)

  • alpha (float | ndarray) – if False or None, then the image is returned without alpha if a float, then mag is scaled by this and used as the alpha channel if an ndarray, then this is explicilty set as the alpha channel

Returns

an rgb / rgba image in 01 space

Return type

ndarray[float32]

SeeAlso:

kwimage.overlay_alpha_images

Example

>>> # xdoc: +REQUIRES(module:matplotlib)
>>> from kwimage.im_draw import *  # NOQA
>>> x, y = np.meshgrid(np.arange(64), np.arange(64))
>>> dx, dy = x - 32, y - 32
>>> radians = np.arctan2(dx, dy)
>>> mag = np.sqrt(dx ** 2 + dy ** 2)
>>> orimask = make_orimask(radians, mag)
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.imshow(orimask, fnum=1, doclf=True, colorspace='rgb')
>>> kwplot.show_if_requested()
kwplot.make_vector_field(dx, dy, stride=0.02, thresh=0.0, scale=1.0, alpha=1.0, color='strawberry', thickness=1, tipLength=0.1, line_type='aa')[source]

Create an image representing a 2D vector field.

Parameters
  • dx (ndarray) – grid of vector x components

  • dy (ndarray) – grid of vector y components

  • stride (int | float) – sparsity of vectors, int specifies stride step in pixels, a float specifies it as a percentage.

  • thresh (float) – only plot vectors with magnitude greater than thres

  • scale (float) – multiply magnitude for easier visualization

  • alpha (float) – alpha value for vectors. Non-vector regions receive 0 alpha (if False, no alpha channel is used)

  • color (str | tuple | kwimage.Color) – RGB color of the vectors

  • thickness (int, default=1) – thickness of arrows

  • tipLength (float, default=0.1) – fraction of line length

  • line_type (int) – either cv2.LINE_4, cv2.LINE_8, or cv2.LINE_AA

Returns

vec_img: an rgb/rgba image in 0-1 space

Return type

ndarray[float32]

SeeAlso:

kwimage.overlay_alpha_images

DEPRECATED USE: draw_vector_field instead

Example

>>> x, y = np.meshgrid(np.arange(512), np.arange(512))
>>> dx, dy = x - 256.01, y - 256.01
>>> radians = np.arctan2(dx, dy)
>>> mag = np.sqrt(dx ** 2 + dy ** 2)
>>> dx, dy = dx / mag, dy / mag
>>> img = make_vector_field(dx, dy, scale=10, alpha=False)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(img)
>>> kwplot.show_if_requested()
kwplot.multi_plot(xdata=None, ydata=None, xydata=None, **kwargs)[source]

plots multiple lines, bars, etc…

One function call that concisely describes the all of the most commonly used parameters needed when plotting a bar / line char. This is especially useful when multiple plots are needed in the same domain.

Parameters
  • xdata (List[ndarray] | Dict[str, ndarray] | ndarray) – x-coordinate data common to all y-coordinate values or xdata for each line/bar in ydata. Mutually exclusive with xydata.

  • ydata (List[ndarray] | Dict[str, ndarray] | ndarray) – y-coordinate values for each line/bar to plot. Can also be just a single ndarray of scalar values. Mutually exclusive with xydata.

  • xydata (Dict[str, Tuple[ndarray, ndarray]]) – mapping from labels to a tuple of xdata and ydata for a each line.

  • **kwargs

    fnum (int):

    figure number to draw on

    pnum (Tuple[int, int, int]):

    plot number to draw on within the figure, e.g. (1, 1, 1)

    label (List|Dict):

    if you specified ydata as a List[ndarray] this is the label for each line in that list. Note this is unnecessary if you specify input as a dictionary mapping labels to lines.

    color (str|List|Dict):

    either a special color code, a single color, or a color for each item in ydata. In the later case, this should be specified as either a list or a dict depending on how ydata was specified.

    marker (str|List|Dict):

    type of matplotlib marker to use at every data point. Can be specified for all lines jointly or for each line independently.

    transpose (bool, default=False):

    swaps x and y data.

    kind (str, default=’plot’):

    The kind of plot. Can either be ‘plot’ or ‘bar’. We parse these other kwargs if:

    if kind=’plot’:

    spread

    if kind=’bar’:

    stacked, width

    Misc:

    use_legend (bool): … legend_loc (str):

    one of ‘best’, ‘upper right’, ‘upper left’, ‘lower left’, ‘lower right’, ‘right’, ‘center left’, ‘center right’, ‘lower center’, or ‘upper center’.

    Layout:

    xlabel (str): label for x-axis ylabel (str): label for y-axis title (str): title for the axes figtitle (str): title for the figure

    xscale (str): can be one of [linear, log, logit, symlog] yscale (str): can be one of [linear, log, logit, symlog]

    xlim (Tuple[float, float]): low and high x-limit of axes ylim (Tuple[float, float]): low and high y-limit of axes xmin (float): low x-limit of axes, mutex with xlim xmax (float): high x-limit of axes, mutex with xlim ymin (float): low y-limit of axes, mutex with ylim ymax (float): high y-limit of axes, mutex with ylim

    titlesize (float): … legendsize (float): … labelsize (float): …

    Grid:

    gridlinewidth (float): … gridlinestyle (str): …

    Ticks:

    num_xticks (int): number of x ticks num_yticks (int): number of y ticks tickwidth (float): … ticklength (float): … ticksize (float): … xticklabels (list): list of x-tick labels, overrides num_xticks yticklabels (list): list of y-tick labels, overrides num_yticks xtick_rotation (float): xtick rotation in degrees ytick_rotation (float): ytick rotation in degrees

    Data:
    spread (List | Dict): Plots a spread around plot lines usually

    indicating standard deviation

    markersize (float|List|Dict): marker size for all or each plot markeredgewidth (float|List|Dict): marker edge width for all or each plot linewidth (float|List|Dict): line width for all or each plot linestyle (str|List|Dict): line style for all or each plot

Note

any plot_kw key can be a scalar (corresponding to all ydatas), a list if ydata was specified as a list, or a dict if ydata was specified as a dict.

plot_kw_keys = [‘label’, ‘color’, ‘marker’, ‘markersize’,

‘markeredgewidth’, ‘linewidth’, ‘linestyle’]

Note

In general this should be deprecated in favor of using seaborn

Returns

ax : the axes that was drawn on

Return type

matplotlib.axes.Axes

References

matplotlib.org/examples/api/barchart_demo.html

Example

>>> import kwplot
>>> kwplot.autompl()
>>> # The new way to use multi_plot is to pass ydata as a dict of lists
>>> ydata = {
>>>     'spamΣ': [1, 1, 2, 3, 5, 8, 13],
>>>     'eggs': [3, 3, 3, 3, 3, np.nan, np.nan],
>>>     'jamµ': [5, 3, np.nan, 1, 2, np.nan, np.nan],
>>>     'pram': [4, 2, np.nan, 0, 0, np.nan, 1],
>>> }
>>> ax = kwplot.multi_plot(ydata=ydata, title='ΣΣΣµµµ',
>>>                      xlabel='\nfdsΣΣΣµµµ', linestyle='--')
>>> kwplot.show_if_requested()

Example

>>> # Old way to use multi_plot is a list of lists
>>> import kwplot
>>> kwplot.autompl()
>>> xdata = [1, 2, 3, 4, 5]
>>> ydata_list = [[1, 2, 3, 4, 5], [3, 3, 3, 3, 3], [5, 4, np.nan, 2, 1], [4, 3, np.nan, 1, 0]]
>>> kwargs = {'label': ['spamΣ', 'eggs', 'jamµ', 'pram'],  'linestyle': '-'}
>>> #ax = multi_plot(xdata, ydata_list, title='$\phi_1(\\vec{x})$', xlabel='\nfds', **kwargs)
>>> ax = multi_plot(xdata, ydata_list, title='ΣΣΣµµµ', xlabel='\nfdsΣΣΣµµµ', **kwargs)
>>> kwplot.show_if_requested()

Example

>>> # Simple way to use multi_plot is to pass xdata and ydata exactly
>>> # like you would use plt.plot
>>> import kwplot
>>> kwplot.autompl()
>>> ax = multi_plot([1, 2, 3], [4, 5, 6], fnum=4, label='foo')
>>> kwplot.show_if_requested()

Example

>>> import kwplot
>>> kwplot.autompl()
>>> xydata = {'a': ([0, 1, 2], [0, 1, 2]), 'b': ([0, 2, 4], [2, 1, 0])}
>>> ax = kwplot.multi_plot(xydata=xydata, fnum=4)
>>> kwplot.show_if_requested()

Example

>>> import kwplot
>>> kwplot.autompl()
>>> ydata = {'a': [0, 1, 2], 'b': [1, 2, 1], 'c': [4, 4, 4, 3, 2]}
>>> kwargs = {
>>>     'spread': {'a': [.2, .3, .1], 'b': .2},
>>>     'xlim': (-1, 5),
>>>     'xticklabels': ['foo', 'bar'],
>>>     'xtick_rotation': 90,
>>> }
>>> ax = kwplot.multi_plot(ydata=ydata, fnum=4, **kwargs)
>>> kwplot.show_if_requested()
kwplot.next_fnum(new_base=None)[source]
kwplot.phantom_legend(label_to_color, mode='line', ax=None, legend_id=None, loc=0)[source]

Creates a legend on an axis based on a label-to-color map.

Parameters

label_to_color (Dict[str, kwimage.Color]) – mapping from string label to the color.

Todo

  • [ ] More docs and ensure this exists in the right place

kwplot.plot_convolutional_features(conv, limit=144, colorspace='rgb', fnum=None, nCols=None, voxels=False, alpha=0.2, labels=False, normaxis=None, _hack_2drows=False)[source]

Plots the convolutional layers to a matplotlib pyplot.

The convolutional filters (kernels) are stored into a grid and saved to disk as a Maplotlib figure. The convolutional filters, if it has one channel, will be stored as an intensity imgage. If a colorspace is specified and there are three input channels, the convolutional filters will be represented as an RGB image.

In the event that 2 or 4+ filters are displayed, the different channels will be flattened and showed as distinct outputs in the grid.

Todo

  • [ ] refactor to use make_conv_images

Parameters
  • conv (torch.nn.modules.conv._ConvNd) – torch convolutional layer with weights to draw

  • limit (int) – the limit on the number of filters drawn in the figure, achieved by simply dropping any filters past the limit starting at the first filter. Detaults to 144.

  • colorspace (str) – the colorspace seen by the convolutional filter (if applicable), so we can convert to rgb for display.

  • voxels (bool) – if True, and we have a 3d conv, show the voxels

  • alpha (float) – only applicable if voxels=True

  • stride (list) – only applicable if voxels=True

Returns

fig - a Matplotlib figure

Return type

matplotlib.figure.Figure

References

https://matplotlib.org/devdocs/gallery/mplot3d/voxels.html

Example

>>> # xdoctest: +REQUIRES(module:torch)
>>> conv = torch.nn.Conv2d(3, 9, (5, 7))
>>> plot_convolutional_features(conv, colorspace=None, fnum=None, limit=2)

Example

>>> # xdoctest: +REQUIRES(--comprehensive)
>>> # xdoctest: +REQUIRES(module:torch)
>>> import torchvision
>>> # 2d uncolored gray-images
>>> conv = torch.nn.Conv3d(1, 2, (3, 4, 5))
>>> plot_convolutional_features(conv, colorspace=None, fnum=1, limit=2)
>>> # 2d colored rgb-images
>>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
>>> plot_convolutional_features(conv, colorspace='rgb', fnum=1, limit=2)
>>> # 2d uncolored rgb-images
>>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
>>> plot_convolutional_features(conv, colorspace=None, fnum=1, limit=2)
>>> # 3d gray voxels
>>> conv = torch.nn.Conv3d(1, 2, (6, 4, 5))
>>> plot_convolutional_features(conv, colorspace=None, fnum=1, voxels=True,
>>>                             limit=2)
>>> # 3d color voxels
>>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
>>> plot_convolutional_features(conv, colorspace='rgb', fnum=1,
>>>                             voxels=True, alpha=1, limit=3)
>>> # hack the nice resnet weights into 3d-space
>>> # xdoctest: +REQUIRES(--network)
>>> import torchvision
>>> model = torchvision.models.resnet50(pretrained=True)
>>> conv = torch.nn.Conv3d(3, 1, (7, 7, 7))
>>> weights_tohack = model.conv1.weight[0:7].data.numpy()
>>> # normalize each weight for nice colors, then place in the conv3d
>>> for w in weights_tohack:
...     w[:] = (w - w.min()) / (w.max() - w.min())
>>> weights_hacked = weights_tohack.transpose(1, 0, 2, 3)[None, :]
>>> conv.weight.data[:] = torch.FloatTensor(weights_hacked)
>>> plot_convolutional_features(conv, colorspace='rgb', fnum=1, voxels=True, alpha=.6)
>>> plot_convolutional_features(conv, colorspace='rgb', fnum=2, voxels=False, alpha=.9)

Example

>>> # xdoctest: +REQUIRES(--network)
>>> # xdoctest: +REQUIRES(module:torch)
>>> import torchvision
>>> model = torchvision.models.resnet50(pretrained=True)
>>> conv = model.conv1
>>> plot_convolutional_features(conv, colorspace='rgb', fnum=None)
kwplot.plot_matrix(matrix, index=None, columns=None, rot=90, ax=None, grid=True, label=None, zerodiag=False, cmap='viridis', showvals=False, showzero=True, logscale=False, xlabel=None, ylabel=None, fnum=None, pnum=None)[source]

Helper for plotting confusion matrices

Parameters

matrix (ndarray | pd.DataFrame) – if a data frame then index, columns, xlabel, and ylabel will be defaulted to sensible values.

Todo

  • [ ] Finish args docs

  • [ ] Replace internals with seaborn

Example

>>> # xdoctest: +REQUIRES(module:pandas)
>>> from kwplot.mpl_draw import *  # NOQA
>>> import pandas as pd
>>> classes = ['cls1', 'cls2', 'cls3']
>>> matrix = np.array([[2, 2, 1], [3, 1, 0], [1, 0, 0]])
>>> matrix = pd.DataFrame(matrix, index=classes, columns=classes)
>>> matrix.index.name = 'real'
>>> matrix.columns.name = 'pred'
>>> plot_matrix(matrix, showvals=True)
>>> # xdoc: +REQUIRES(--show)
>>> import matplotlib.pyplot as plt
>>> import kwplot
>>> kwplot.autompl()
>>> plot_matrix(matrix, showvals=True)

Example

>>> # xdoctest: +REQUIRES(module:pandas)
>>> from kwplot.mpl_draw import *  # NOQA
>>> matrix = np.array([[2, 2, 1], [3, 1, 0], [1, 0, 0]])
>>> plot_matrix(matrix)
>>> # xdoc: +REQUIRES(--show)
>>> import matplotlib.pyplot as plt
>>> import kwplot
>>> kwplot.autompl()
>>> plot_matrix(matrix)

Example

>>> # xdoctest: +REQUIRES(module:pandas)
>>> from kwplot.mpl_draw import *  # NOQA
>>> matrix = np.array([[2, 2, 1], [3, 1, 0], [1, 0, 0]])
>>> classes = ['cls1', 'cls2', 'cls3']
>>> plot_matrix(matrix, index=classes, columns=classes)
kwplot.plot_surface3d(xgrid, ygrid, zdata, xlabel=None, ylabel=None, zlabel=None, wire=False, mode=None, contour=False, rstride=1, cstride=1, pnum=None, labelkw=None, xlabelkw=None, ylabelkw=None, zlabelkw=None, titlekw=None, *args, **kwargs)[source]

References

http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html

Example

>>> # DISABLE_DOCTEST
>>> import kwplot
>>> import matplotlib as mpl
>>> import kwimage
>>> shape=(19, 19)
>>> sigma1, sigma2 = 2.0, 1.0
>>> ybasis = np.arange(shape[0])
>>> xbasis = np.arange(shape[1])
>>> xgrid, ygrid = np.meshgrid(xbasis, ybasis)
>>> sigma = [sigma1, sigma2]
>>> gausspatch = kwimage.gaussian_patch(shape, sigma=sigma)
>>> title = 'ksize={!r}, sigma={!r}'.format(shape, (sigma1, sigma2))
>>> kwplot.plot_surface3d(xgrid, ygrid, gausspatch, rstride=1, cstride=1,
>>>                   cmap=mpl.cm.coolwarm, title=title)
>>> kwplot.show_if_requested()
kwplot.render_figure_to_image(fig, dpi=None, transparent=None, **savekw)[source]

Saves a figure as an image in memory.

Parameters
  • fig (matplotlib.figure.Figure) – figure to save

  • dpi (Optional[int | str]) – The resolution in dots per inch. If None it will default to the value savefig.dpi in the matplotlibrc file. If ‘figure’ it will set the dpi to be the value of the figure.

  • transparent (bool) – If True, the axes patches will all be transparent; the figure patch will also be transparent unless facecolor and/or edgecolor are specified via kwargs.

  • **savekw – other keywords passed to fig.savefig. Valid keywords include: facecolor, edgecolor, orientation, papertype, format, pad_inches, frameon.

Returns

an image in RGB or RGBA format.

Return type

np.ndarray

Note

Be sure to use fig.set_size_inches to an appropriate size before calling this function.

Example

>>> import kwplot
>>> fig = kwplot.figure(fnum=1, doclf=True)
>>> ax = fig.gca()
>>> ax.cla()
>>> ax.plot([0, 10], [0, 10])
>>> canvas_rgb = kwplot.render_figure_to_image(fig, transparent=False)
>>> canvas_rgba = kwplot.render_figure_to_image(fig, transparent=True)
>>> assert canvas_rgb.shape[2] == 3
>>> assert canvas_rgba.shape[2] == 4
>>> # xdoctest: +REQUIRES(--show)
>>> kwplot.autompl()
>>> kwplot.imshow(canvas_rgb, fnum=2)
>>> kwplot.show_if_requested()
kwplot.set_figtitle(figtitle, subtitle='', forcefignum=True, incanvas=True, size=None, fontfamily=None, fontweight=None, fig=None)[source]

A wrapper around subtitle that also sets the canvas window title if using a Qt backend.

Parameters
  • figtitle (str)

  • subtitle (str)

  • forcefignum (bool) – (default = True)

  • incanvas (bool) – (default = True)

  • fontfamily (None) – (default = None)

  • fontweight (None) – (default = None)

  • size (None) – (default = None)

  • fig (None) – (default = None)

CommandLine

python -m kwplot.mpl_core set_figtitle --show

Example

>>> # DISABLE_DOCTEST
>>> autompl()
>>> fig = figure(fnum=1, doclf=True)
>>> result = set_figtitle(figtitle='figtitle', fig=fig)
>>> # xdoc: +REQUIRES(--show)
>>> show_if_requested()
kwplot.set_mpl_backend(backend, verbose=None)[source]
Parameters

backend (str) – name of backend to use (e.g. Agg, PyQt)

kwplot.show_if_requested(N=1)[source]

Used at the end of tests. Handles command line arguments for saving figures

Referencse:

http://stackoverflow.com/questions/4325733/save-a-subplot-in-matplotlib