Matplotlib errorbar plot does not use marker cycling - python

In the following example, the error bar plot does not use the marker cycle specified in the axes rc, although it does use the color cycle. Specifying fmt rather than marker in the cycler throws an AttributeError: Unknown property fmt. How can I use the prop_cycle to specify the markers of an error bar plot? I am using Matplotlib 1.5.1 and Python 3.5.1.
import matplotlib.pyplot as plt
from cycler import cycler
plt.rc('axes', prop_cycle=cycler(color=['orange', 'violet', 'darkgreen'],
marker=['s', 'o', 'd']))
plt.rc('lines', linestyle=None)
plt.errorbar((0, 1), (1, 0), yerr=(0.1, 0.1))
plt.errorbar((0, 1), (0, 1), yerr=(0.1, 0.1))
plt.errorbar((0, 1), (0.5, 0.75), yerr=(0.1, 0.1))

Although this doesn't answer the question as posed, there are two ways to get around this using a prop_cycle. One is to simply use a for loop to construct the graphs. If you'd rather not use a for loop, you can define a generator function to yield values of the markers. This has the disadvantage that it doesn't automatically reset for every axis, but I think its easier to use than a for loop. The while True: statement is necessary to get it to loop back to the beginning as though it were a cycle of markers to use.
import matplotlib.pyplot as plt
from cycler import cycler
def mfunc(syms):
while True:
for s in syms:
yield s
markers = ['s', 'o']
mark = mfunc(markers)
plt.rc('axes', prop_cycle=cycler(color=['orange', 'violet', 'darkgreen']))
plt.rc('lines', linestyle=None)
plt.errorbar((0, 1), (1, 0), yerr=(0.1, 0.1), marker=next(mark))
plt.errorbar((0, 1), (0, 1), yerr=(0.1, 0.1), marker=next(mark))
plt.errorbar((0, 1), (0.5, 0.75), yerr=(0.1, 0.1), marker=next(mark))

Related

Quiver plot arrows using Matplotlib

I am trying to make a quiver plot using the list I4. In I4[0], (0,0) and (1,0) represent the starting position and the direction of the arrow respectively. However, the current output doesn't match the expected one. I attach both here.
import matplotlib.pyplot as plt
I4 = [[(0, 0), (1, 0)], [(0, 0), (0, -1)], [(1, 0), (1, -1)], [(0, -1), (1, -1)]]
fig, ax = plt.subplots(figsize = (10,10))
for i in range(0,len(I4)):
ax.quiver(I4[i][0], I4[i][1])
plt.show()
The current output is
The expected output is
Alternatively, you could use plt.arrow (doc here):
import matplotlib.pyplot as plt
I4 = [(0, 0),(1, 1),(0, 1), (0, 1)]
dI4=[(1,0),(0,-1),(1,0),(0,-1)]
texts=['(0,-1)','(1,-1)','(1,0)','(0,0)']
textxy=[(0,0),(1,0),(1,1),(0,1)]
fig, ax = plt.subplots(figsize = (10,10))
for i in range(len(I4)):
ax.arrow(I4[i][0], I4[i][1],dI4[i][0],dI4[i][1],length_includes_head=True,head_width=0.05,color='k',lw=3)
if i<2:
dy=-0.1
else:
dy=0.1
plt.text(textxy[i][0], textxy[i][1]+dy,texts[i],fontsize=20)
ax.set_aspect('equal')
ax.set_xlim([-0.5,1.5])
ax.set_ylim([-0.5,1.5])
plt.axis('off')
plt.show()
And the output gives:
Please, take a look at the documentation with help(ax.quiver): you'll see that you need to specify ax.quiver(x, y, u, v) where x, y are the starting coordinates, u, v represents the directions.
In practice, you need to unpack your lists, like this:
ax.quiver(*I4[i][0], *I4[i][1])

How to transform a matplotlib figure containing patches to a plotly figure?

