Matplotlib: rotating a patch - python

I wanted to rotate a Rectangle in matplotlib but when I apply the transformation, the rectangle doesn't show anymore:
rect = mpl.patches.Rectangle((0.0120,0),0.1,1000)
t = mpl.transforms.Affine2D().rotate_deg(45)
rect.set_transform(t)
is this a known bug or do I make a mistake?

The patch in the provided code makes it hard to tell what's going on, so I've made a clear demonstration that I worked out from a matplotlib example:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib as mpl
fig = plt.figure()
ax = fig.add_subplot(111)
r1 = patches.Rectangle((0,0), 20, 40, color="blue", alpha=0.50)
r2 = patches.Rectangle((0,0), 20, 40, color="red", alpha=0.50)
t2 = mpl.transforms.Affine2D().rotate_deg(-45) + ax.transData
r2.set_transform(t2)
ax.add_patch(r1)
ax.add_patch(r2)
plt.xlim(-20, 60)
plt.ylim(-20, 60)
plt.grid(True)
plt.show()

Apparently the transforms on patches are composites of several transforms for dealing with scaling and the bounding box. Adding the transform to the existing plot transform seems to give something more like what you'd expect. Though it looks like there's still an offset to work out.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib as mpl
fig = plt.figure()
ax = fig.add_subplot(111)
rect = patches.Rectangle((0.0120,0),0.1,1000)
t_start = ax.transData
t = mpl.transforms.Affine2D().rotate_deg(-45)
t_end = t_start + t
rect.set_transform(t_end)
print repr(t_start)
print repr(t_end)
ax.add_patch(rect)
plt.show()

Related

matplotlib is returning empty plot

Click Here for the image
trying to plot an animated line chart in python. Why is this code returning to a blank white plot ? a guidance would be appreciated. And also if there is a better way to draw an animated line chart in Python, please suggest.Thank you.
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
x_data=[]
y_data =[]
fig,ax = plt.subplots()
ax.set_xlim(0,100)
ax.set_ylim(0,12)
line, = ax.plot(0,0)
def update(i):
x_data.append(i*10)
y_data.append(i)
line.set_xdata(x_data)
line.set_ydata(y_data)
return line,
animation = FuncAnimation(fig,func = update, frames = np.arange(0,10,0.01), interval =200)
plt.show()
The code works for me, but is very slow because you have added 1000 frames at 200ms intervals, so the full animation takes 200 seconds to complete.
You need the imports at the top (and the appropriate libraries installed)
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
x_data = []
y_data = []
fig, ax = plt.subplots()
ax.set_xlim(0, 100)
ax.set_ylim(0, 12)
line, = ax.plot(0, 0)
def update(i):
x_data.append(i*10)
y_data.append(i)
line.set_xdata(x_data)
line.set_ydata(y_data)
return line,
animation = FuncAnimation(fig,func = update, frames = np.arange(0, 10, 0.01), interval = 2)
plt.show()
I have set the interval to 2ms in the above code to show a faster animation.

Adding rectangles to a plot - doesn't show the right dimension [duplicate]

I'm trying to draw a rectangle in matplotlib using the following code:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
width = 20
height = 10
rect = patches.Rectangle((0,0),width, height, linewidth=4,edgecolor='r',facecolor='none')
ax.add_patch(rect)
plt.show()
Which results in:
The axes do not fit the rectangle limits in this case. I could solve it with:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
width = 20
height = 10
ax.set_xlim(0,width)
ax.set_ylim(0,height)
rect = patches.Rectangle((0,0),width, height, linewidth=4,edgecolor='r',facecolor='none')
ax.add_patch(rect)
plt.show()
This gives me the following picture which solves the problem in this case:
However, as I am trying to plot many rectangles and other shapes in the same figure, I need a way that matplotlib smartly determines the proper axes limits itself, like the way it does when plotting normal diagrams.
You are looking for .autoscale(). You may use .margins(0) to remove any extra space that is added by default.
I.e.
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig, ax = plt.subplots()
width = 20
height = 10
rect = patches.Rectangle((0,0),width, height, linewidth=4,edgecolor='r',facecolor='none')
ax.add_patch(rect)
ax.margins(0)
ax.autoscale()
plt.show()

