Как представить точки рассеяния трехмерной функции с помощью GNUPLOT

Я хотел бы представить в 3D результат функции f (X, Y, Z) = (X² (Y + Z) + Y² (X-Z) + Z² (-X-Y) -21) с точками разброса. Любые советы, как это сделать в GNUPLOT, приветствуются (от -100 до +100 в каждом направлении).

Я пытаюсь увидеть «0» в целых числах X Y и Z. Размер точек будет значением, возвращаемым функцией.


person floppy_molly    schedule 05.05.2019    source источник


Ответы (3)


Целочисленные значения [-100: 100] в 3-х измерениях составляют 8 миллионов точек. Если бы вы хоть что-нибудь нарисовали для каждого из них, результирующее отображение было бы заполнено каждым пикселем, и это было бы бесполезно в качестве инструмента визуализации. Кодирование по размеру или цвету в каждом пункте не поможет. Теперь количество точек, которые вы хотите найти, может составлять управляемое небольшое подмножество, которое можно визуализировать как трехмерную диаграмму рассеяния в gnuplot, но вам придется выбирать эти точки, а не строить все.

Простым подходом было бы перебрать x, y, z для вычисления вашей функции, а затем, если значение соответствует вашему желанию (f (x, y, z) == 0?), Напишите, что [x, y, z] триплет в файл. Если количество найденных точек приемлемо, вы можете визуализировать в gnuplot с помощью команд ниже. В качестве примера я использую случайные точки между [-1: 1].

  unset border
  set xzeroaxis; set yzeroaxis; set zzeroaxis
  set tics nomirror axis
  set xyplane at 0
  splot "zeros" using 1:2:3 with points pt 7 ps 0.4

(тип точки 7 - сплошной круг, размер точки 0,4 делает их меньше)

введите описание изображения здесь

person Ethan    schedule 06.05.2019
comment
Спасибо за совет. Придется переосмыслить свою тему. - person floppy_molly; 06.05.2019
comment
Я вижу, я смотрю на построение четырехмерных графиков. stackoverflow.com/questions/14995610/. f (X, Y, Z), как функция плотности, не должно быть представлено ничем, когда отрицательно, зеленой точкой, когда ноль, желтой точкой, когда ›0 и‹ 100, голубой точкой, когда ›100 и‹ 1000. светло-серый при ‹100000, розовый при› 100000. Буду дальше чесать затылок. советы более чем приветствуются. GNUPLOT по-прежнему является хорошей отправной точкой. - person floppy_molly; 06.05.2019
comment
В исходном запросе три не было функцией плотности. Если вы можете переосмыслить его как функцию локальной плотности, то, возможно, разрабатываемая версия gnuplot сможет делать то, что вы хотите. См. stackoverflow.com/questions/53484738/ - person Ethan; 06.05.2019
comment
благодаря. Я вижу много представлений функции плотности с помощью matplotlib или gnuplot: набор точек с неравномерно распределенными координатами и одинаковым весом каждой точки. плотность, которую я хочу представить, определяется точками, равномерно распределенными X Y Z (все целые числа), и в этих точках определяется значение плотности (отличное от 1; см. функцию f выше). - person floppy_molly; 08.05.2019
comment
См. Ответ №2. Представлять такое количество баллов по отдельности непрактично. Вам нужно будет выбрать другое представление. - person Ethan; 09.05.2019

Ответ №2: Если функция плотности в большинстве случаев не равна нулю, она заполняет сплошной объем. Чтобы визуализировать этот объем, вам нужно будет выбрать определенные точки или взять срезы или что-то еще. Разумные варианты зависят от структуры вашей функции. Gnuplot предлагает несколько подходов. См. Этот пример использования 2D-срезов, взятых из текущего демонстрационного набора voxel.dem . Этот подход имеет смысл для гладкой функции плотности, но, вероятно, не для функции, где интересующие биты являются дискретными точками, а не областями пространства.

введите описание изображения здесь

person Ethan    schedule 09.05.2019

введите описание изображения здесь спасибо. Я пойду позже. Я просто написал сценарий, который заполняет дискретное представление достаточно для меня с помощью matplotlib (я не был так хорошо знаком с gnuplot). Также: представление функции «F (X, Y, Z) - A = Результат» в (X, Y, Z) целыми числами в 3D. Результат = 0? точка окрашена в черный цвет. Еще цветные.

    import matplotlib as mpl
from mpl_toolkits.mplot3d.proj3d import proj_transform
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np

mpl.use('tkagg')

def distance(point, event):
    plt.sca(ax)     # <------------------ introduce this one  !!!!!!!!!!!!!!!!!!!!!!!!!!!
    x2, y2, _ = proj_transform(point[0], point[1], point[2], plt.gca().get_proj())
    x3, y3 = ax.transData.transform((x2, y2))
    return np.sqrt ((x3 - event.x)**2 + (y3 - event.y)**2)

def calcClosestDatapoint(X, event):
    distances = [distance(X[i, 0:3], event) for i in range(Sol)]
    return np.argmin(distances)
#
def annotatePlot(X, index):
    global last_mark, generated_labels
    if activated_labelling:

        x2, y2, _ = proj_transform(X[index, 0], X[index, 1], X[index, 2], ax.get_proj())
        last_mark = plt.annotate(generated_labels[index],
            xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom',
            bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
            arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))

        fig.canvas.draw()
