Reputation: 1654
I am in the process of learning numpy. I wish to plot a graph of Planck's law for different temperatures and so have two np.array
s, T
and l
for temperature and wavelength respectively.
import scipy.constants as sc
import numpy as np
import matplotlib.pyplot as plt
lhinm = 10000 # Highest wavelength in nm
T = np.linspace(200, 1000, 10) # Temperature in K
l = np.linspace(0, lhinm*1E-9, 101) # Wavelength in m
labels = np.linspace(0, lhinm, 6) # Axis labels giving l in nm
B = (2*sc.h*sc.c**2/l[:, np.newaxis]**5)/(np.exp((sc.h*sc.c)/(T*l[:, np.newaxis]*sc.Boltzmann))-1)
for ticks in [True, False]:
plt.plot(B)
plt.xlabel("Wavelength (nm)")
if ticks:
plt.xticks(l, labels)
plt.title("With xticks()")
plt.savefig("withticks.png")
else:
plt.title("Without xticks()")
plt.savefig("withoutticks.png")
plt.show()
I would like to label the x-axis with the wavelength in nm. If I don't call plt.xitcks()
the labels on the x-axis would appear to be the index in to the array B (which holds the caculated values).
I've seen answer 7559542, but when I call plt.xticks()
all the values are scrunched up on the left of the axis, rather than being evenly spread along it.
So what's the best way to define my own set of values (in this case a subset of the values in l
) and place them on the axis?
Upvotes: 2
Views: 8565
Reputation: 69213
You can supply the x
values to plt.plot
, and let matplotlib take care of setting the tick labels.
In your case, you could plot plt.plot(l, B)
, but then you still have the ticks in m, not nm.
You could therefore convert your l
array to nm before plotting (or during plotting). Here's a working example:
import scipy.constants as sc
import numpy as np
import matplotlib.pyplot as plt
lhinm = 10000 # Highest wavelength in nm
T = np.linspace(200, 1000, 10) # Temperature in K
l = np.linspace(0, lhinm*1E-9, 101) # Wavelength in m
l_nm = l*1e9 # Wavelength in nm
labels = np.linspace(0, lhinm, 6) # Axis labels giving l in nm
B = (2*sc.h*sc.c**2/l[:, np.newaxis]**5)/(np.exp((sc.h*sc.c)/(T*l[:, np.newaxis]*sc.Boltzmann))-1)
plt.plot(l_nm, B)
# Alternativly:
# plt.plot(l*1e9, B)
plt.xlabel("Wavelength (nm)")
plt.title("With xticks()")
plt.savefig("withticks.png")
plt.show()
Upvotes: 3
Reputation: 131730
The problem is that you're not giving your wavelength values to plt.plot()
, so Matplotlib puts the index into the array on the horizontal axis as a default. Quick solution:
plt.plot(l, B)
Without explicitly setting tick labels, that gives you this:
Of course, the values on the horizontal axis in this plot are actually in meters, not nanometers (despite the labeling), because the values you passed as the first argument to plot()
(namely the array l
) are in meters. That's where xticks()
comes in. The two-argument version xticks(locations, labels)
places the labels at the corresponding locations on the x axis. For example, xticks([1], 'one')
would put a label "one" at the location x=1, if that location is in the plot.
However, it doesn't change the range displayed on the axis. In your original example, your call to xticks()
placed a bunch of labels at coordinates like 10-9, but it didn't change the axis range, which was still 0 to 100. No wonder all the labels were squished over to the left.
What you need to do is call xticks()
with the points at which you want to place the labels, and the desired text of the labels. The way you were doing it, xticks(l, labels)
, would work except that l
has length 101 and labels
only has length 6, so it only uses the first 6 elements of l
. To fix that, you can do something like
plt.xticks(labels * 1e-9, labels)
where the multiplication by 1e-9
converts from nanometers (what you want displayed) to meters (which are the coordinates Matplotlib actually uses in the plot).
Upvotes: 3
Reputation: 399
You need to use same size lists at the xtick
. Try setting the axis values separately from the plot value as below.
import scipy.constants as sc
import numpy as np
import matplotlib.pyplot as plt
lhinm = 10000 # Highest wavelength in nm
T = np.linspace(200, 1000, 10) # Temperature in K
l = np.linspace(0, lhinm*1E-9, 101) # Wavelength in m
ll = np.linspace(0, lhinm*1E-9, 6) # Axis values
labels = np.linspace(0, lhinm, 6) # Axis labels giving l in nm
B = (2*sc.h*sc.c**2/l[:, np.newaxis]**5)/(np.exp((sc.h*sc.c)/(T*l[:, np.newaxis]*sc.Boltzmann))-1)
for ticks in [True, False]:
plt.plot(B)
plt.xlabel("Wavelength (nm)")
if ticks:
plt.xticks(ll, labels)
plt.title("With xticks()")
plt.savefig("withticks.png")
else:
plt.title("Without xticks()")
plt.savefig("withoutticks.png")
plt.show()
Upvotes: 0