Compute 2D FFT in NumPy - numpy

I load image in NumPy using imageio and it loads in the format H x W x 3 where H and W are the spatial axes and 3 refers to RGB channels.
I wish to compute the images 2D FFT and use np.fft.fft2(img). I look at the documentation of np.fft.fft2 and it uses axes=(-2,-1). Does this mean that my FFT is being computed over the W and the 3 axes?
Will the correct way be np.fft.fft2(img,axes=(0,1))?

I am not sure about the solution that you suggest, but another option may be to calculate the transform for every color, do your processing, and merge again after if needed.
Something like this:
image_red, image_green, image_blue = imageio[:,:,0], imageio[:,:,1], imageio[:,:,2]
fft_red = np.fft.fft(image_red)
etc...
You can plot the proposed solution and this method to check the difference, for example:
import matplotlib.pyplot as plt
plt.figure('onlyRed')
plt.imshow(np.abs(fft_red))

Related

Generating a mouse heatmap with X, Y coordinates

I'm trying to use Python to generate a mouse heatmap using a large set of X, Y coordinates. I've imported the CSV using Pandas, here's the first few rows to get an idea of what it looks like:
X Y
0 2537 638
1 2516 637
2 2451 644
3 2317 652
4 2147 658
5 1999 647
I've tried using Matplotlib with not a lot of success, so swapped over to Seaborn to attempt to generate the heatmap that way. For reference, this is what I'm hoping to generate (with a different image in the background):
https://imgur.com/s5qiBsB
This is what my current code looks like:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import numpy as np
df = pd.read_csv(r'C:\Users\Jen\Desktop\mp.csv')
df[["x", "y"]] = pd.DataFrame.to_numpy(df)
matrix = np.zeros((df.x.max()+1, df.y.max()+1))
matrix[df.x, df.y] = df.index
sns.heatmap(matrix, cmap='jet')
plt.show()
With the following as a result:
https://imgur.com/12dMBsk
Obviously, this isn't exactly what I'm going for. First off, my x and y axes are swapped. What do I need to do to make my result look more like the example I provided? How do I create that blob effect around the different points?
More than happy to try anything at this point. This dataset is about 13,000 rows but I anticipate it will be even larger in the future.
(For reference, these were captured using 2 monitors, each at a resolution of 1650x1050, hence the large x values)

Plotting a 3-dimensional numpy array

I have a 3d numpy array with the shape (128,128,384). Let's call this array "S". This array only contains binary values either 0s or 1s.
\now \i want to get a 3d plot of this array in such a way that \ I have a grid of indices (x,y,z) and for every entry of S when it is one \ I should get a point printed at the corresponding indices in the 3d grid. e.g. let's say I have 1 entry at S[120,50,36], so I should get a dot at that point in the grid.
So far I have tried many methods but have been able to implement one method that works which is extremely slow and hence useless in my case. that method is to iterate over the entire array and use a scatter plot. \here is a snippet of my code:
from numpy import np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
for i in range(0,128):
for j in range(0,128):
for k in range(0,384):
if S[i,j,k]==1:
ax.scatter(i,j,k,zdir='z', marker='o')
Please suggest to me any method which would be faster than this.
Also, please note that I am not trying to plot the entries in my array. The entries in my array are only a condition that tells me if I should plot corresponding to certain indices.
Thank you very much
You can use numpy.where.
In your example, remove the for loops and just use:
i, j, k = np.where(S==1)
ax.scatter(i,j,k,zdir='z', marker='o')

Locally weighted smoothing for binary valued random variable

I have a random variable as follows:
f(x) = 1 with probability g(x)
f(x) = 0 with probability 1-g(x)
where 0 < g(x) < 1.
Assume g(x) = x. Let's say I am observing this variable without knowing the function g and obtained 100 samples as follows:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import binned_statistic
list = np.ndarray(shape=(200,2))
g = np.random.rand(200)
for i in range(len(g)):
list[i] = (g[i], np.random.choice([0, 1], p=[1-g[i], g[i]]))
print(list)
plt.plot(list[:,0], list[:,1], 'o')
Plot of 0s and 1s
Now, I would like to retrieve the function g from these points. The best I could think is to use draw a histogram and use the mean statistic:
bin_means, bin_edges, bin_number = binned_statistic(list[:,0], list[:,1], statistic='mean', bins=10)
plt.hlines(bin_means, bin_edges[:-1], bin_edges[1:], lw=2)
Histogram mean statistics
Instead, I would like to have a continuous estimation of the generating function.
I guess it is about kernel density estimation but I could not find the appropriate pointer.
straightforward without explicitly fitting an estimator:
import seaborn as sns
g = sns.lmplot(x= , y= , y_jitter=.02 , logistic=True)
plug in x= your exogenous variable and analogously y = dependent variable. y_jitter is jitter the point for better visibility if you have a lot of data points. logistic = True is the main point here. It will give you the logistic regression line of the data.
Seaborn is basically tailored around matplotlib and works great with pandas, in case you want to extend your data to a DataFrame.

