from scipy import ndimage
def GetPSD1D(psd2D):
h = psd2D.shape[0]
w = psd2D.shape[1]
wc = w//2
hc = h//2
# create an array of integer radial distances from the center
Y, X = np.ogrid[0:h, 0:w]
r = np.hypot(X - wc, Y - hc).astype(np.int)
# SUM all psd2D pixels with label 'r' for 0<=r<=wc
# NOTE: this will miss power contributions in 'corners' r>wc
psd1D = ndimage.sum(psd2D, r, index=np.arange(0, wc))
return psd1D
def GetRPSD(psd2D, dTheta, rMin, rMax):
h = psd2D.shape[0]
w = psd2D.shape[1]
wc = w//2
hc = h//2
# note that displaying PSD as image inverts Y axis
# create an array of integer angular slices of dTheta
Y, X = np.ogrid[0:h, 0:w]
theta = np.rad2deg(np.arctan2(-(Y-hc), (X-wc)))
theta = np.mod(theta + dTheta/2 + 360, 360)
theta = dTheta * (theta//dTheta)
theta = theta.astype(np.int)
# mask below rMin and above rMax by setting to -100
R = np.hypot(-(Y-hc), (X-wc))
mask = np.logical_and(R > rMin, R < rMax)
theta = theta + 100
theta = np.multiply(mask, theta)
theta = theta - 100
# SUM all psd2D pixels with label 'theta' for 0<=theta❤60 between rMin and rMax
angF = np.arange(0, 360, int(dTheta))
psd1D = ndimage.sum(psd2D, theta, index=angF)
# normalize each sector to the total sector power
pwrTotal = np.sum(psd1D)
psd1D = psd1D/pwrTotal
return angF, psd1D
https://medium.com/tangibit-studios/2d-spectrum-characterization-e288f255cc59
https://gist.github.com/TangibitStudios/47beaf24690329ac7fecddde70835ce9#file-getpsd1d-py
https://gist.github.com/TangibitStudios/ac423728f82d1564da0341e3e9fe22eb#file-getrpsd-py