Using a logarithmic scale in matplotlib - python-2.7

I have the following plot in which the X range is very wide and the shape of the graph near 1 MeV to 0.1 MeV is suppressed.
I want a plot where the X scale has equal separation (or equal grid) between 10,1,0.1 MeV.

You can use matplotlib's semilogx function instead of plot to make the x axis logarithmic.
Here's a short example:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.01,14,0.01)
y = np.log(100*x)
fig,(ax1,ax2) = plt.subplots(2)
ax1.plot(x,y)
ax1.set_xlim(x[-1],x[0])
ax1.set_title('plot')
ax2.semilogx(x,y)
ax2.set_xlim(x[-1],x[0])
ax2.set_title('semilogx')
plt.show()

also consider
ax.set_xscale("log")
http://matplotlib.org/examples/pylab_examples/aspect_loglog.html

Related

Plot an ellipse with python 2.7 knowing the equation

I have this equation, which define an ellipse.
7.91x^2 + -0.213xy + 5.46y^2 -0.031x -0.0896y = 1
Of the general form: Ax^2 + Bxy + Cy^2 + Dx +Ey = 1
I am using python 2.7 -- pythonxy
Of course, I tried by trying to solve an array of points x and y but it doesn’t work. I used the approach from this question in the following code, but it does not show the desired ellipse.
import numpy as np
import matplotlib.pyplot as plt
z = -np.linspace(-0.5,+0.5,1000)
x = np.linspace(-0.5,+0.5,1000)
x,z = np.meshgrid(x,z)
Z = -1 + 5.46*z**2
X = 7.91*x**2
plt.contour(x,z,(X+Z),[0])
plt.xlim([-0.6,0.6])
plt.ylim([-0.6,+0.6)
The code you show does not represent the equation of the ellipse. It's a bit hard to tell what exactly you were trying in that code, but the approach here is of course completely the same as in the linked question's answer, namely to calculate the left hand side of the equation with a meshgrid and show the level of the right hand side as a contour line.
import numpy as np
import matplotlib.pyplot as plt
x = -np.linspace(-0.5,+0.5,1000)
y = np.linspace(-0.5,+0.5,1000)
X,Y = np.meshgrid(x,y)
#equation: 7.91x^2 + -0.213xy + 5.46y^2 -0.031x -0.0896y = 1
eqn = 7.91* X**2 -0.213*X*Y + 5.46*Y**2 -0.031*X - 0.0896*Y
Z = 1
plt.contour(X,Y,eqn,[Z])
plt.xlim([-0.6,0.6])
plt.ylim([-0.6,+0.6])
plt.show()

Strange thick line in python plots?

I am using matplotlib.pyplot in python. Consider y-axis is real values called "ranking loss" and x-axis is the number of the iterations(1000). Then I plot the average ranking loss of 2 runs of an algorithm in each iteration.
Does anyone know why do I get this strange thick chart instead of a line?
Thank you very much in advance
And the command is :
fig = plt.figure()
fig.suptitle('Batch-GD', fontsize=20)
plt.xlabel('Iteration', fontsize=18)
plt.ylabel('Avg ranking loss', fontsize=16)
plt.grid(True)
plt.xlim(0, iter)
plt.plot(avg_loss)
fig.savefig('GD_with_ini.jpg')
plt.show()
What's happening here is probably, that your line density is so high that lines overlap in a way that a plain surface is shown instead of the line itself.
If we take e.g. 10000 points and make the plot oscillate at very high frequency, we get a similar behaviour. Zooming in shows that there actually is a line.
Code to reproduce the plot:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes, mark_inset
x = np.linspace(0,1000,num=10000)
y = np.sin(x*100.)*x/5000.+np.exp(-x/60.)+np.sin(x/50.)*0.016
plt.plot(x,y)
###### show inset ####
ax = plt.gca()
axins = inset_axes(ax, 2,2, loc=1)
axins.plot(x,y)
axins.set_xlim(400, 410)
axins.set_ylim(-0.1, 0.17)
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")
plt.show()
A solution can then be to calculate some kind of rolling average. E.g.:
def running_mean(x, N):
cumsum = np.cumsum(np.insert(x, 0, 0))
return (cumsum[N:] - cumsum[:-N]) / N
N=300
cumsum = running_mean(y, N)
ax.plot(x[N//2:-N//2+1], cumsum, c="orange")
axins.plot(x[N//2:-N//2+1], cumsum, c="orange")

Tight layout for matplotlib 3d surface plot

I am trying to create a 3d surface plot in matplotlib. the plot surface works fine using ax.plot_surface api. But I couldn't find a way to remove the padding surrounding the subplot. In fact, I don't need the outer axes that go from 0.0 to 1.0 at all. How can i remove the padding? I already tried many suggestions from stackoverflow like "ax.autoscale_view('tight')" and "fig.tight_layout()". autoscale_view don't change anything and fig.tight_layout() is not available in the matplotlib version i am using. For strict compatibility requirements i have to use a very old (Version 0.99) version of matplotlib. Any ideas ?
For completeness I have added a sample source code i am using:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize = (18,12))
rect = fig.add_subplot(2, 3, 2).get_position()
ax = Axes3D(fig, rect)
X = np.arange(-5, 5, 0.025)
Y = np.arange(-5, 5, 0.025)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet)
ax.view_init(azim=-90, elev=90)
ax.axis('off')
plt.show()

How to produce MATLAB plot (interpolation) in Matplotlib (Numpy)?

I am trying to follow a MATLAB example of meshgrid + interpolation. The example code is found HERE. On that site, I am going through the following example: Example – Displaying Nonuniform Data on a Surface.
Now, I would like to produce a similar plot in Python (Numpy + Matplotlib) to what is shown there in MATLAB. This is the plot that MATLAB produces:
I am having trouble with doing this in Python. Here is my code and my output in Python 2.7:
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
x = np.random.rand(200)*16 - 8
y = np.random.rand(200)*16 - 8
r = np.sqrt(x**2 + y**2)
z = np.sin(r)/r
xi = np.linspace(min(x),max(x), 100)
yi = np.linspace(min(y),max(y), 200)
X,Y = np.meshgrid(xi,yi)
Z = griddata(x, y, z, X, Y, interp='linear')
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1,cmap=cm.jet)
Here is the result of my attempt at doing this with matplotlib and NumPy..
Could someone please help me recreate the MATLAB plot in matplotlib, as either a mesh or a surface plot?
So it seems that the major differences in the look have to do with the default number of lines plotted by matlab, which can be adjusted by increasing rstride and cstride. In terms of color, in order for the colormap to be scaled properly it is probably best in this case to set your limits, vmin and vmax because when automatically set, it will use the min and max of Z, but in this case, they are both nan, so you could use np.nanmin and np.nanmax.
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
x = np.random.rand(200)*16 - 8
y = np.random.rand(200)*16 - 8
r = np.sqrt(x**2 + y**2)
z = np.sin(r)/r
xi = np.linspace(min(x),max(x), 100)
yi = np.linspace(min(y),max(y), 200)
X,Y = np.meshgrid(xi,yi)
Z = griddata(x, y, z, X, Y, interp='linear')
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=5, cstride=5, cmap=cm.jet, vmin=np.nanmin(Z), vmax=np.nanmax(Z), shade=False)
scat = ax.scatter(x, y, z)
In matplotlib unfortunately I get some annoying overlapping/'clipping' problems, where Axes3d doesn't always properly determine the order in which object should be displayed.

Any way to create histogram with matplotlib.pyplot without plotting the histogram?

I am using matplotlib.pyplot to create histograms. I'm not actually interested in the plots of these histograms, but interested in the frequencies and bins (I know I can write my own code to do this, but would prefer to use this package).
I know I can do the following,
import numpy as np
import matplotlib.pyplot as plt
x1 = np.random.normal(1.5,1.0)
x2 = np.random.normal(0,1.0)
freq, bins, patches = plt.hist([x1,x1],50,histtype='step')
to create a histogram. All I need is freq[0], freq[1], and bins[0]. The problem occurs when I try and use,
freq, bins, patches = plt.hist([x1,x1],50,histtype='step')
in a function. For example,
def func(x, y, Nbins):
freq, bins, patches = plt.hist([x,y],Nbins,histtype='step') # create histogram
bincenters = 0.5*(bins[1:] + bins[:-1]) # center bins
xf= [float(i) for i in freq[0]] # convert integers to float
xf = [float(i) for i in freq[1]]
p = [ (bincenters[j], (1.0 / (xf[j] + yf[j] )) for j in range(Nbins) if (xf[j] + yf[j]) != 0]
Xt = [j for i,j in p] # separate pairs formed in p
Yt = [i for i,j in p]
Y = np.array(Yt) # convert to arrays for later fitting
X = np.array(Xt)
return X, Y # return arrays X and Y
When I call func(x1,x2,Nbins) and plot or print X and Y, I do not get my expected curve/values. I suspect it something to do with plt.hist, since there is a partial histogram in my plot.
I don't know if I'm understanding your question very well, but here, you have an example of a very simple home-made histogram (in 1D or 2D), each one inside a function, and properly called:
import numpy as np
import matplotlib.pyplot as plt
def func2d(x, y, nbins):
histo, xedges, yedges = np.histogram2d(x,y,nbins)
plt.plot(x,y,'wo',alpha=0.3)
plt.imshow(histo.T,
extent=[xedges.min(),xedges.max(),yedges.min(),yedges.max()],
origin='lower',
interpolation='nearest',
cmap=plt.cm.hot)
plt.show()
def func1d(x, nbins):
histo, bin_edges = np.histogram(x,nbins)
bin_center = 0.5*(bin_edges[1:] + bin_edges[:-1])
plt.step(bin_center,histo,where='mid')
plt.show()
x = np.random.normal(1.5,1.0, (1000,1000))
func1d(x[0],40)
func2d(x[0],x[1],40)
Of course, you may check if the centering of the data is right, but I think that the example shows some useful things about this topic.
My recommendation: Try to avoid any loop in your code! They kill the performance. If you look, In my example there aren't loops. The best practice in numerical problems with python is avoiding loops! Numpy has a lot of C-implemented functions that do all the hard looping work.
You can use np.histogram2d (for 2D histogram) or np.histogram (for 1D histogram):
hst = np.histogram(A, bins)
hst2d = np.histogram2d(X,Y,bins)
Output form will be the same as plt.hist and plt.hist2d, the only difference is there is no plot.
No.
But you can bypass the pyplot:
import matplotlib.pyplot
fig = matplotlib.figure.Figure()
ax = matplotlib.axes.Axes(fig, (0,0,0,0))
numeric_results = ax.hist(data)
del ax, fig
It won't impact active axes and figures, so it would be ok to use it even in the middle of plotting something else.
This is because any usage of plt.draw_something() will put the plot in current axis - which is a global variable.
If you would like to simply compute the histogram (that is, count the number of points in a given bin) and not display it, the np.histogram() function is available