Matplotlib issue with grid layout and shapes

Is it possible to create something like the picture? cause I just can't get it to work. Mine isn't showing shapes on the grid for some reason. Any help would be appreciated
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
import matplotlib.patches as mpatches
# Data for plotting
fig, ax = plt.subplots(1,figsize=(8,7))
#use add_patch instead, it's more clear what you are doing
ax.plot([1,5,2],[2,3,4],color="cyan")
rect = Rectangle((5,5),6,6, fill= False)
plt.gca().add_patch(rect)
ax.add_patch(rect)
plt.ylim(1400,2300)
plt.xlim(34,48)
plt.xlabel("inches")
plt.ylabel("weight (lbs)")
plt.title('Váha a vyváženie lietadla Cessna 172N')
plt.legend(["Utility","Normal category"])
plt.grid()
plt.plot
plt.show()

How do you scale a polygon patch in matplotlib?

In the example below, I create a rectangular patch using matplotlib.patches.Polygon. Is there a way to scale the patch before adding it to the plot?
I've tried using matplotlib.transforms.Affine2D in a variety of ways with no success. As usual, the matplotlib documentation on transformations is woefully insufficient.
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
poly = Polygon( zip(x,y), facecolor='red', edgecolor='red', alpha=0.5)
ax.add_patch(poly)
plt.show()
If by scale you mean multiplication by a factor, you can easily do this via numpy.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
scale = 2
poly = Polygon( np.c_[x,y]*scale, facecolor='red', edgecolor='red', alpha=0.5)
ax.add_patch(poly)
plt.show()
The same can be achieved with a matplotlib.transforms.Affine2D() transform.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import matplotlib.transforms as transforms
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot([-3,3],[-3,3])
x = [-1,0,1,1,0,-1]
y = [1,1,1,-1,-1,-1]
trans = transforms.Affine2D().scale(2) + ax.transData
poly = Polygon( np.c_[x,y], facecolor='red', edgecolor='red', alpha=0.5,
transform=trans)
ax.add_patch(poly)
plt.show()
Although it seems a bit overkill for a simple scaling like this.

How can I have one annotation pointing to several points in matplotlib?

I have some data that I usually plot in matplotlib. Certain values of the independent variable are resonances, and I want to label them with something resembling matplotlib's annotate. Is there a way to have one annotation (one balloon that says something like "resonances") with arrows that point to several points on the plot?
In this form is better to you?
import matplotlib.pyplot as plt
import numpy as np
a = np.ones(100)
multi = np.arange(0,100,5)
plt.ylim(-0.5,10)
plt.text(50, 6.5,'a=5k',fontsize=20)
for x in multi:
plt.annotate("",xy=(x,1),xytext=(50,6),
arrowprops=dict(facecolor='black', shrink=0.005))
plt.plot(a,'k.')
plt.show()
how about (basically ripped out of the docs http://matplotlib.org/users/annotations_intro.html)
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = ax.plot(t, s, lw=2)
coords_to_annote = [(2,1),(3,1),(4,1)]
for coords in coords_to_annote:
ax.annotate('local max', xy=coords, xytext=(3, 1.5),
arrowprops=dict(facecolor='black', shrink=0.05),
)
ax.set_ylim(-2,2)
plt.show()
You are looking for some similar to?
import matplotlib.pyplot as plt
import numpy as np
a = np.ones(100)
multi = np.arange(0,100,5)
plt.ylim(-0.5,10)
for x in multi:
plt.annotate("a=5k",xy=(x,1),xytext=(x,1+4*np.random.rand()),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.plot(a,'k.')
plt.show()

Categories

Resources