Как представить точки рассеяния 3D-функции с помощью GNUPLOT - PullRequest
0 голосов
/ 05 мая 2019

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

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

Ответы [ 3 ]

0 голосов
/ 09 мая 2019

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

enter image description here

0 голосов
/ 10 мая 2019

enter image description here спасибо. Я последую позже. я просто написал скрипт, который заполняет дискретное представление пока что достаточно для меня с matplotlib (я не был так знаком с gnuplot). Также: представление функции "F (X, Y, Z) - A = Result" в (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()
0 голосов
/ 06 мая 2019

Целочисленные значения [-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 делает их меньше)

enter image description here

...