Наиболее эффективный способ создания большого массива (x, y, z) координат - PullRequest
2 голосов
/ 09 октября 2019

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

theta_in  = 30.0 * np.pi/180.0
theta_out = 60.0 * np.pi/180.0
phi       = 2*np.pi # rotation
R = 1.0
sampling = 100

theta = np.linspace(theta_in,theta_out,sampling)
phi   = np.linspace(0,phi,sampling)
r     = np.linspace(-R,R,sampling)

x = []
y = []
z = []
for ri in r:
    for pi in phi:
         for ti in theta:
            xi = ri*np.cos(pi)*np.sin(ti)
            yi = ri*np.sin(pi)*np.sin(ti)
            zi = ri*np.cos(ti)
            x.append(xi)
            y.append(yi)
            z.append(zi)

Это приводит к следующему желаемому выводу:

enter image description here

Использование этих вложенных циклов для создания списков координат не очень эффективно. Мой вопрос: что было бы наиболее эффективным способом сделать это, возможно, избегая использования вложенных циклов for?

Ответы [ 2 ]

3 голосов
/ 09 октября 2019

Создать открытые сетки из этих входов и затем выполнить те же самые операции -

RI,PI,TI = np.ix_(r,phi,theta) # get open grids           
X = RI*np.cos(PI)*np.sin(TI)
Y = RI*np.sin(PI)*np.sin(TI)
Z = np.repeat(RI*np.cos(TI),sampling,axis=1)

Альтернатива # 1: Эти открытые сетки также могут быть построены с явным добавлением оси, например -

RI,PI,TI = r[:,None,None], phi[:,None], theta

Альтернатива # 2: мы можем предварительно вычислить np.sin(TI) и повторно использовать его в два этапа.

Альтернатива # 3: Кроме того, для транслируемой версии Z только для чтения мы можемиспользуйте np.broadcast_to -

Z = np.broadcast_to(RI*np.cos(TI),(sampling,sampling,sampling))

Альтернатива # 4: использование многоядерных процессоров с модулем numexpr -

import numexpr as ne

X = ne.evaluate('RI*cos(PI)*sin(TI)')
# similarly Y and Z

Обратите внимание, что выходные значения будут 3D массивами. Таким образом, чтобы получить эквивалентные, вы можете сгладить их. Для этого же мы можем использовать .ravel() на выходах.

0 голосов
/ 09 октября 2019
theta_in  = 30.0 * np.pi/180.0
theta_out = 60.0 * np.pi/180.0
phi       = 2*np.pi # rotation
R = 1.0
sampling = 100

theta = np.linspace(theta_in,theta_out,sampling)
phi   = np.linspace(0,phi,sampling)
r     = np.linspace(-R,R,sampling)

x=list(map(lambda ti,pi,ri:ri*np.cos(pi)*np.sin(ti),theta,phi,r))
y=list(map(lambda ti,pi,ri:ri*np.sin(pi)*np.sin(ti),theta,phi,r))
z=list(map(lambda ti,ri:ri*np.cos(ti),theta,r))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...