I would like to plot curved/arced lines on a Basemap map.
I can plot a straight line using map.plot(x,y,..), but how do I make it curved/have arrows?
In matplotlib, this can be done using annotate(..), but Basemap doesn't have this method.
Any ideas?
This is a very old question, but I thought it might be good to answer anyway. When you said curved lines, I assumed you meant drawing a great circle. There is an example of doing exactly that in the basemap documentation, which I have modified to make a little more easy to modify yourself:
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
m = Basemap(projection='cyl')
p0_ll = -73.98, 40.78
p1_ll = 0.08, 51.53
m.drawgreatcircle(p0_ll[0], p0_ll[1], p1_ll[0], p1_ll[1],
linewidth=2, color='b')
m.drawcoastlines()
m.fillcontinents()
plt.show()
Note that the great circle method cannot handle the crossing of the edges of the map (as mentioned in the documentation), which, although clearly documented, is a pretty major flaw IMHO.
Hope that helps somebody,
Related
This is my first post, so I apologise if I am doing something wrong. I couldn't find any similar questions.
I am trying to generate an animation/video using matplotlib. The animation shows a dot moving along a curve. In my attempt to do this, I can see the point wobbling as it moves along the curve. How can I get rid of this effect? Here's a short script able to reproduce the effect and a gif animation. Thanks in advance
import numpy as np
import matplotlib.pyplot as plt
N=800#The bigger this number the worse the effect
s=np.linspace(0,2*np.pi,N)
xy=np.array([s,np.power(s,0.8)])#
plt.ion()
fig, ax=plt.subplots()
line1,=ax.plot(xy[0,:],xy[1,:],'-g')
t=0
ms=8
line2,=ax.plot(xy[0,t],xy[1,t],'or',markersize=ms)
ax.set_aspect('equal')
disc=1
M=N#int(N/2)
for lab in range(0,M,disc):
line1.set_xdata(xy[0,:])
line1.set_ydata(xy[1,:])
line2.set_xdata(xy[0,lab])
line2.set_ydata(xy[1,lab])
fig.canvas.draw()
fig.canvas.flush_events()
print("done!")
I plot a figure containing several curves using matplotlib and then try to convert it into bokeh:
import numpy as np
import matplotlib.pyplot as plt
from bokeh import mpl
from bokeh.plotting import show, output_file
num_plots = 6
colormap = plt.cm.gist_ncar
time = np.random.random_sample((300, 6))
s_strain = np.random.random_sample((300, 6))
def time_s_strain_bokeh(num_plots, colormap, time, s_strain):
plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, num_plots)])
plt.figure(2)
for i in range(0, num_plots):
plt.plot(time[:,i], s_strain[:,i])
plt.grid(True)
# save it to bokeh
output_file('anywhere.html')
show(mpl.to_bokeh())
time_s_strain_bokeh(num_plots, colormap, time, s_strain)
it works fine. However, I want to have a semilogx plot. When I change plt.plot in the "for" loop into plt.semilogx, I have the following error:
UnboundLocalError: local variable 'laxis' referenced before assignment
What can I do to change the x-axis onto log scale?
I'm with the same issue! 1/2 of the solution is this (supose my data is in a Pandas dataframe called pd):
pd.plot(x='my_x_variable', y='my_y_variable)
p = mpl.to_bokeh()
p.x_mapper_type='log' # I found this property with p.properties_with_values()
show(p)
I edited this answare because I just found part 2/2 of the solution:
When I use just the code above, the plot is semilog (ok!), but the x axis is flipped (mirrored)!!!
The solution I found is explicitly redefine xlim:
p.x_range.start=0.007 # supose pd['my_x_variable'] starts at 0.007
p.x_range.end=0.17 # supose pd['my_x_variable'] ends at 0.17
With this my plot became identical with the matplotlib original plot. The final code looks like:
pd.plot(x='my_x_variable', y='my_y_variable)
p = mpl.to_bokeh()
p.x_mapper_type='log'
p.x_range.start= pd['my_x_variable'].iloc[1] # numpy start at 0, take care!
p.x_range.end= pd['my_x_variable'].iloc[-1]
show(p)
As of Bokeh 0.12, partial and incomplete MPL compatibility is provided by the third party mplexporter library, which now appears to be unmaintained. Full (or at least, much more complete) MPL compat support will not happen until the MPL team implements MEP 25. However, implementing MEP 25 is an MPL project task, and the timeline/schedule is entirely outside of the control of the Bokeh project.
The existing MPL compat based on mplexporter is provided "as-is" in case it is useful in the subset of simple situations that it currently works for. My suggestion is to use native Bokeh APIs directly for anything of even moderate complexity.
You can find an example of a semilog plot created using Bokeh APIs here:
http://docs.bokeh.org/en/latest/docs/user_guide/plotting.html#log-scale-axes
I would like to know how to have proper axes on a 3D surface plot in MayaVi. The best axes I could create looked something like this...
However, these do not look very professional if I were to give a presentation or put these on a poster.
I would like the axes to look something like this...
These axes look much more professional and are easier to read than the default MayaVi axes.
Any help would be greatly appreciated.
Thanks!
I had this problem too.
I hacked a bad workaround by not displaying the mayavi axes, but plotting the axes I needed myself using plot3d()
from mayavi import mlab
import numpy as np
xx = yy = zz = np.arange(-0.6,0.7,0.1)
xy = xz = yx = yz = zx = zy = np.zeros_like(xx)
mlab.plot3d(yx,yy+lensoffset,yz,line_width=0.01,tube_radius=0.01)
mlab.plot3d(zx,zy+lensoffset,zz,line_width=0.01,tube_radius=0.01)
mlab.plot3d(xx,xy+lensoffset,xz,line_width=0.01,tube_radius=0.01)
You can now add labels and annotations using text3d()
Very inelegant and brute force, but works in a pinch.
As a result of a full day of trial and error, I'm posting my findings as a help to anyone else who may come across this problem.
For the last couple days, I've been trying to simulate a real-time plot of some radar data from a netCDF file to work with a GUI I'm building for a school project. The first thing I tried was a simple redrawing of the data using the 'interactive mode' of matplotlib, as follows:
import matplotlib.pylab as plt
fig = plt.figure()
plt.ion() #Interactive mode on
for i in range(2,155): #Set to the number of rows in your quadmesh, start at 2 for overlap
plt.hold(True)
print i
#Please note: To use this example you must compute X, Y, and C previously.
#Here I take a slice of the data I'm plotting - if this were a real-time
#plot, you would insert the new data to be plotted here.
temp = plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])
plt.draw()
plt.pause(.001) #You must use plt.pause or the figure will freeze
plt.hold(False)
plt.ioff() #Interactive mode off
While this technically works, it also disables the zoom functions, as well as pan, and well, everything!
For a radar display plot, this was unacceptable. See my solution to this below.
So I started looking into the matplotlib animation API, hoping to find a solution. The animation did turn out to be exactly what I was looking for, although its use with a QuadMesh object in slices was not exactly documented. This is what I eventually came up with:
import matplotlib.pylab as plt
from matplotlib import animation
fig = plt.figure()
plt.hold(True)
#We need to prime the pump, so to speak and create a quadmesh for plt to work with
plt.pcolormesh(X[0:1], Y[0:1], C[0:1])
anim = animation.FuncAnimation(fig, animate, frames = range(2,155), blit = False)
plt.show()
plt.hold(False)
def animate( self, i):
plt.title('Ray: %.2f'%i)
#This is where new data is inserted into the plot.
plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])
Note that blit must be False! Otherwise it will yell at you about a QuadMesh object not being 'iterable'.
I don't have access to the radar yet, so I haven't been able to test this against live data streams, but for a static file, it has worked great thus far. While the data is being plotted, I can zoom and pan with the animation.
Good luck with your own animation/plotting ambitions!
I am new to Python, though I do have previous programming experience. My current interest is to generate good quality schematics (and maybe later on also data graphs).
I need to draw a circlar arc with an arrowhead at the end point. I have sieved through many posts and tried my hand at a few examples, but it seems I still miss some basic knowledge. So I need something like this:
http://i.stack.imgur.com/Z5V86.png
I was experimenting with the example below, trying to initially plot a circular arc, but even this does not work. I am using matplotlib.patches but I am open to other suggestions for what I need.
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse, Arc
from matplotlib import cm, colors, patches
from math import pi
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ellipse = Arc([2.5,2.5],1,1,0,0,pi,color='green', linewidth='0.5')
ax.add_patch(ellipse)
plt.show()
Well,
if you want an angle of pi, pass 180.
linewidth must be a scalar. pass .5 and not '.5' as linewidth parameter
you need to change the limits of the axes, or you won't see the arc. Add something like ax.set_xlim(1.5,3.1) and ax.set_ylim(2.4,3.7).
You may also want to opt for another strategy, something like
ax.plot([.5],[.5],marker=r'$\circlearrowleft$',ms=100)