#
def onMouseMotion(event):
    global Coord
    if activated_labelling:
        closestIndex = calcClosestDatapoint(Coord, event)
        last_mark.remove()
        annotatePlot(Coord, closestIndex)       

def show_on(event):
    global activated_labelling, last_mark,pid,mid

    if activated_labelling == False:
        activated_labelling = True
        x2, y2, _ = proj_transform(Coord[0,0], Coord[0,1], Coord[0,2], ax.get_proj())

        last_mark = plt.annotate("3D measurement on " + generated_labels[0],
                    xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom',
        bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
        arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))  
        mid = fig.canvas.mpl_connect('motion_notify_event', onMouseMotion)
#
def show_off(event):
    global activated_labelling
    '''
    deactivate the persistent XYZ position labels at the grafic
    '''
    if activated_labelling:
        activated_labelling = False
        last_mark.remove()
        fig.canvas.draw()
        fig.canvas.mpl_disconnect(mid)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#ax = fig.gca(projection='3d')
activated_labelling = False

Wide = 100
Minimum = -50     
ScanLimit = 3  #  searching between o and 3; 4 and 5 are no solutions
Search = 45

Coord=[]

values=[]

generated_labels = []
#
XMin = 0
XMax = 0
YMin = 0
YMax = 0
ZMin = 0
ZMax = 0

# count the solutions found in the scan area defined above
Sol=0

for i in range(Wide+1):
    for j in range(Wide+1):
        for k in range(Wide+1):

            ########################################################################
            ########################################################################
            ####
            ####                   THIS IS THE POLYNOM TO BE REPRESENTED
            ####
            param_dens = ((i+Minimum)**3)+((j+Minimum)**3)+((k+Minimum)**3) -Search

            if abs(param_dens) <= abs(ScanLimit):
                Coord.append([i+Minimum,j+Minimum,k+Minimum])

                if ScanLimit !=0:
                    values.append([abs(param_dens)])

                labelling = "value {}\nin   X:{}   Y:{}   Z:{}".format(Search+param_dens,i+Minimum,j+Minimum,k+Minimum)    
                generated_labels.append(labelling)
                print(labelling+"\n")

# increase the number indicating the solutions found
                Sol +=1           
# for centering the window          
                if XMin > i+Minimum:
                    XMin = i+Minimum
                if YMin > j+Minimum:
                    YMin = j+Minimum   
                if ZMin > k+Minimum:
                    ZMin = k+Minimum

                if XMax < i+Minimum:
                    XMax = i+Minimum
                if YMax < j+Minimum:
                    YMax = j+Minimum                 
                if ZMax < k+Minimum:
                    ZMax = k+Minimum

print('######################################################')
print('## statistics / move this to a parallel search engine?')
print('## search ')
print("##   total solution %d for searching center %d" % (Sol,Search))    
print("##   from %d to %d" % (Search-ScanLimit,Search+ScanLimit))
print("##   from %d to %d" % (Minimum,Wide+Minimum))      
print('##')      
print('#######################################################')
#
values = np.array(values, dtype='int64')    
Coord = np.array(Coord, dtype='int64')          
#

if ScanLimit !=0:

    cmap = plt.cm.jet  # define the colormap
# extract all colors from the .jet map
    cmaplist = [cmap(i) for i in range(cmap.N)]
# force the first color entry to be black
    cmaplist[0] = (0, 0, 0, 1.0)
# create the new map
    cmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, cmap.N)

# define the bins and normalize
    bounds = np.linspace(0, ScanLimit, ScanLimit+1)
    norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
# create a second axes for the colorbar
    ax2 = fig.add_axes([0.95, 0.1, 0.03, 0.8])
    cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm,
        spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i')

#    
ax.set_xlim3d(XMin-5, XMax+5)
ax.set_ylim3d(YMin-5, YMax+5)
ax.set_zlim3d(ZMin-5, ZMax+5)
#
ax.set_xlabel('X X')
ax.set_ylabel('Y Y')
ax.set_zlabel('Z Z')

ax.set_aspect(aspect=1)

# extract the scatterplot drawing in a separate function so we ca re-use the code
def draw_scatterplot():
    if ScanLimit !=0:
        ax.scatter3D(Coord[:,0], Coord[:,1], Coord[:,2], s=20, c=values[:,0], cmap=cmap, norm=norm)
    else:
        ax.scatter3D(Coord[:,0], Coord[:,1], Coord[:,2], s=20, c='green')

# draw the initial scatterplot
draw_scatterplot()

# create the "on" button, and place it somewhere on the screen
ax_on = plt.axes([0.0, 0.0, 0.1, 0.05])
button_on = Button(ax_on, 'on')
#
ax_off = plt.axes([0.12, 0.0, 0.1, 0.05])
button_off = Button(ax_off, 'off')
#
#ax_off = plt.axes([0.24, 0.0, 0.1, 0.05])
#button_off = Button(ax_off, 'off')

# link the event handler function to the click event on the button
button_on.on_clicked(show_on)
button_off.on_clicked(show_off)

#fig.colorbar(img)
plt.show()
person floppy_molly    schedule 10.05.2019