Как управлять 2D преобразованием Фурье (FFT) в 3D массиве с маской numpy?

#python #math #numpy #fft

#python #математика #numpy #fft

Вопрос:

У меня возникли проблемы с выполнением 2D быстрых преобразований Фурье в 3D массиве. Они имеют математическую природу и характер «понимания python / numpy».

РЕДАКТИРОВАТЬ: Для пояснения, основные вопросы: как numpy.fft справляется с массивами с маской? Могу ли я усреднить по оси, а затем выполнить БПФ и получить тот же результат, что и при выполнении БПФ, а затем усреднить по осям, которые не были задействованы в БПФ?

Массив состоит из значения потока двуокиси углерода (в «единицах») между атмосферой и океаном для каждого градуса широты и долготы (в определенной области). Форма массива (730, 50, 182) соответствует (времени, широте, долготе). Значения land маскируются с помощью:

 import numpy as np
from numpy import ma
carbon_flux = ma.masked_values(carbon_flux, 1e 20)
  

Я хотел бы показать логарифм дисперсии 2D преобразования Фурье carbon_flux, усредненной по долготе. Я усредняю массив по последней оси (долгота), а затем выполняю преобразование Фурье следующим образом:

 ft_type_1 = np.log(np.abs(np.fft.fft2(ma.mean(cflux, 2)))
  

Это дает мне приемлемый результат. Однако мне сказали сначала выполнить усреднение:

 ft_type_2 = np.log(np.mean(np.abs(np.fft.fft2(carbon_flux, axes=(0, 1))),axis=2)
  

Это приводит к тому, что маскированные значения используются для вычисления fft (я могу судить по первому значению fft порядка 10e19).

Насколько я понимаю, результат выполнения усреднения до fft будет отличаться от выполнения усреднения после fft. Прав ли я в предположении или не имеет значения, в каком порядке я выполняю эти функции?

Использует ли fft замаскированные значения? Могу ли я избежать этого?

Наконец, я вычислил логарифм 2D преобразования Фурье carbon_flux, усредненный по широте. Я не понимаю, как вычислить логарифм ДИСПЕРСИИ 2D преобразования Фурье, усредненного по широте. Нужно ли просто возводить значение моего результирующего изображения fft в квадрат, чтобы получить дисперсию?

Похоже, это очень сложная серия вопросов, но мы будем признательны за любую помощь в любом отделе. Спасибо.

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

1. Во-первых, я не знаю, как numpy.fft справляется со всем этим. Однако FT является линейной операцией, поэтому, пока вы усредняете данные перед получением абсолютного значения, это не должно иметь большого значения.

2. @aganders3 Спасибо. Да, похоже, это верно на практике. Две результирующие цифры почти точно совпадают. Интересно, откуда берутся небольшие различия?

Ответ №1:

После краткого просмотра документации, я думаю, numpy.fft можно просто проигнорировать маску. Я бы попробовал использовать ma.filled() функцию, чтобы поместить какое-то другое значение во все замаскированные записи.

Что-то вроде этого (взято из вашего примера кода):

 ft_type_1 = np.log(np.abs(np.fft.fft2(ma.mean(carbon_flux.filled(cflux_fill_value), 2)))
ft_type_2 = np.log(np.mean(np.abs(np.fft.fft2(carbon_flux.filled(cflux_fill_value), axes=(0, 1))),axis=2)
  

где cflux_fill_value есть какое-то разумное предположение, чтобы заменить замаскированные значения. Значение заполнения также можно задать на другом шаге (оно сохраняется как часть массива с маской), и тогда вы могли бы использовать carbon_flux.filled() без аргумента.

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

1. Под игнорированием, я полагаю, вы имеете в виду numpy. fft использует то, чем массив был до того, как он был замаскирован. Я заменил замаскированные значения carbon_flux на среднее значение: carbon_flux_data = ma.getdata(carbon_flux) тогда i= np.where(carbon_flux_data > 1e19) , тогда carbon_flux_data[i] = ma.mean(carbon_flux) . Даст ли это более точное значение для ft_type_1[0, 0], члена нулевой частоты (среднее значение сигнала)?

2. Короткий ответ: да, вероятно. Я не знаком с вашими данными, но, похоже, они были собраны с помощью некоторых датчиков, которые вышли из строя при нескольких измерениях, выдавая значения> 1e9. Правильно ли это? Поскольку вы не знаете там значений, вы должны угадать — замена на среднее значение является одним из вариантов, и может быть хорошим предположением. Другим вариантом было бы угадать эти точки на основе измерений из близлежащих времен / местоположений. Вы, вероятно, знаете больше о данных, поэтому я бы оставил вам, как лучше заполнить пробелы. Это может не иметь большого значения, в зависимости от того, сколько значений «отсутствует».

3. Кроме того, повторите: первую часть вашего поста. Я думаю, numpy.fft используется то, чем был массив до того, как он был замаскирован. Я думаю, что использование carbon_flux.filled(ma.mean(carbon_flux)) должно выполнять то же самое, что вы описали. Я предложил заполнение нулями, потому что это распространено в моей области (MRI), но, вероятно, не лучшая идея для вашего случая!

4. Спасибо! Замаскированные данные представляют значения суши, поскольку на суше нет газообмена воздух-море.