I would like to integrate some figures containing patches in my plotly workflow. I generated them using matplotlib patches and try to transform the plot with plotly.tools.mpl_to_plotly. However, only regular plots seem to be converted using this function, my patches are lost.
Is there any way to convert patch containing plots into plotly?
Minimal (non-) working example using exemplary code from the matplotlib page:
import numpy as np
from matplotlib.path import Path
from matplotlib.patches import PathPatch
import matplotlib.pyplot as plt
import plotly.tools as tls
vertices = []
codes = []
codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY]
vertices = [(1, 1), (1, 2), (2, 2), (2, 1), (0, 0)]
codes += [Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY]
vertices += [(4, 4), (5, 5), (5, 4), (0, 0)]
vertices = np.array(vertices, float)
path = Path(vertices, codes)
pathpatch = PathPatch(path, facecolor='None', edgecolor='green')
fig, ax = plt.subplots()
ax.add_patch(pathpatch)
ax.set_title('A compound path')
ax.autoscale_view()
import plotly.tools as tls
tls.mpl_to_plotly(fig)
Thanks!

I want to plot perpendicular vectors in Python

I would like to simply plot perpendicular vectors in 2D. I've implemented 2 ways to plot them in the code below but the vectors don't "look" perpendicular to me when the plots are drawn. If it makes any difference I'm using Spyder.
import numpy as np
import matplotlib.pyplot as plt
x1=[0,0,4,3]
x2=[0,0,-3,4]
x3=[0,0,3,-4]
soa =np.array([x1,x2,x3])
X,Y,U,V = zip(*soa)
plt.figure()
ax = plt.gca()
ax.quiver(X,Y,U,V,angles='xy',scale_units='xy',scale=1)
ax.set_xlim([-10,10])
ax.set_ylim([-10,10])
plt.draw()
plt.show()
import pylab as pl
from matplotlib import collections as mc
lines = [[(0, 1), (4, 3)], [(-3, 4), (3, -4)]]
c = np.array([(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1)])
lc = mc.LineCollection(lines, colors=c, linewidths=2)
fig, ax = pl.subplots()
ax.add_collection(lc)
ax.autoscale()
ax.margins(0.1)
Your problem is that the size of the unit differs on the x and y axes. You need to force them to be equal.
In matplotlib.pyplot, add the line
plt.axes().set_aspect('equal')
just before you show the graph with
plt.show()
I get this result in the IPython console in Spyder:
In pylab, add the line
ax.set_aspect('equal')
at the end. However, these line segments still do not look perpendicular, and that is because they really are not perpendicular. The slope of your first, red line segment is 2/3, so your second, green line segment should have slope -3/2 but it actually has slope -4/3. Perhaps change your line to
lines = [[(0, 1), (4, 3)], [(-3, 4), (3, -5)]]
(I changed the ending -4 to -5) to get the correct second slope. You get a change from this first figure to the second:
and that last does look perpendicular.
The problem is the aspect ratio of the figure canvas.
Use:
plt.figure(figsize=(6,6))

Python annotation arrows with same headlength

