построить данные, хранящиеся в файле, используя (mayavi) mlab.contour3d?

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

   x1   y1    z1    val(x1,y1,z1)  
   x1   y1    z2    val(x1,y1,z2)  
    .    .     .       .  
   x1   y1     z_K  val(x1,y1,z_K)  

   x1   y2     z1    val(x1,y2,z1)  
    .    .     .       .  
    .    .     .       .  
   x_L   y_M    z_K    val(x_L,y_M,z_K)  

(Здесь первые 3 значения в каждой строке дают координаты (x, y, z) точки, а 4-е значение дает значение скаляра в этой точке. Я могу вставить минимальный файл примера, если это полезно)

Файл данных можно успешно прочитать с помощью numpy.loadtxt, но как мне оттуда перейти к построению изоповерхности с помощью (mayavi) mlab.contour3d? Я думаю, что выходной массив по умолчанию из loadtxt находится в неправильном формате для mlab.contour3d.

Все примеры mlab.contour3d, которые мне удалось найти, генерируют сетку с использованием ogrid, а затем строят простую функцию (sin и т. Д.) Этой сетки. Я смог успешно запустить эти примеры, но они не говорят мне, как читать данные из файла в правильный формат массива, готового для построения. Я уверен, что очень многим новичкам в подобной должности было бы полезно, если бы кто-нибудь дал мне указатель; Построение трехмерных данных, хранящихся в файле, созданном другой программой, несомненно, должно быть одной из наиболее распространенных задач построения графиков, которые должны выполнять ученые.


person user3390991    schedule 07.03.2014    source источник
comment
Было бы полезно, если бы вы могли добавить некоторые образцы данных (например, несколько строк из вашего файла данных) и свой код, который читает файл. Затем люди могут показать вам, как перейти от этого к рабочему решению.   -  person YXD    schedule 07.03.2014


Ответы (2)


Я обнаружил, что следующее работает хорошо.

x, y, z, d - одномерные массивы numpy из необработанного текстового файла ввода, где d = f (x, y, z)

# Import relevant modules
import numpy as np
import scipy.interpolate as si
from mayavi import mlab

# Generate the figure
figure = mlab.figure()

# Generate the 3D mesh
xi, yi, zi = np.meshgrid(*([np.linspace(0,1,100)] * 3))

# Interpolate d over the 3D mesh
di = si.griddata((x, y, z), d, (xi, yi, zi))

# Generate the desired figure
min_d = d.min()
max_d = d.max()
grid = mlab.pipeline.scalar_field(di)
mlab.pipeline.volume(grid, vmin=min_d, vmax=min_d + .5*(max_d-min_d))

# Other good options too
## mlab.contour3d(di, vmin=min_d, vmax=min_d + .8*(max_d-min_d))
## pts = mlab.points3d(x, y, z, d)
mlab.axes()
mlab.show()
person Frederick Liu-Marlton    schedule 20.02.2019

Приношу свои извинения г-ну Э за задержку с ответом, у меня не было доступа в Интернет на выходных. Однако у меня был доступ к компьютеру, и я нашел ответ на свой вопрос, хотя и немного некрасивый. Я уверен, что следующий метод можно улучшить, и по причинам, указанным выше, я знаю, что это важное базовое использование программного обеспечения для 3D-построения, поэтому, если у кого-то есть какие-либо улучшения, которые они могут предложить, они будут очень признательны. В следующем объяснении предполагается, что вы используете Linux, но я уверен, что сделать то же самое (т.е. сохранить и запустить файлы Python) в других операционных системах несложно.

Сначала сгенерируйте образец файла данных. Настоящие данные поступают из программы на Фортране, но для текущих тестовых целей я буду использовать python для создания образца файла данных. Сохраните следующий код в файле «gen-data.py» (скопируйте и вставьте в ваш любимый текстовый редактор и затем нажмите «Сохранить как» и т. д.)

#!/usr/bin/python
import numpy as numpy

# run this program with 
#" python  gen-data.py > stream.out  "
# to generate sample data file stream.out  
x_low = -1 ; x_upp = 1 ; NX = 5
y_low = -2 ; y_upp = 2 ; NY = 3
z_low = -3 ; z_upp = 3 ; NZ = 3

x_arr = numpy.linspace(x_low,x_upp,num = NX, endpoint=True)
y_arr = numpy.linspace(y_low,y_upp,num = NY, endpoint=True)
z_arr = numpy.linspace(z_low,z_upp,num = NZ, endpoint=True)

