Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the meaning of clip_box in Matplotlib Artist?

I am testing the clip_box feature of Artist using the code snippet below:

import matplotlib.pyplot as plt
from matplotlib.transforms import Bbox
import numpy as np

fig = plt.figure()
ax = fig.subplots(1, 2)

x = [1, 2, 3, 4]
y = [3, 8, 5, 2]

line_a, = ax[0].plot(x, y, color='red', linewidth=3.0)
line_b, = ax[1].plot(x, y, color='red', linewidth=3.0)

boundingbox = Bbox(np.array([[0, 0], [3, 9]]))
line_b.set_clip_box(boundingbox)
line_b.set_clip_on(True)

plt.show()

What I expect is the last part of line_b will be cut out by the clip box, and line_b will be a bit shorter than line_a.

It turns out that there's nothing left on the second subplot. It's totally empty. Is my understanding of the clip_box wrong or are there some issues in the code snippet?

like image 671
olddon Avatar asked Sep 20 '25 16:09

olddon


1 Answers

The "natural" clip box for the right hand side plot is ax[1].bbox. Finding its extent tells us what units should be used to specify the clip box Bbox.

Since we don't add the Bbox instance to any axes when we create, it could only be relative to the figure. When we print ax[1].bbox, we can see that its size is to be specified in pixels.

It's indeed much simpler to use a Rectangle or Polygon to specify the clip box because they can be added to axes. Using 'none' color for its facecolor could be more convenient because it's figure style-independent.

import matplotlib.pyplot as plt
from matplotlib.transforms import Bbox

fig = plt.figure(dpi=89)
ax = fig.subplots(1, 2)

x = [1, 2, 3, 4]
y = [3, 8, 5, 2]

line_a, = ax[0].plot(x, y, color='red', linewidth=3.0)
line_b, = ax[1].plot(x, y, color='red', linewidth=3.0)

print(ax[1].bbox, '\n', ax[1].bbox.extents)
# the line above prints
# TransformedBbox(
#     Bbox(x0=0.5477272727272726, y0=0.10999999999999999, x1=0.8999999999999999, y1=0.88),
#     BboxTransformTo(
#         TransformedBbox(
#             Bbox(x0=0.0, y0=0.0, x1=6.393258426966292, y1=4.797752808988764),
#             Affine2D().scale(178.0))))
# [ 623.31363636   93.94       1024.2         751.52      ]
# 178.0 is 2 * dpi, I believe the doubling happens because of what screen I have got

boundingbox =  Bbox.from_extents([623.31363636, 93.94, 900.2, 751.52])
print(boundingbox, '\n', boundingbox.extents)
# the line above prints
# Bbox(x0=623.31363636, y0=93.94, x1=900.2, y1=751.52) 
# [623.31363636  93.94       900.2        751.52      ]
line_b.set_clip_box(boundingbox)
line_b.set_clip_on(True)

plt.show()
like image 162
Yulia V Avatar answered Sep 22 '25 05:09

Yulia V