I'm using matplotlib to create annotations with arrows.
from matplotlib import pyplot as plt
plt.figure()
plt.annotate('Text1', xy=(1, 0), xytext=(1, 1), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.annotate('Text2', xy=(3, 0), xytext=(3, 3), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.annotate('Text3', xy=(6, 0), xytext=(6, 6), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.annotate('Text4', xy=(9, 0), xytext=(9, 9), arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10))
plt.xlim((0, 10))
plt.ylim(0, 10)
plt.show()
As can be seen, the length of the arrow heads is affected by the line-length and varies between the arrows.
I'm looking for a way to create arrows with different line-lengths but equal arrow-headlengths.
Although many options are listed on the annotations manual page, i was not able to produce the desired result.
As an alternative approach i tried to plot the arrows seperatedely using plt.arrow. In that case the arrow heads looked as desired, but when using transparency, additional lines became visible.
Best regards, zinjaai
In the arrowprops you can't specify the length of the head, but the frac arguement specifies the length of the head as a fraction the arrow length. Since you know xy and xytext you can compute the necessary fraction for a desired headlength.
I've don't it quickly for the example you provided (with an head length of 0.5).
from matplotlib import pyplot as plt
plt.figure()
plt.annotate('Text1', xy=(1, 0), xytext=(1, 1),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/1))
plt.annotate('Text2', xy=(3, 0), xytext=(3, 3),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/3))
plt.annotate('Text3', xy=(6, 0), xytext=(6, 6),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/6))
plt.annotate('Text4', xy=(9, 0), xytext=(9, 9),
arrowprops=dict(alpha=0.5, fc='r', ec='r', headwidth=10, frac=0.5/9))
plt.xlim((0, 10))
plt.ylim(0, 10)
plt.show()
Result:
You could wrap this in a function, which computes the length of the arrow (given xy and xytext) and then passes that on to plt.annotate.

Plot counter of data points in matlpotlib

I have a matplotlib scatter plot like following.
import matplotlib.pyplot as plt
from pylab import plot,axis,show,pcolor,colorbar,bone
axiss = [(0, 0), (0, 1), (0, 0), (2, 2), (0, 2), (2, 2), (2, 0), (0, 2), (1, 2), (2, 0)]
x,y = zip(*axiss)
labels = ['u1', 'u2', 'u3', 'u4',
'u5', 'u6', 'u7', 'u8',
'u9', 'u10']
fig, ax = plt.subplots()
ax.scatter(x, y)
for i, txt in enumerate(labels):
ax.annotate(txt, (x[i],y[i]))
show()
Instead of labels I want to show how many data points are scattered on one point. For example in the data point I have marked in red, It should show '2'. And in the mouse hover event I need to see the labels. So in the example it should be 'u7' and 'u10'. Is it possible with matplotlib?
It got a little long, but I would first collect the unique element in axiss using set and count the number of each unique element. Then include that data into scatter's third argument, the size of the points. I would also annotate each points according the the number of datasets in that point.
Now the interactive annotation is a tricky part. I could not find mouse-hover event catcher, but you can do pretty much the same thing for mouse-clicking event. Save the first script on this page http://wiki.scipy.org/Cookbook/Matplotlib/Interactive_Plotting as interactive_annotations.py and import it in the script.
import matplotlib.pyplot as plt
from pylab import plot,axis,show,pcolor,colorbar,bone
import numpy as np
axiss = [(0, 0), (0, 1), (0, 0), (2, 2), (0, 2), (2, 2), (2, 0), (0, 2), (1, 2), (2, 0)]
# get unique elements
axiss_unique = list(set(axiss))
# get number of data at each datapoint
axiss_count = [axiss.count(x) for x in axiss_unique]
sc = 100 # scale up the datapoints for scatter
labels = [] # label each point according to number of data there
annotates = [] # intereactively label each point according to the datapoint name
for i in range(len(axiss_count)):
labels.append('%i'%axiss_count[i])
annotates.append( ' '.join(['u'+str(k) for k, j in enumerate(axiss) if j == axiss_unique[i]]))
axiss_count[i] *= sc
x,y = zip(*axiss_unique)
fig, ax = plt.subplots()
# get offsets of the labels to each point
x_os, y_os = max(x)/20., max(y)/20.
ax.scatter(x, y, axiss_count)
for i, txt in enumerate(labels):
ax.annotate(txt, (x[i]+x_os,y[i]+y_os), fontsize=15)
# interactive annotation
import interactive_annotations
af = interactive_annotations.AnnoteFinder(x,y, annotates)
connect('button_press_event', af)
show()
Result is something like this.
You can edit interactive_annotations.py to change the offset of the annotations, fonts, etc.

Categories

Resources