I have drawn two sets of axes which overlap, one being a zoomed version of the other. I want to draw lines between the corners of the zoomed axes and the corners of the rectangl
Not easily AFAIK, as you essentially want to define one point in one CS and the other in another (BlendedGenericTransform allows you to define your xs in one CS and ys in another, but not individual points).
As a result, the only solution I know of is to construct a transform which expects a certain number of points to transform. I've implemented a 2 point transformation class which transforms the first point given the first transform, and the second point with the other transform:
import matplotlib.transform as mtrans
class TwoPointTransformer(mtrans.Transform):
is_affine = False
has_inverse = False
def __init__(self, first_point_transform, second_point_transform):
self.first_point_transform = first_point_transform
self.second_point_transform = second_point_transform
return mtrans.Transform.__init__(self)
def transform_non_affine(self, values):
if values.shape != (2, 2):
raise ValueError('The TwoPointTransformer can only handle '
'vectors of 2 points.')
result = self.first_point_transform.transform_affine(values)
second_values = self.second_point_transform.transform_affine(values)
result[1, :] = second_values[1, :]
return result
With this I can then add a line expressed in the coordinates I care about:
line = plt.Line2D(xdata=(-45, 0), ydata=(-15, 0),
transform=TwoPointTransformer(ax1.transData, ax2.transAxes))
Note: I believe there to be an issue with the matplotlib caching of lines with non-affine transforms such as this. This problem manifests itself when we resize the figure. As a result, the simplest solution to this is to also add the line:
fig.canvas.mpl_connect('resize_event', lambda v: line.recache())
Which will re-compute the line each time the figure is resized.
This should do the trick for you.
HTH