Я перевожу старый код IDL на Python. Я новичок и надеялся (все еще надеюсь), что, перейдя к IDL-коду, я смогу выучить язык быстрее. Я начал с того, что казалось «самой простой» функцией для переноса. Эта функция принимает заданный «psd» и создает из него смоделированную карту. Не совсем уверен, что означает «psd», но мы работаем в астрономическом контексте, поэтому, вероятно, можно с уверенностью предположить, что это означает спектральную плотность мощности... для наших целей это двумерный массив любой формы. Прежде чем взять код, генерирующий PSD-файл с искусственной атмосферой, я использовал массивы меньшего размера 2x3, 3x4 и 4x4. Дела шли... не совсем хорошо, но до того, как что-то сломалось, я продвинулся в коде дальше, чем сейчас. У меня довольно ограниченный опыт работы как с IDL, так и с numpy (astropy обычно обрабатывала за меня много вещей numpy, поэтому мне никогда не приходилось напрямую кодировать новые вещи), и поэтому я действительно изо всех сил пытаюсь понять, ЧТО не так. Проблема с исправлением этого возникает потому, что я НЕ ПОНИМАЮ, какие части кода IDL должны оставаться в Python.
Итак, ниже приведен код IDL и моя попытка перевести указанный код IDL в Python.
МВЛ:
lang-none
;we've allowed the map_ft too much freedom, so we need to make
;sure it will produce a real map
;obviously the dc component is real
map_ft[0,0] = sign(real_part(map_ft[0,0])) * abs(map_ft[0,0])
;if map_dim1 is divisible by 2 then we need to reverse
;along the extra column at the highest frequency
if (map_dim1 mod 2L) eq 0L then begin
map_ft[map_dim1/2L,0L] = sign(real_part(map_ft[map_dim1/2L,0L])) * $
abs(map_ft[map_dim1/2L,0L])
map_ft[map_dim1/2L,1L:(map_dim2/2L - 1L + (map_dim2 mod 2L))] = $
conj(reverse(reform(map_ft[map_dim1/2L,map_dim2/2L+1L:*])))
endif
Питон:
# we've allowed the map_ft too much freedom, so we need to make
# sure it will produce a real map
# obviously the dc component is real (no clue what dc means btw)
map_ft[0, 0] = np.sign(map_ft[0, 0].real) * np.abs(map_ft[0, 0])
print(row_len, ' // 2 + (', row_len % 2, ') = ', (row_len // 2 + (row_len % 2)))
#if col_len is divisible by 2 then we need to reverse
#along the extra column at the highest frequency
if (col_len % 2) == 0: # working on columns
mid_col = col_len // 2
map_ft[0, mid_col] = np.sign(map_ft[0, mid_col].real) * np.abs(map_ft[0, mid_col])
end_row = (row_len // 2 + row_len % 2)
map_ft[1 :row_len // 2 - 1 + (row_len % 2), mid_col] = \
np.conj(np.flip(np.squeeze(map_ft[row_len // 2 + 1 :, mid_col])))
Примечание: map_dim2, mapdim1 = row_len, col_len = psd.shape & map_ft
— это сложный массив, равный по форме PSD (в данном конкретном случае PSD — это массив размера (4096, 2048).
Ошибка возникает в строке np.conj(...) и гласит: ValueError: не удалось транслировать входной массив из формы (2047,) в форму (2046,).
Наконец, мы можем перейти к тому, в чем именно мне нужна помощь: мне интересно, насколько необходимо дословно переводить код IDL или есть ли более питонические или более чистые способы написания этого кода. Однако я не решаюсь упростить что-то самому, потому что с моими ограниченными знаниями это фактически означало бы отказ от исходного кода и попытку понять гораздо более сложные для изучения математические концепции, на которых был основан этот код (конечная цель - получить старый Код атмосферной фильтрации запущен и работает, поэтому я еще не усвоил много fft и страшной математики. Кроме того, прежде чем кто-нибудь спросит, у меня нет лицензии IDL (по крайней мере, пока) и, к сожалению, я не могу проверить, что делает код, когда. выполняется в IDL. А пока просто притворитесь, что это невозможно, и, надеюсь, это изменится.
Я был бы признателен за помощь в том, чтобы сделать этот код более питоническим, потому что я довольно быстро учусь, работая в обратном направлении, и любая помощь в переводе этого кода будет очень признательна.
Конечные точки среза IDL являются инклюзивными, а конечные точки среза Python — исключительными. Например, в IDL x[1:4]
извлекает подмассив длиной 4 (элементы с индексами 1, 2, 3, 4), а в Python x[1:4]
извлекает подмассив длиной 3 (элементы с индексами 1, 2, 3).
Имея это в виду, вам следует изменить это:
map_ft[1 :row_len // 2 - 1 + (row_len % 2), mid_col] = \
к этому:
map_ft[1 :row_len // 2 + (row_len % 2), mid_col] = \
Этот ответ был великолепен! Я ХОЧУ ДОБАВИТЬ ДЛЯ БУДУЩИХ ЧИТАТЕЛЕЙ: пятикратно проверьте, что делают ваши строки и столбцы, поскольку их порядок меняется в Python. Сначала я думал, что этот ответ не сработал, пока не понял, что один из моих переводов все еще вызывал столбцы в форме IDL, а не в форме numpy ([cols, rows] IDL против [rows, cols] numpy). Всегда проверяйте дважды, пожалуйста!