Извлечение данных из конвейера Mayavi, в частности, координат для заданной точки поверхности.

Я запускаю скрипт для создания цилиндрической поверхности, определяемой набором точек. Я использую Mayavi для визуализации визуализаций. Для следующего скрипта, как я могу найти координаты каждой точки? Кажется, что Mayavi делает это за кулисами в конвейере данных, но я не совсем уверен, как это извлечь. В качестве альтернативы я пытался выполнять вложенные циклы for, но я не понял правильного алгоритма... Тем временем я буду продолжать попытки. Однако, если кто-то знает, как извлечь их из пайплайна Mayavi, это было бы здорово, так как мне больше не придется добавлять время вычислений.

import numpy as np
import mayavi
from mayavi import mlab

class cylinder:
  def __init__(self, radius, length):
    phi, x = np.mgrid[0:np.pi:50j, 0:length:50j]
    self.z = radius * np.sin(phi)
    self.y = radius * np.cos(phi)
    self.x = x
    self.mesh = mlab.points3d(self.x,self.y,self.z, mode = 'point')


def main():
  cylinder = cylinder(radius=1,length=2)
  mayavi.mlab.axes()
  mlab.show()


main()

person CrypticParadigm    schedule 31.10.2018    source источник
comment
cylinder = cylinder(...) приведет к UnboundLocalError, поскольку cylinder квалифицировано как локальное имя из-за его появления в левой части, но оно отображается в правой части до того, как будет назначено. Не затеняйте такие имена, особенно нелокальные. Напишите что-то вроде cyl = cylinder(radius=1, lenth=2).   -  person Andras Deak    schedule 01.11.2018
comment
Я заметил, что за более чем полтора года активности здесь и 8 вопросов вы не приняли ни одного ответа на свои сообщения и не дали никаких отзывов ответчикам после беглого взгляда на некоторые из этих вопросов. Пожалуйста, рассмотрите возможность принятия ответов на свои старые вопросы, потому что это сигнализирует о том, что ваша проблема решена, а также повышает репутацию как вам, так и отвечающему. См. также Как работает принятие?.   -  person Andras Deak    schedule 01.11.2018
comment
Хорошо, спасибо, я так и сделаю.   -  person CrypticParadigm    schedule 01.11.2018


Ответы (1)


Все данные, которые вы передаете Mayavi, будут присутствовать в соответствующем источнике данных. Я хотел бы отметить, однако, что я бы не подумал, что вы часто захотите реконструировать свои данные из конвейера, поскольку именно вы передавали эти данные в первую очередь (поэтому вы должны иметь возможность отслеживать этих данных без необходимости копаться в низкоуровневом механизме vtk).

В любом случае, предполагая, что у вас есть только одна сцена и один источник данных в вашем конвейере:

engine = mlab.get_engine()
source = engine.scenes[0].children[0]
# choose a scene among engine.scenes if necessary
# choose a source among engine.scenes[0] if necessary

points_data = np.array(source.data.points)

В вашем конкретном примере вы передали три массива формы (50,50) в points3d. Что мы получаем для points_data, так это массив формы (2500,3). Подозрительный. Конечно же, мы можем изменить его в соответствующую форму, чтобы восстановить исходные данные:

x,y,z = points_data.T
# x,y,z have shape (2500,) now, no way to know the "true" original shape

# if we know what their shape _should_ be, we can fix that too:
x,y,z = points.data.reshape(50,50,3).transpose(2,0,1)

# compare to the original data
radius,length = 1,2
phi, x0 = np.mgrid[0:np.pi:50j, 0:length:50j]
z0 = radius * np.sin(phi)
y0 = radius * np.cos(phi)
print(np.array_equal(x, x0)) # True
print(np.array_equal(y, y0)) # True
print(np.array_equal(z, z0)) # True

Поскольку многомерная структура входных массивов не имеет отношения к Mayavi, я не ожидаю, что мы сможем восстановить исходные x,y,z массивы с правильной формой из конвейера. Если бы я был Mayavi, я бы ravel все входные массивы потерял всю возможную многомерную структуру, и я почти уверен, что именно это и происходит.