Figures with lots of data points in matplotlib

I generated the attached image using matplotlib (png format). I would like to use eps or pdf, but I find that with all the data points, the figure is really slow to render on the screen. Other than just plotting less of the data, is there anyway to optimize it so that it loads faster?
I think you have three options:
As you mentioned yourself, you can plot fewer points. For the plot you showed in your question I think it would be fine to only plot every other point.
As #tcaswell stated in his comment, you can use a line instead of points which will be rendered more efficiently.
You could rasterize the blue dots. Matplotlib allows you to selectively rasterize single artists, so if you pass rasterized=True to the plotting command you will get a bitmapped version of the points in the output file. This will be way faster to load at the price of limited zooming due to the resolution of the bitmap. (Note that the axes and all the other elements of the plot will remain as vector graphics and font elements).
First, if you want to show a "trend" in your plot , and considering the x,y arrays you are plotting are "huge" you could apply a random sub-sampling to your x,y arrays, as a fraction of your data:
import numpy as np
import matplotlib.pyplot as plt
fraction = 0.50
x_resampled = []
y_resampled = []
for k in range(0,len(x)):
if np.random.rand() < fraction:
x_resampled.append(x[k])
y_resampled.append(y[k])
plt.scatter(x_resampled,y_resampled , s=6)
plt.show()
Second, have you considered using log-scale in the x-axis to increase visibility?
In this example, only the plotting area is rasterized, the axis are still in vector format:
import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(size=400000)
y = np.random.uniform(size=400000)
plt.scatter(x, y, marker='x', rasterized=False)
plt.savefig("norm.pdf", format='pdf')

Contour plotting orbitals in pyquante2 using matplotlib

I'm currently writing line and contour plotting functions for my PyQuante quantum chemistry package using matplotlib. I have some great functions that evaluate basis sets along a (npts,3) array of points, e.g.
from somewhere import basisset, line
bfs = basisset(h2) # Generate a basis set
points = line((0,0,-5),(0,0,5)) # Create a line in 3d space
bfmesh = bfs.mesh(points)
for i in range(bfmesh.shape[1]):
plot(bfmesh[:,i])
This is fast because it evaluates all of the basis functions at once, and I got some great help from stackoverflow here and here to make them extra-nice.
I would now like to update this to do contour plotting as well. The slow way I've done this in the past is to create two one-d vectors using linspace(), mesh these into a 2D grid using meshgrid(), and then iterating over all xyz points and evaluating each one:
f = np.empty((50,50),dtype=float)
xvals = np.linspace(0,10)
yvals = np.linspace(0,20)
z = 0
for x in xvals:
for y in yvals:
f = bf(x,y,z)
X,Y = np.meshgrid(xvals,yvals)
contourplot(X,Y,f)
(this isn't real code -- may have done something dumb)
What I would like to do is to generate the mesh in more or less the same way I do in the contour plot example, "unravel" it to a (npts,3) list of points, evaluate the basis functions using my new fast routines, then "re-ravel" it back to X,Y matrices for plotting with contourplot.
The problem is that I don't have anything that I can simply call .ravel() on: I either have 1d meshes of xvals and yvals, the 2D versions X,Y, and the single z value.
Can anyone think of a nice, pythonic way to do this?
If you can express f as a function of X and Y, you could avoid the Python for-loops this way:
import matplotlib.pyplot as plt
import numpy as np
def bf(x, y):
return np.sin(np.sqrt(x**2+y**2))
xvals = np.linspace(0,10)
yvals = np.linspace(0,20)
X, Y = np.meshgrid(xvals,yvals)
f = bf(X,Y)
plt.contour(X,Y,f)
plt.show()
yields