Структура данных для ромбовидного массива в python - PullRequest
1 голос
/ 08 апреля 2020

У меня есть два массива, которые связаны друг с другом с помощью операции отображения. Я назову их S (f k , f q ) и Z (f i , α j ). Аргументы все частоты дискретизации. Правило отображения довольно простое:

f i = 0,5 · (f k - f q )
α j = f k + f q

S является результатом нескольких БПФ и сложных умножений и определяется в прямоугольной сетке angular. Тем не менее, Z определяется на ромбовидной сетке, и мне не ясно, как лучше всего это хранить. Изображение ниже представляет собой попытку визуализации операции для простого примера массива 4 × 4, но в целом размеры не равны и намного больше (возможно, 64 × 16384, но это выбирается пользователем). Синие точки - это результирующие значения f i и α j , а текст описывает, как они связаны с f k , f q и дискретные индексы. Diamond-shaped array representation Ромбовидная природа Z означает, что в одном «ряду» будут «столбцы», попадающие между «столбцами» смежных «рядов». Еще один способ думать об этом заключается в том, что f i может принимать значения дробного индекса!

Обратите внимание, что использование нулей или нанов для заполнения элементов, которые не существуют ни в одной данной строке, имеет два недостатка: 1) он увеличивает размер того, что уже может быть очень большим двумерным массивом, и 2) он на самом деле не отражает истинную природу Z (например, размер массива не будет правильным).

В настоящее время я использую словарь, индексированный по фактическим значениям α j для хранения результаты:

import numpy as np
from collections import defaultdict
nrows = 64
ncolumns = 16384
fk = np.fft.fftfreq(nrows)
fq = np.fft.fftfreq(ncolumns)
# using random numbers here to simplify the example
# in practice S is the result of several FFTs and complex multiplications
S = np.random.random(size=(nrows,ncolumns)) + 1j*np.random.random(size=(nrows,ncolumns))

ret = defaultdict(lambda: {"fi":[],"Z":[]})
for k in range(-nrows//2,nrows//2):
    for q in range(-ncolumns//2,ncolumns//2):
        fi = 0.5*fk[k] - fq[q]
        alphaj = fk[k] + fq[q]
        Z = S[k,q]
        ret[alphaj]["fi"].append(fi)
        ret[alphaj]["Z"].append(Z)

Я все еще нахожу это немного обременительным, чтобы работать с ним, и интересно, есть ли у кого-нибудь предложения для лучшего подхода? «Лучше» здесь будет определяться как более вычислительно и эффективнее памяти и / или легче взаимодействовать и визуализироваться с помощью чего-то вроде matplotlib.

Примечание: Это связано с другим вопросом о том, как избавиться от этих неприятных петель. Поскольку речь идет о сохранении результатов, я подумал, что было бы лучше создать два отдельных вопроса.

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Вы все еще можете просматривать его как прямой двумерный массив. Но вы можете представить в виде массива строк, каждая строка которого имеет разное количество элементов. Например, вот ваш 4x4 в виде 2D-массива: (каждый 0 здесь представляет собой уникальный элемент данных)

xxx0xxx
xx0x0xx
x0x0x0x
0x0x0x0
x0x0x0x
xx0x0xx
xxx0xxx

Его разреженное представление будет:

[
  [0],
  [0,0],
  [0,0,0],
  [0,0,0,0],
  [0,0,0],
  [0,0],
  [0]
]

С этим представлением Вы устраняете пустое пространство. Есть небольшая математика, связанная с преобразованием цветовой температуры в строку и спектральной частоты в столбец (и наоборот), но это легко поддается обработке. Вы знаете границы и предметы равномерно распределены по каждому ряду. Так что перевод должен быть достаточно легким.

Если я что-то упустил. , .

0 голосов
/ 13 апреля 2020

Оказывается, что ответ на связанный вопрос по оптимизации эффективно решил мою проблему о том, как лучше хранить данные. Новый код возвращает двумерные массивы для f i ,% alpha; j , и их можно использовать для прямого индексирования S. Таким образом, чтобы получить все значения S для% alpha; j = 0, например, можно сделать

S[alphaj == 0]

Я могу использовать это довольно эффективно, и это кажется самым быстрым способом создания разумной структуры данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...