Only getting bottom of blackbody curve rather than whole function - math

I'm trying to plot the blackbody distribution at T = 2.73, I'm getting a curve but not a complete one and can only see the very bottom of the curve. Any suggestions? Here is my code:
import matplotlib.pyplot as plt
from numpy import *
from scipy import *
h=6.62606957e-34
c=2.998e8
k=1.3806488e-23
T = 100
f = arange(0,10000)
E = (8*h/(c**3.0))*(f**3.0)*(1/(exp((h*f)/(k*T))-1))
plt.plot(f, E*10000)
plt.title('Black-Body spectrum for T = 2.725K')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Energy Density (f)')
plt.show()

Use something like
x = linspace(0,12,1501)
f = 10**x
eterm = exp(-(h*f)/(k*T))
E = (2*h)/(c**2) * f**3 * eterm/(1-eterm)
I introduced the eterm exponential term to convert the overflow in the exponential into a less harmful underflow.
Check your sources and compare to wikipedia on Planck's law to get the right formula.
You can now also use
plot(x,E)
to get the x axis in log-scale, since if you get the right end of the x interval wrong, the graph will be uninformatively squished to the y axis.

Related

Plotting a Gaussian Convolution Graph

I'm writing a research paper on the SIFT algorithm, and I want to create a graphic to help explain the concept of a Gaussian blur in the context of continuous functions before I describe the discrete process. The graphic I want to create is a graph of a standard Gaussian convolved with a sine function. I can plot a Gaussian, and I can plot sine, but I don't know how to plot their convolution. I don't know how to calculate their convolution to plot it, and I don't know of any software that will allow me to use a convolution operator in the plot. I am familiar with tikz and gnuplot, but I would not know how to do this with either of them. Any suggestions as to how I could go about this would be greatly appreciated. Thanks.
You could use python's matplotlib and np.convolve
Please see the following code
__author__ = 'kgeorge'
import os
import numpy as np
import math
import matplotlib.pyplot as plt
from matplotlib import gridspec
#create gaussian for the x values in x-axis
def create_gaussian(x_axis):
sigma = 1.0
denom = math.sqrt(2 * math.pi) * sigma
twoSigmaSq = 2.0*sigma**2
e=np.zeros_like(x_axis)
for i,x in enumerate(x_axis):
e[i]=math.exp (-(x*x)/twoSigmaSq)
e = e / denom
return e
def main():
#x_axis
sz=100
halfW = int(sz/2)
x_axis=np.linspace(-halfW, halfW, 1000)
#cos fun
cos_f=np.cos(x_axis)
#gaussian
gaussian_f=create_gaussian(x_axis)
fig = plt.figure()
gs = gridspec.GridSpec(3, 1)
ax1 = fig.add_subplot(gs[0,0])
ax1.plot(x_axis, cos_f)
ax1.set_title('cos')
ax2 = fig.add_subplot(gs[1,0])
ax2.plot(x_axis, gaussian_f)
ax2.set_title('gaussian')
ax3 = fig.add_subplot(gs[2,0])
convolved_ret=np.convolve(cos_f, gaussian_f, mode='same')
ax3.plot(x_axis, convolved_ret)
ax3.set_title('cos convolved with gaussian')
gs.update(wspace=0.5, hspace=0.5)
plt.show()
Please see the output here.

clean up plot of tan(x)

I want to visualize the roots of tan(xi) = tanh(xi), xi>0 and my plot
plot(tan(pi*xi), tanh(pi*xi), (xi, 0, 4), ylim=(-1, 2))
comes out like this
where one sees the actual roots, xi_i \approx pi*(n+1/4), n=1, ... but also
fake roots at pi*(n+1/2), the reason why being sympy plotting algorithm that draws a vertical line between plus and minus infinity.
I tried to avoid the adaptive sampling and using a low sampling rate to no avail. Other programs, eg gnuplot, give me a more reasonable plot, at least in view of my concerns, that is...
Eventually my question is, is it possible to avoid those vertical lines in sympy's plot() function?
Sympy uses matplotlib as a backend for plotting; the root cause is that matplotlib connects the dots even around a singularity. If one plots with numpy, the direct access to y-values being plotted allows one to replace overly large numbers with nan or infinity. If staying within sympy, such tight control over numerics does not appear to be available. The best I could do is to split the range into a list of smaller ranges that do not include singularities, using the knowledge of the specific function tan(pi*x):
import math
from sympy import *
xi = symbols('xi')
xmin = 0
xmax = 4
ranges = [(xi, n-0.499, n+0.499) for n in range(math.ceil(xmin+0.5), math.floor(xmax+0.5))]
ranges.insert(0, (xi, 0, 0.499))
ranges.append((xi, math.floor(xmax+0.5) - 0.499, xmax))
plot((tanh(pi*xi), (xi, xmin, xmax)), *[(tan(pi*xi), ran) for ran in ranges], ylim=(-1, 2))
Output:
When a curve has singularities, it can plotted by segments, excluding the singularities. A tiny interval around the each singularity is built with math.nextafter(a,b) which returns a plus the smallest possible increment for a float, in direction of b.
from sympy import init_printing, symbols, plot
from sympy import singularities, Interval, tan, pi
from math import nextafter
init_printing()
x = symbols('x')
# The function to plot
y = tan(pi*x)
# Split x range at x singularities
min_x = next_x = 0
max_x = 4 # 4*pi
segments = []
undefs = singularities(y, x, domain=Interval(min_x, max_x))
for u in undefs:
# Add a subrange up to singularity for singularities within x range
if (u >= min_x) and (u <= max_x):
segments.append((x, next_x, nextafter(u, u-1)))
next_x = nextafter(u, u+1)
# Add last segment
if u <= max_x: segments.append((x, next_x, max_x))
# Plot all segments
plots = plot(*[(y, segment) for segment in segments], ylim=(-2,2), show=False)
plots.aspect_ratio = (1,1)
plots.show()
Of course you can use the same color for each curve segment.

