I have the following script in Python. I am calculating the Fourier Transform of an array. When I want to plot the results (Fourier transform) I am using the absolute value of that calculation.
However, I do not know how the absolute value of complex numbers is being produced.
Does anyone know how it calculates? I need this to reproduce in Java.
import numpy as np
import matplotlib.pyplot as plt
from numpy import fft
inp = [1,2,3,4]
res = fft.fft(inp)
print(res[1]) # returns (-2+2j) complex number
print(np.abs(res[1])) # returns 2.8284271247461903
np.abs gives magnitude of complex number i.e. sqrt(a^2 + b^2) in your case it's sqrt(8).
https://numpy.org/doc/stable/reference/generated/numpy.absolute.html
sqrt(Re(z)**2 + Im(z)**2)
for z = a + ib this becomes:
sqrt(a*a + b*b)
It's just the euclidean norm. You have to sum the square of real part and imaginary part (without the i) and do the sqrt of it.
https://www.varsitytutors.com/hotmath/hotmath_help/topics/absolute-value-complex-number
From numpy.absolute(arr, out = None, ufunc ‘absolute’) documentation:
This mathematical function helps user to calculate absolute value of each element.
For a complex number a+ib, the absolute value is sqrt(a^2 + b^2).
For complex valued pairs, a+ib, you can consider using the java Math static method hypot:
Math.hypot(a, b)
The method is an implementation of the Pythagorean theorem, sqrt(a*a + b*b) but additionally provides underflow and overflow protection.
Related
I'm a little confused by Python's calculation of variance. The results below show that variance calculated manually without Bessel's correction ("len(nums)" rather than "len(nums)-1") returns the same result as numpy's builtin var() function. Can anyone explain why this is?
# Create a sample list
import math
import numpy as np
nums = list(range(101))
# Compute the mean of the list
mean = np.mean(nums)
# Compute the variance manually
variance = sum(pow(x - mean, 2) for x in nums) / len(nums)
print (variance)
# Compute and print using var()
np_variance = np.array(nums).var()
print(np_variance)
Edit: I was under the impression the variance formula should use n-1 (Bessel's correction) in the denominator rather than just n (represented by len(nums) here). It looks like this alternative method that doesn't use Bessel's correction is the same as the one the builtin function uses, which doesn't seem right to me.
I need to use discrete Fourier transform (DFT) in Python (and inverse DFT) and the results I obtain are a bit weird, so I tried on a small example and I am not sure I understand the mistake (if it is math or coding). Here is my small version of the code:
from __future__ import division
import numpy as np
from pylab import *
pi = np.pi
def f(x):
return sin(x)
theta = np.arange(0,2*pi,2*pi/4)
k = np.arange(0,4,1)
x = f(theta)
y = np.fft.fft(x)
derivative = np.fft.ifft(1j*k*y)
print(derivative)
So what I do is to sample sin at 4 different points between 0 and 2pi and create with these numbers a vector x. Then I take the DFT of x to get y. What I want is to get the derivative of sin at the chosen points, so to do this I multiply y by k (the wave number, which in this case would be 0,1,2,3) and my the imaginary number 1j (this is because in the Fourier sum I have for each term something of the form e^{ikx}). So in the end I take the inverse DFT of 1jky and I am supposed to get the derivative of sin. But what I get is this.
[ -1.00000000e+00 -6.12323400e-17j -6.12323400e-17 +2.00000000e+00j
1.00000000e+00 +1.83697020e-16j 6.12323400e-17 -2.00000000e+00j]
when I was supposed to get this
[1,0,-1,0]
ignoring round-off errors. Can someone tell me what am I doing wrong? Thank you!
Manipulation of the spectrum must preserve this Hermitian symmetry if the inverse FFT is to yield result. Accordingly, the derivative operator in the frequency domain is defined over the lower half of the spectrum, and the upper half of the spectrum constructed from symmetry. Note that for spectrum of even sizes the value at exactly N/2 must be its own symmetry, hence must have a imaginary part which is 0. The following illustrate how to construct this derivative operator:
N = len(y)
if N%2:
derivative_operator = np.concatenate((np.arange(0,N/2,1),[0],np.arange(-N/2+1,0,1)))*1j
else:
derivative_operator = np.concatenate((np.arange(0,N/2,1),np.arange(-N//2+1,0,1)))*1j
You'd use this derivative_operator in the frequency-domain as follow:
derivative = np.fft.ifft(derivative_operator*y)
In your sample case you should then get the following result
[ 1.00000000e+00+0.j 6.12323400e-17+0.j
-1.00000000e+00+0.j -6.12323400e-17+0.j]
which is within roundoff errors of your expected [1,0,-1,0].
I wanted to compute the inverse Laplace transform manually without resorting to any library. Specifically, I wanted to compute a bilateral laplace inverse transform. I wanted to check my understanding and tried the following manually, but not able to match the answer. Where am I going wrong?
I want to compute laplace transform of 1/(s-a). I know the answer is eat. My attempt:
a = 2
t = 0.5
f = lambda s: 1/(s-a)
def g(u):
gammah=1
s = complex(real=gammah,imag=u)
return (f(s)).real*np.cos(s.imag*t) * 2*np.exp(s.real*t)/pi
import spicy as sp
import numpy as np
sp.integrate(g,0,np.inf,limit=10000)
gives me -0.9999999
but I know the answer is exp = 2.71...
The main error is mathematical. As Wikipedia says,
integration is done along the vertical line Re(s) = γ in the complex plane such that γ is greater than the real part of all singularities of F(s)
The function F(s) = 1/(s-a) has a singularity at a, which is 2 in your example. So γ needs to be greater than 2. For example, with γ=3 the output of quad is
(2.718278877362764, 2.911191228083254e-06)
as expected. By the, your import spicy etc can't possibly work, correct import syntax would be
from scipy.integrate import quad
# ....
quad(g, 0, np.inf, limit=10000)
Im trying to repoduce the fft functions in python. Iv'e seen a similar question Manual fft not giving me same results as fft here, but I'm having trouble seeing if i'm doing the same error or a different one.
import numpy as np
import numpy.random as npr
N=9 ### 10 -1
MC=10
###Genrate soem data
data=complex(1,0)*npr.uniform(size=(N,MC))+complex(0,1)*npr.uniform(size=(N,MC))
naive_fft=complex(1,0)*np.zeros((N,MC))
for K in range(N):
for m in range(N):
phase=(2*np.pi*K*m)/float(N+1)
naive_fft[K,:]=naive_fft[K,:]+data[m,:]*np.exp(complex(0,1)*phase)
fft=np.fft.fft(data,axis=0)
ifft=np.fft.ifft(data,axis=0)
print('fft')
print(naive_fft-fft)
print('ifft')
print(naive_fft-ifft*(N+1.0))
Comparing my results to the numpy fft i cannot reproduce neither fft nor ifft (only the naive_fft[0,:] seem to match the fft[0,:] values.
There are several things to mention. First of all, in Python we use 1j to represent the imaginary unit, not complex(0, 1). If you would like to compare your result to numpy, then you have to check how numpy implements the fft. See the Numpy FFT docs for details. You'll find that numpy follows the most common fft definition, which uses a negative exponent. Furthermore, float(N+1) in your phase is simply wrong. It must read N.
All in all you have:
# ...
naive_fft = np.zeros((N,MC), dtype='complex')
for K in range(N):
for m in range(N):
phase=(-2*np.pi*K*m) / float(N)
naive_fft[K] += data[m] * np.exp(phase*1j)
xfft = np.fft.fft(data, axis=0)
# ...
Test it with
>>> np.isclose(xfft, naive_fft).all()
True
The inverse transformation works analogously but with a positive exponent.
What function can I use in Python if I want to sample a truncated integer power law?
That is, given two parameters a and m, generate a random integer x in the range [1,m) that follows a distribution proportional to 1/x^a.
I've been searching around numpy.random, but I haven't found this distribution.
AFAIK, neither NumPy nor Scipy defines this distribution for you. However, using SciPy it is easy to define your own discrete distribution function using scipy.rv_discrete:
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
def truncated_power_law(a, m):
x = np.arange(1, m+1, dtype='float')
pmf = 1/x**a
pmf /= pmf.sum()
return stats.rv_discrete(values=(range(1, m+1), pmf))
a, m = 2, 10
d = truncated_power_law(a=a, m=m)
N = 10**4
sample = d.rvs(size=N)
plt.hist(sample, bins=np.arange(m)+0.5)
plt.show()
I don't use Python, so rather than risk syntax errors I'll try to describe the solution algorithmically. This is a brute-force discrete inversion. It should translate quite easily into Python. I'm assuming 0-based indexing for the array.
Setup:
Generate an array cdf of size m with cdf[0] = 1 as the first entry, cdf[i] = cdf[i-1] + 1/(i+1)**a for the remaining entries.
Scale all entries by dividing cdf[m-1] into each -- now they actually are CDF values.
Usage:
Generate your random values by generating a Uniform(0,1) and
searching through cdf[] until you find an entry greater than your
uniform. Return the index + 1 as your x-value.
Repeat for as many x-values as you want.
For instance, with a,m = 2,10, I calculate the probabilities directly as:
[0.6452579827864142, 0.16131449569660355, 0.07169533142071269, 0.04032862392415089, 0.02581031931145657, 0.017923832855178172, 0.013168530260947229, 0.010082155981037722, 0.007966147935634743, 0.006452579827864143]
and the CDF is:
[0.6452579827864142, 0.8065724784830177, 0.8782678099037304, 0.9185964338278814, 0.944406753139338, 0.9623305859945162, 0.9754991162554634, 0.985581272236501, 0.9935474201721358, 1.0]
When generating, if I got a Uniform outcome of 0.90 I would return x=4 because 0.918... is the first CDF entry larger than my uniform.
If you're worried about speed you could build an alias table, but with a geometric decay the probability of early termination of a linear search through the array is quite high. With the given example, for instance, you'll terminate on the first peek almost 2/3 of the time.
Use numpy.random.zipf and just reject any samples greater than or equal to m