Как правильно реализовать дискретное преобразование Фурье для сложных значений в Python?

#python #math #fft

Вопрос:

Я начинаю пробовать еще несколько интересных проектов на python, что привело меня к попытке создать программу, которая будет принимать текстовый файл с координатами x и y и создавать анимацию эпицикла, подобную этой. У меня уже есть функция, которая может нарисовать эпицикл с заданным центром, радиусом, частотой и фазой. Я подошел к биту «математика», выполнив дискретное преобразование Фурье в списке комплексных чисел(соответствующих координатам x-y). Вот мой код для DFT:

 def dft(vals):
  transformed=[]
  N=len(vals)
  for k in range(0,N):
    coeff=0
    upper_freq=0

    if k>N/2 :
        b=-k
    else:
        b=k

    for n in range(0,N):

        coeff =(vals[n]*(np.e**(-2*np.pi*1j*k*n*1/N)))
        
    transformed.append([coeff,b])

return transformed
 

Это дает мне список пар чисел, первое из которых-коэффициент, а второе-частота.Затем я прокручиваю этот список, чтобы получить радиус, фазу и частоту соответствующего эпицикла, как это :

 for item in weights:
  complex_no=item[0]
  rad=abs(complex_no)*2/(len(weights))
  final_freq=item[1]/len(weights)
  phase=math.atan(complex_no.imag/complex_no.real)
  if final_freq != 0:
    rad_freq.append([rad,final_freq,phase])
 

Кажется, это отлично работает для координат квадрата (созданных программно), но когда я пытаюсь использовать более сложный путь координат, циклер идет не так. Поэтому мой вопрос заключается в том, является ли первый код правильной реализацией DFT (я особенно не уверен в том, какие частоты являются отрицательными), и является ли это правильным способом извлечения информации о радиусе/фазе/частоте из координат DFT-ed ?

Квадрат правильно нарисован с помощью программы Выше:Квадрат, правильно нарисованный с помощью программы Предполагаемый ПутьВыше:Предполагаемый путь Фактический ПутьВыше:Фактический путь

Заранее большое спасибо, Крис


ОБНОВЛЕНИЕ Я обновил свой код DFT :

 `
def dft_1(vals):
    transformed=[]
    coeff=0
    N=len(vals)
    if N % 2==0:
        for k in range(int((-N/2)  1),int(N/2  1)):
            coeff=0
            for n in range(0,N):
                coeff =(vals[n]*(np.exp(-2*np.pi*1j*k*n*1/N)))
            transformed.append([coeff,k])
    else:
        for k in range(int(-(N-1)/2),int((N-1)/2)):
            for n in range(0,N):
                coeff =(vals[n]*(np.exp(-2*np.pi*1j*k*n*1/N)))
            transformed.append([coeff,k])
    return transformed


`
 

Однако это мало повлияло на код, поэтому я подозреваю, что это как-то связано с остальной частью моего кода рисования/анимации. Я создал проект GitHub для этого сейчас, чтобы другие могли посмотреть/ критиковать мой код: https://github.com/FourierFoibles/Fourier-Pygame — Я чрезвычайно благодарен тем, кто уже ответил, и тем, кто помогает в будущем.

Крис

Комментарии:

1. Хорошее использование графики. Возможно, вы можете начать с просмотра ответа, который вы получите с помощью библиотеки, а затем вернуться к своей реализации: pythonnumericalmethods.berkeley.edu/notebooks/… или это: hub.packtpub.com/…

2. @duffymo Спасибо! Я попробую это и попытаюсь вернуться и отредактировать об этом!

3. Правильный способ-использовать numpy.fft , а не изобретать велосипед заново.

4. @CrisLuengo Я пытаюсь узнать о DFT с помощью попытки реализации, и поэтому использование NumPy не будет большой помощью. Однако большое спасибо за предложение.

5. Вместо np.e**(…) того , чтобы делать np.exp(..) , что, вероятно, более точно. И пропустите внутренний цикл в пользу операций с массивом. Но я не вижу очевидной проблемы с вашим кодом DFT. Вы уверены, что код чертежа правильный?