0
votes

I looked into the matplotlib.transforms module but haven't figured out how to achieve all the following targets at the same time.

  1. plot a curve with x and y coordinates in list x and y.
  2. plot a rectangle (matplotlib.patches.Rectangle) that sticks to the bottom left corner
  3. width of the rectangle is 10% of horizontal axis (xmax-xmin).
  4. height is 1, meaning a unit height rectangle
  5. the rectangle sticks to the bottom left corner, when plot is moved/zoomed.
  6. the rectangle's width remains 10% of horizontal axis 0.1*(xmax-xmin) when zoomed
  7. the rectangle's height changes consistently with y-axis when zoomed.

It seems that along the horizontal direction, scale and position are both in axes.transAxes, which is easy to do. However, along the vertical direction, I need scale to be in axes.transData, but position in axes.transAxes. If I give up item 5, I can use the transforms.blended_transform_factory(), to have axes.transAxes on horizontal and axes.transData on vertical direction, in which case if I zoom, the height of the rectangle changes correctly, but it might go out-of-sight, either partially or completely, in the vertical direction.

Does anyone know if this is doable without hacking too much into matplotlib?

1

1 Answers

1
votes

You can subclass AnchoredOffsetbox to have an artist stay "anchored" at a specific position of the axes. See Anchored Artists demo

demonstration code:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.offsetbox import OffsetBox, AnchoredOffsetbox, AuxTransformBox
        
class AnchoredRectangle(AnchoredOffsetbox):
    def __init__(self, transform, width, height, loc, **rect_kwds):
        self._box = AuxTransformBox(transform)
        self.rectangle = Rectangle((0, 0), width, height, **rect_kwds)
        self._box.add_artist(self.rectangle)
        super().__init__(loc, pad=0, borderpad=0,
                         child=self._box, frameon=False)



fig, ax = plt.subplots()


r = AnchoredRectangle(ax.get_yaxis_transform(), width=0.1, height=1,
                         loc='lower left', color='green', alpha=0.5)

ax.add_artist(r)

ax.set_xlim(0,1)
ax.set_ylim(0,2)

plt.show()

enter image description here