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.
Related
I am wondering whether it is possible to plot a vertical bar over a 2-dimensional representation of a graph. Say I have a tree and I want to associate with any node a "potential" which can be represented as a vertical bar.
NetworkX can do that using the matplotlib drawing tools because the result is a matplotlib figure on which you can use matplotlib to draw anything else you'd like on top of the networkx drawing of the graph.
nx.draw(G)
mpl.plot([xpt, xpt], [ymin, ymax], '--b')
mpl.show()
This is a minimal example which does what I was looking for (in Python):
import networkx as nx
import random
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
degree = 3
N = 10
g = nx.random_regular_graph(degree, N)
fig = plt.figure(figsize=(10,7))
ax = Axes3D(fig)
for i,j in enumerate(g.edges()):
x = np.array((positions[j[0]][0], positions[j[1]][0]))
y = np.array((positions[j[0]][1], positions[j[1]][1]))
ax.plot(x, y, c='black', alpha=0.5)
for key, value in positions.items():
xi = value[0]
yi = value[1]
# Scatter plot
ax.scatter(xi, yi, c= 'red')
ax.bar3d(xi, yi, 0, 0.01, 0, random.random(), shade=False)
ax.set_axis_off()
It generates this kind of plot, which can be useful to represent additional information on a graph
I have an RGB bitmap. Actually it is the contour plot of some scalar field plotted with the 'jet' colormap. I need to reverse the bitmap and obtain the source data. Is there a ready-to-use ond open-source tool for that? Python module is OK too.
Well, as nobody did it, this is a lasy algorithm that do the job:
import numpy as np
import scipy.misc
import matplotlib.pyplot as plt
## The digitized field will be scaled to range (0,1)
scale = np.linspace(0.0, 1.0, 300)
## Palette is a curve in RGB space
jet = plt.cm.get_cmap('jet')
palette = 255.0 * np.array([ jet(s)[:3] for s in scale ])
## Read the field as RGB image
field_0 = scipy.misc.imread('field.png')[:,:,:3]
ny, nx, _ = field_0.shape
## Use Euclidian norm to find a closest point in the palette
dist = lambda v : np.array([ np.linalg.norm(p - v) for p in palette ])
field = np.array([ [ scale[np.argmin(dist(field_0[i,j]))]
for j in range(nx) ]
for i in range(ny)[::-1] ])
## Plot
fig, ax = plt.subplots(1, 2)
ax[0].imshow(field_0)
ax[1].contourf(field, cmap='gray')
plt.show()
Thanks to everyone who cared.
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.
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.
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