trajectory of bullet, when there is a drag force

i tried to express the trajectory of bullet when there is a drag force.
however, i am not able to express the graph precisely.
how to depict trajectory from ode equation?.
this is my graph. this graph does not plausible. although i struggled setting different sign of vydot value, this is not working correctly.
from pylab import*
from scipy.integrate import odeint
import matplotlib.pyplot as plt
import numpy as np
g=10
m=1
k=0.01
y=zeros([2])
vy0=0
vydot=200
vx0=0
vxdot=200
y[0]=vy0
y[1]=vydot
x=zeros([2])
x[0]=vx0
x[1]=vxdot
t=linspace(0,1000,5000)
def fy(y,t):
g0=y[1]
g1=-k*y[1]
return array([g0,g1])
def fx(z,t):
g0=-x[1]
g1=-k*(x[1])-g
return array([g0,g1])
ans1=odeint(fy,y,t)
ans2=odeint(fx,x,t)
ydata=(ans1[:,])
xdata=(ans2[:,])
plt.plot(ydata,xdata)
show()"""
In air, as opposed to liquids, the bullet not only displaces the volume along its path, but also increases the impulse of the displaced air molecules proportional to the velocity. Thus the drag force is
vn=sqrt(vx²+vy²)
dragx = -k*vn*vx
dragy = -k*vn*vy
Thus use
def f(z,t):
x,y,vx,vy = z
vn = sqrt(vx*vx+vy*vy)
return array([vx, vy, -k*vn*vx, -k*vn*vy-g ])
For a first overview, consider the problem without drag. Then the solution is
x(t) = vx*t = 200m/s*t
y(t) = vy*t-g/2*t² = 200m/s*t - 5m/s²*t²
y(t)=0 is again met for t=2*vy/g at the x coordinate 2*vx*vy/g = 8000m. Maximum height is reached for t=vy/g at height vy²/(2g)=2000m.

IPython, Plotting a Polynomial

I've been working with Sympy for an Interpolation, in which I obtain as a result a 7th degree Polynomial (ax^7 + bx^6 + cx^5 + ...+ h) which I want to Plot, but wen I try to plot it I get errors, for example, if I try:
plt.plot(r,U.subs(x,r))
where r = np.linspace(0,20,num=100) and U = Polynomial(x);
the result is an error message: ValueError: sequence too large; must be smaller than 32, I obtain MemoryError: if I try `r = np.arange(20)'. The only way I could plot it is with a for cycle, substituting one by one and saving it in another variable as a list. So my question is, what is wrong with the first's inputs? is there an easy way to plot a polynomial?
Welcome to SO!
The subs() method is not meant to be used with numpy arrays. lambdify() does what you want. Try:
import numpy as np
import matplotlib.pyplot as plt
import sympy as sy
sy.init_printing() # nice formula rendering in IPython
x = sy.symbols("x", real=True)
# the sample polynomial:
pp = x**3 + 3*x**2 - 6*x - 8
# Convert expression function usable with numpy array:
f_pp = sy.lambdify(x, pp, modules=np)
# Do the plotting:
x_n = np.linspace(-5, 2, 500)
y_n = f_pp(x_n) # evaluate all x_n
fg, ax = plt.subplots(1, 1)
ax.plot(x_n, y_n)
fg.canvas.draw()
plt.show()
The parameter modules=np ensures, that numpy is used for functions in the expression (e.g., sin() => np.sin()). In this example, it is not explicitly needed.
PS: If you include a runnable example in your question, it makes live much easier for potential answerers.

griddata and polar plots

I am using matplotlib to fit some data to a grid and plot it as a polar projection. Something like in the example below. However, I want it to be smooth where the edges of the plot meet at 0/360 degrees. Anyone know how I do this??
from pylab import *
import random
x = linspace(0, 360, 361).astype(int)
x = x*pi/180
y = linspace(0.05, 0.5, 800)
xgrid, ygrid = meshgrid(x, y)
baz = []
for c in range(2000): baz.append(random.randint(0,360))
freq = rand(len(baz))
pwr = rand(len(baz))
zgrid = griddata(baz,freq,pwr, xgrid, ygrid)
subplot(111, polar=True)
pcolormesh(xgrid, ygrid, zgrid)
show()
Also the data I am working with has a gap due to the mask created by griddata (I use griddata as above but then sum many grids in a loop). I would like to fill the missing segment (see attached fig), does anyone know how to do this?
thanks
Dave
If you know which grids come together at the 0/360 degree position you could just concatenate them and do a spline interpolation on it (scipy interpolation).
For your second problem I am not sure but how about creating your grids in polar coordinates? Would this solve your problem?
Kind regards

Resources