Drawing obtuse circular arc with arrowhead in matplotlib - python

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)

Related

Wobbling in matplotlib animation

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!")

How to create visual profiler?

I would like to visualize some statistics about a program's running time in Python. Unfortunately this program has written in Fortran and C++, and I cannot use any language specific visualization tool. From the output of the program I have created a class including the start time and the end time of different functions, and subroutines. For example:
class MyProgramRuntime:
def __init__(self):
self.foo1CallTime
self.foo1EndTime
self.foo2CallTime
self.foo2EndTime
I would like to get a similar plot like on the picture on the following link: Picture
I am not sure if is this the best solution, but it works really nice for me. I have used the matplotlib.patches lib to plot as long rectangles as the actual function/subroutine runned in seconds. The variables in the class are float variables, I got them by extracting from the actual datetime the datetime of the program's beginning with datetime.timedelta.total_seconds() . The plotting looks like the following:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
def plotRunningTimes(mpr): #mpr is an instance of the MyProgramRuntime class
fig = plt.figure()
ax = plt.subplot(111)
ax.add_patch( patches.Rectangle( (mpr.foo1CallTime, 0.1),
mpr.foo1EndTime-mpr.foo1Calltime,
0.1) )

Plot semilogx with matplotlib then convert it into Bokeh

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

How to plot a queue of points?

I have the following code.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.ion()
plt.show()
mapping = defaultdict(partial(deque, maxlen=10))
My mapping structure contains a queues with x, y, z values. I want to plot only the point in queue so as the queue changes the plot should also change. How would I do that?
Note: This is challenging because the queue is of a bounded size and the plot has to reflect only whats in the queue.
The hacky way to do this is:
ln, = ax.plot(x,y,z)
# some code that updates the x,y,z values -> new_x,new_y,new_z
ln.remove
ln, = ax.plot(new_x,new_y,new_z)
plt.draw()
which removes the line with the old data and adds one with the new data.
If you are willing to write code that depends on the internals of matplotlib (which is a bad idea as the internal will likely change under you), you can also do this by:
ln._verts3d = new_x,new_y,new_z
Patch here for added a function to do this: https://github.com/matplotlib/matplotlib/pull/1629
The animation module nicely wraps up many of the things needed to do animation (including a way to stream output directly to ffmpeg), and there is a very nice tutorial.
Line3D docs, Line2D docs

Plotting curved line in Python Basemap

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,

Categories