#the following line generates data (for distance from the origin) 
# over  a structured grid
for x in x_arr:
    for y in y_arr:
        for z in z_arr:
            print x , y , z , x**2 + y**2 + z**2

Запустите программу, используя python gen-data.py> stream.out, который будет хранить образец файла данных описанного выше типа в файле данных stream.out. У вас должен быть файл со значениями:
-1.0 -2.0 -3.0 14.0
-1.0 -2.0 0.0 5.0
-1.0 -2.0 3.0 14.0
-1.0 0.0 -3.0 10.0
- 1,0 0,0 0,0 1,0
-1,0 0,0 3,0 10,0
-1,0 2,0 -3,0 14,0
-1,0 2,0 0,0 5,0
-1,0 2,0 3,0 14,0
-0,5 -2,0 -3,0 13,25
. . . .
0,5 2,0 3,0 13,25
1,0 -2,0 -3,0 14,0
1,0 -2,0 0,0 5,0
1,0 -2,0 3,0 14,0
1,0 0,0 -3,0 10,0
1,0 0,0 0,0 1,0
1.0 0.0 3.0 10.0
1.0 2.0 -3.0 14.0
1.0 2.0 0.0 5.0
1.0 2.0 3.0 14.0
Каждая строка в файле данных имеет вид
xyz V (x, y, z)
где x, y, z описывают координаты x, y, x точки в пространстве, а V (x, y, z) обозначает значение скаляра в этой точке.

Построение данных
Наша проблема состоит в том, как построить эти данные с помощью Mayavi - меня особенно интересует построение изоповерхностей, которое может быть достигнуто с помощью команды contour3d. Многочисленные примеры в Интернете показывают данные построения contour3d, которые генерируются с помощью команды mgrid. (Есть также примеры с использованием команды ogrid, но для меня mgrid было легче понять). Стратегия: если мы сможем манипулировать нашими данными, чтобы они имели ту же форму, что и вывод команды mgrid, мы должны иметь возможность построить график. Анализируя вывод mgrid, было ясно, что требовалось 3 трехмерные массивы numpy для хранения координат x, y и z и еще один трехмерный массив numpy для хранения скалярных значений (V в приведенном выше) в этих точках. Следующая программа выполняет эти шаги. Я думаю, что программу определенно можно улучшить: я уверен, что подпрограмму fill_up_array можно было бы заменить однострочником кем-то, кто знает о нарезке массивов в python, и, вероятно, есть другие места, которые можно улучшить. Я не могу избавиться от мысли, что все это, вероятно, можно сделать в 1 или 2 строчки для тех, кто знает, что они делают в numpy / mayavi, но следующая программа, я считаю, проста для понимания и работает (вы должны увидеть усеченные сферические поверхности на появившемся графике).
Сохраните следующий файл в "hope.py" и запустите с
python hope.py

import numpy
from mayavi import mlab

def fill_up_array(output_arr,source_arr,nx,ny,nz,posn):
# takes a slice of results from source_arr and writes to output_arr
# there is probably an easy one liner to do this ?
#TODO: add checks to ensure input is sensible
    for i in range(nx):
        for j in range(ny):
            for k in range(nz):
                output_arr[i][j][k] = source_arr[i][j][k][posn]

# these numbers have to correspond to those used in gen-data.py
NX = 5 ; NY = 3 ; NZ = 3 

NDIM = 4  # number of columns in data file, 4 for current example


#initialise arrays:
# xx will contain x coordinate of data point
# yy will contain y coordinate of data point
# zz will contain z coordinate of data point
# VV will contain sample scalar value at (x,y,z)
xx = numpy.zeros((NX,NY,NZ))
yy = numpy.zeros((NX,NY,NZ))
zz = numpy.zeros((NX,NY,NZ))
VV =  numpy.zeros((NX,NY,NZ))


#now read in values from stream.out file to these arrays
full = numpy.loadtxt("stream.out")
fy = numpy.reshape(full, (NX,NY,NZ,NDIM))


fill_up_array(xx,fy,NX,NY,NZ,0)
fill_up_array(yy,fy,NX,NY,NZ,1)
fill_up_array(zz,fy,NX,NY,NZ,2)
fill_up_array(VV,fy,NX,NY,NZ,3)


#test plot
mlab.contour3d(xx, yy, zz, VV)
mlab.show()
person user3390991    schedule 10.03.2014