Adding lines and geometric shapes on matplotlib candlestick chart - python

I have made a candlestick currency chart on python using matplotlib.finance. Everything is working but I would like to add lines and shapes on the actual chart. When I was using normal type of chart in matplotlib. I would be doing:
plt.plot([xmin, xmax], [0.0005,0.0005], linewidth=3, color='purple')
To draw a horizontal line from xmin to xmax (to be defined) at the 0.0005 price level.But since I am using the method candlestick2_ohlc I don't really know how to proceed...
This is what I have:
This is what I am looking to get:
Also is it possible to draw and fill triangles?

Drawing segments
plt.plot([xmin, xmax], [ymin, ymax])
Drawing triangles
x = [x1, x2]
y = [y1, y2]
plt.fill(x,y)
Drawing polygons
x = [x1,...,xn]
y = [y1,...,yn]
plt.fill(x,y)
It's that easy!

The easiest way to draw a horizontal line is to use
plt.axhline(y=1.066)

Related

matplotlib vlines dynamic ymax parameter from seaborn distplot

I'm plotting a seaborn distplot from pandas dataframe as my initial working matplotlib canvas. Then to add more info to the canvas I'm using vlines as vertical markers.
However I didn't find a trivial way to define dynamic ymax param for vlines, since it is distribution dependent.
sns.distplot(data.values) # distribution chart
plt.vlines(x=[1,2], ymin=0, ymax=?)
Is there a way to pass the ymax acccording to the highest value in the chart? (so the plot height and the vertical lines height will be aligned). I considered something like:
plt.vlines(x=[1,2], ymin=0, ymax=data.values.max())
However the maximal value of data.values is actually represented on the X axis.
You may loop over the input points (useful if there aren't too many, say <=10)
for i in [1,2]:
ax.axvline(i)
Or you can supply a blended transform for the vlines,
ax.vlines(x=[1,2], ymin=0, ymax=1, transform=ax.get_yaxis_transform())
I found a way to retrieve the coordinates of the canvas:
dist = sns.distplot(data.values)
ymin,ymax = dist.get_ylim()
Then it's quite straightforward:
plt.vlines(x=[1,2], ymin=ymin, ymax=ymax)

Plotting 3-D surfaces and lines with perspective

I'm trying to plot a line through a 3-D surface as a means of indicating the axis. However, this only results in the line being plotted entirely on top of or beneath the surface--changing the zorder does not solve this.
What I'm looking for is for the line to appear as if it were piercing through the surface
My code and output are below:
fig = plt.figure(figsize=(9,9))
ax = plt.axes(projection='3d')
ax.plot_surface(X,Z,Y,
linewidth=0,
cmap=cm.jet,
facecolors=cm.jet(r_3d/max(abs(r_3d.flatten()))),
edgecolor='none',
shade=False,
antialiased=False)
ax.plot([0,0],[-0.3,0.3],[0,0],linewidth=2,c='k')
Example of line plotted on top of surface
Hand drawn example of my desired output
I think you can solve this with zorder (example here), though I have not tried specifically with a 3d plot. zorder changes the plotting order, or essentially the depth at which specific items are plotted. Large z orders plot on top and small ones plot in the back, so if you make the 3d item a z order of 1 and the line as z order zero that should work.

Shade the area between two axhline using matplotlib

What I'm trying to achieve: a plot with two axhline horizontal lines, with the area between them shaded.
The best so far:
ax.hline(y1, color=c)
ax.hline(y2, color=c)
ax.fill_between(ax.get_xlim(), y1, y2, color=c, alpha=0.5)
The problem is that this leaves a small amount of blank space to the left and right of the shaded area.
I understand that this is likely due to the plot creating a margin around the used/data area of the plot. So, how do I get the fill_between to actually cover the entire plot without matplotlib rescaling the x-axis after drawing? Is there an alternative to get_xlim that would give me appropriate limits of the plot, or an alternative to fill_between?
This is the current result:
Note that this is part of a larger grid layout with several plots, but they all leave a similar margin around these shaded areas.
Not strictly speaking an answer to the question of getting the outer limits, but it does solve the problem. Instead of using fill_between, I should have used:
ax.axhspan(y1, y2, facecolor=c, alpha=0.5)
Result:
ax.get_xlim() does return the limits of the axis, not that of the data:
Axes.get_xlim()
Returns the current x-axis limits as the tuple (left, right).
But Matplotlib simply rescales the x-axis after drawing the fill_between:
import matplotlib.pylab as pl
import numpy as np
pl.figure()
ax=pl.subplot(111)
pl.plot(np.random.random(10))
print(ax.get_xlim())
pl.fill_between(ax.get_xlim(), 0.5, 1)
print(ax.get_xlim())
This results in:
(-0.45000000000000001, 9.4499999999999993)
(-0.94499999999999995, 9.9449999999999985)
If you don't want to manually set the x-limits, you could use something like:
import matplotlib.pylab as pl
import numpy as np
pl.figure()
ax=pl.subplot(111)
pl.plot(np.random.random(10))
xlim = ax.get_xlim()
pl.fill_between(xlim, 0.5, 1)
ax.set_xlim(xlim)

Python: Matplotlib Surface_plot

I'm trying to Plot a high resolution surface_plot, but I would also really like some nice grid lines on top of it. If i use the gridlines in the same argument
ax.plot_surface(x_itp, y_itp, z_itp, rstride=1, cstride=1, facecolors=facecolors, linewidth=0.1)
I get a LOT of grid lines. If I, on the other hand, set "rstride" and "cstride" to higher values, my sphere will become ugly.
I then tried to smash a
ax.plot_wireframe(x_itp, y_itp, z_itp, rstride=3, cstride=3)
in afterwards, but it just lies on top of the colored sphere.. meaning that I can see the backside of the wireframe and then the surface_plot behind it all.
Have anyone tried this?
Another option was to use "Basemap" which can create a nice grid, but then I will have to adapt my colored surface to that.?!
My plot looks like this:
If I add edges to the map with a higher "rstride" and "cstride" then it looks like this:
code :
norm = plt.Normalize()
facecolors = plt.cm.jet(norm(d_itp))
# surface plot
fig, ax = plt.subplots(1, 1, subplot_kw={'projection':'3d', 'aspect':'equal'})
ax.hold(True)
surf = ax.plot_surface(x_itp, y_itp, z_itp, rstride=4, cstride=4, facecolors=facecolors)
surf.set_edgecolors("black")
I want to show the \theta and \phi angles around the sphere.. maybe with 30 degrees apart.
Cheers!
Morten
It looks like you may need to use basemap. With plot_surface() you can either have high resolution plot or low resolution with good grid on top. But not both. I just made a simple basemap with contour plot. I think you can do easily apply pcolor on it. Just do not draw continent and country boundary. Then, you have a nice sphere which gives more control. After making your plot, you can easily add grid on it.
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
map = Basemap(projection='ortho',lat_0=45,lon_0=-150)
map.drawmapboundary(fill_color='aquamarine')
map.drawmeridians(np.arange(0,360,30)) # grid every 30 deg
map.drawparallels(np.arange(-90,90,30))
nlats = 73; nlons = 145; delta = 2.*np.pi/(nlons-1)
lats = (0.5*np.pi-delta*np.indices((nlats,nlons))[0,:,:])
lons = (delta*np.indices((nlats,nlons))[1,:,:])
wave = 0.6*(np.sin(2.*lats)**6*np.cos(4.*lons))
mean = 0.5*np.cos(2.*lats)*((np.sin(2.*lats))**2 + 2.)
x, y = map(lons*180./np.pi, lats*180./np.pi) # projection from lat, lon to sphere
cs = map.contour(x,y,wave+mean,15,linewidths=1.5) # contour data. You can use pcolor() for your project
plt.title('test1')
plt.show()

pcolormesh () and contourf() do not work

Esteemed experts, am back with a problem I presented about two months ago, I have been working on it since with no success. This concerns superposition of contours on a basemap. I have looked at numerous examples on this, e.g. the example here: http://nbviewer.ipython.org/github/Unidata/tds-python-workshop/blob/master/matplotlib.ipynb
A sample of the data is on one of my previous posts, here: Contours with map overlay on irregular grid in python.
After preparing the data, here are plotting methods:
# Setting the plot size and text
fig = plt.figure(figsize=(10,8))
lev = [15, 20, 25, 30, 35, 40,45]
norm1 = colors.BoundaryNorm(lev, 256)
# Draw filled contours
# 1. pcolor does not show the filled contours
#cs = plt.pcolor(x,y,zi, cmap = cm.jet, norm = norm1)
# 2. pcolormesh does not show the filled contours
#cs = plt.pcolormesh(x,y,zi, shading = "flat", cmap=cmap)
# 3. contourf does not show the filled contours
#cs = plt.contourf(xi, yi, zi) #, levels=np.linspace(zi.min(),zi.max(),5))
cs = plt.contourf(xi, yi, zi, cmap = cm.jet, levels = lev, norm = norm1)
# 4. Draw line contours with contour()
#cs = m.contour(x,y,zi,linewidths=1.2) # This works
plt.scatter(data.Lon, data.Lat, c=data.Z, s=100,
vmin=zi.min(), vmax=zi.max()) # Does not work at all
# Color bar
#cbar = m.colorbar(fig,location='right',pad="10%")
fig.colorbar(cs)
# Plot a title
plt.figtext(.5,.05,'Figure 1. Mean Rainfall Onset Dates',fontsize=12,ha='center')
plt.show()
Sorry I am not able to post the plot examples, but:
pcolor, pcolormesh and contourf above all give a map without any filled contours but with a colorbar
the above plots without the map object give filled contours including scatter plot (without map background)
contour gives the map with contour lines superposed:
I am baffled because this is an example copy-pasted from the example in the link quoted above.
Any hint as to a possible cause of the problem would be appreciated
Zilore Mumba
you need to use the basemap to plot the contours vs using matplotlib.pyplot. see my example for some of my code.
#Set basemap and grid
px,py=n.meshgrid(x,y)
m=Basemap(projection='merc',llcrnrlat=20,urcrnrlat=55,
llcrnrlon=230,urcrnrlon=305,resolution='l')
X,Y=m(px,py)
#Draw Latitude Lines
#labels[left,right,top,bottom] 1=True 0=False
parallels = n.arange(0.,90,10.)
m.drawparallels(parallels,labels=[1,0,0,0],fontsize=10,linewidth=0.)
# Draw Longitude Lines
#labels[left,right,top,bottom] 1=True 0=False
meridians = n.arange(180.,360.,10.)
m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10,linewidth=0)
#Draw Map
m.drawcoastlines()
m.drawcountries()
m.drawstates()
m.fillcontinents(color='grey',alpha=0.1,lake_color='aqua')
#Plot Contour lines and fill
levels=[5.0,5.1,5.2,5.3,5.4,5.6,5.7,5.8,5.9,6.0]
cs=m.contourf(px,py,thickness,levels,cmap=p.cm.RdBu,latlon=True,extend='both')
cs2=m.contour(px,py,thickness,levels,latlon=True,colors='k')
#Plot Streamlines
m.streamplot(px,py,U,V,latlon=True,color='k')
#Add Colorbar
cbar = p.colorbar(cs)
cbar.add_lines(cs2)
cbar.ax.set_ylabel('1000 hPa - 500 hPa Thickness (km)')
#Title
p.title('Geostrophic Winds with Geopotential Thickness')
p.show()
Without knowing how your data look like it's a bit difficult to answer your question, but I'll try anyway. You might want to grid your data, for example, with an histogram, then contour the results.
For example, if you're interested in plotting 2D contours of points that have coordinates (x,y) and a third property (z) you want to use for the colors, you might give this a try
from numpy import *
H=histogram2d(x,y,weights=z)
contourf(H[0].T,origin='lower')
But, like I said, it's hard to understand what you're looking for if you're not giving details about your data. Have a look at the matplotlib guide for more examples http://matplotlib.org/examples/pylab_examples/contourf_demo.html

Categories

Resources