person Andras Deak    schedule 01.11.2018
comment
спасибо - я нашел способ, прежде чем вернуться к этому: dataset = mayavi.tools.pipeline.get_vtk_src(cylinder.mesh)[0] на следующей строке сделать datapoints = dataset.points.to_array() - person CrypticParadigm; 01.11.2018
comment
@physicsmajor, если у вас есть доступ к cylinder.mesh, то у вас есть доступ к cylinder.x, cylinder.y и cylinder.z. Что мне не хватает? - person Andras Deak; 01.11.2018
comment
Моя цель состояла в том, чтобы построить список координат для каждой точки, который был бы списком кортежей. Хотя у меня был доступ к cylinder.x, cylinder.y и cylinder.z, у меня возникли проблемы с составлением списка уникальных координат, поскольку cylinder.x/cylinder.y/cylinder.z являются вложенными массивами. Я уверен, что это можно сделать с помощью вложенных циклов for, но это было давно... Также может быть более эффективным извлечение из конвейера, поскольку Mayavi уже построил нужные мне данные (не в виде списка кортежей, а в виде массив массивов координат, что достаточно хорошо), поэтому мне не нужно писать дополнительный код. - person CrypticParadigm; 01.11.2018
comment
Вы согласны? - person CrypticParadigm; 01.11.2018
comment
@physicsmajor Я считаю, что вы ищете zip(cylinder.x.ravel(), cylinder.y.ravel(), cylinder.z.ravel()). Или это поместите внутрь list(), если вы не хотите просто перебирать их один раз. - person Andras Deak; 01.11.2018
comment
Или np.array([cylinder.x.ravel(), cylinder.y.ravel(), cylinder.z.ravel()]).T, если вас устраивает двумерный массив. - person Andras Deak; 01.11.2018
comment
Кажется, list(zip(cylinder.x.ravel(), cylinder.y.ravel(), cylinder.z.ravel())) это именно то, что я искал - спасибо! - person CrypticParadigm; 01.11.2018
comment
почему, когда я пытаюсь получить список координат только для поперечного сечения (то есть когда длина = 0), я получаю много дубликатов? - person CrypticParadigm; 01.11.2018
comment
@physicsmajor, потому что в этом случае вы, вероятно, используете np.mgrid[0:2*pi*50j, 0:0:50j], который во второй переменной аналогичен np.linspace(0,0,50), который содержит 50 нулей. Если вам нужно поперечное сечение, вам не нужен набор данных 2d, только набор 1d. Вместо того, чтобы создавать новую 2D-сетку с помощью length=0, вы должны смотреть на x==x0 подмножество вашей 2D-сетки. Таким образом, соответствующие точки, например, inds = x==0; x_section = x[inds]; y_section = y[inds], z_section = z[inds]. Отвечает ли это на ваш вопрос? - person Andras Deak; 02.11.2018
comment
Да. Я также исправил это, выполнив phi, x0 = np.mgrid[0:np.pi:50j, 0:length:1j] с длиной = 0, что дает мне то же самое. - person CrypticParadigm; 02.11.2018
comment
Здравствуйте-- У меня есть вопрос. Как я могу изменить цвет каждой точки? Я хотел бы сканировать или перебирать каждую точку (x, y, z) и передавать ее некоторой заранее определенной функции, которая будет проверять, удовлетворяет ли она некоторому заданному условию, если да, то ее цвет должен быть изменен. Есть ли способ получить доступ к текущей скалярной/цветовой информации и изменить ее? - person CrypticParadigm; 21.11.2018
comment
@physicsmajor изменение цвета существующего графика, вероятно, возможно, но сложно, и мне нужно хорошо изучить это, чтобы понять, как это сделать. С другой стороны, создать график с правильными цветами очень просто, просто передайте четвертый массив в качестве аргумента points3d с той же формой, что и координаты, и это будет использоваться для поиска цветов из карты цветов. Вы можете делать такие вещи, как c = np.where(self.x < self.z, 0, 1), чтобы создать двоичный массив, который даст вам два цвета на графике: один, где массив c равен 0, а другой - 1. - person Andras Deak; 21.11.2018