¡Gran pregunta! Este fue un buen desafío y requiere una combinación de cosas para lograr.
En primer lugar, tenemos que inventar una transformación que devolverá las coordenadas del dispositivo de un valor predefinido más un desplazamiento basado en el punto dado. Por ejemplo, si sabemos que queremos la barra para estar en x_pt, y_pt, a continuación, la transformación debe representar (en pseudocódigo):
def transform(x, y):
return x_pt_in_device + x, y_pt_in_device + y
Una vez hecho esto, se podría utilizar esta transformación para dibujar un cuadro de 20 píxeles alrededor de un punto de datos fijo. Sin embargo, solo desea dibujar un cuadro de altura de píxel fija en la dirección y, pero en la dirección x desea una escala de datos estándar.
Por lo tanto, necesitamos crear una transformación combinada que pueda transformar las coordenadas xey de forma independiente. Todo el código para hacer lo que está pidiendo:
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.transforms as mtrans
import numpy as np
class FixedPointOffsetTransform(mtrans.Transform):
"""
Always returns the same transformed point plus
the given point in device coordinates as an offset.
"""
def __init__(self, trans, fixed_point):
mtrans.Transform.__init__(self)
self.input_dims = self.output_dims = 2
self.trans = trans
self.fixed_point = np.array(fixed_point).reshape(1, 2)
def transform(self, values):
fp = self.trans.transform(self.fixed_point)
values = np.array(values)
if values.ndim == 1:
return fp.flatten() + values
else:
return fp + values
plt.scatter([3.1, 3.2, 3.4, 5], [2, 2, 2, 6])
ax = plt.gca()
fixed_pt_trans = FixedPointOffsetTransform(ax.transData, (0, 2))
xdata_yfixed = mtrans.blended_transform_factory(ax.transData, fixed_pt_trans)
x = [3.075, 3.425] # x range of box (in data coords)
height = 20 # of box in device coords (pixels)
path = mpath.Path([[x[0], -height], [x[1], -height],
[x[1], height], [x[0], height],
[x[0], -height]])
patch = mpatches.PathPatch(path, transform=xdata_yfixed,
facecolor='red', edgecolor='black',
alpha=0.4, zorder=0)
ax.add_patch(patch)
plt.show()
No tengo tiempo para ordenarlo por completo, pero parece que será una forma de transformación combinada. Espero que esto ayude: http://matplotlib.sourceforge.net/users/transforms_tutorial.html#blended-transformations o al menos consigue que alguien comience por el camino correcto. – Paul