Построение поверхности с двоичной цветовой картой

#python #matplotlib

#python #matplotlib

Вопрос:

Я хотел бы создать 3D-график поверхности, параметризованной функцией, и я хотел бы, чтобы поверхность была одного цвета (скажем, белого), где она выше некоторого значения a, и другого цвета (скажем, черного), где она ниже a .

Вот код для создания и построения поверхности (способ создания поверхности не важен, это может быть гораздо более простая функция):

 from __future__ import division
import numpy as np
import time,random
random.seed(-2)

def build_spden(N,M, alpha):
    #computes the spectral density in momentum space
    sp_den = np.zeros((N,M))
    for k1 in prange(-N//2, N//2):
        for k2 in prange(-M//2, M//2):
            sp_den[k1,k2] = np.abs(2*(np.cos(2*np.pi*k1/N) np.cos(2*np.pi*k2/M)-2))
    sp_den[0,0]=1
    return 1/sp_den**(alpha/2)


def gaussian_field(N,M,alpha):
    '''Builds a correlated gaussian field on a surface NxM'''
    spectral_density = build_spden(N,M, alpha)
    # FFT of gaussian noise:
    noise_real = np.random.normal(0, 1, size = (N,M))
    noise_fourier = np.fft.fft2(noise_real)

    # Add correlations by Fourier Filtering Method:
    convolution = noise_fourier*np.sqrt(spectral_density)

    # Take IFFT and exclude residual complex part
    correlated_noise = np.fft.ifft2(convolution).real

    # Return normalized field
    return correlated_noise * (np.sqrt(N*M)/np.sqrt(np.sum(spectral_density)) )


#PLOT

N = 2**5
alpha = .75
a = -.1985
surf = gaussian_field(N,N,alpha)

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

x = np.outer(np.arange(0, N), np.ones(N))
y = x.copy().T # transpose
z = surf
fig = plt.figure()
ax = plt.axes(projection='3d')

ax.plot_surface(x, y, z,alpha=.4)  #plot the surface
z2 = a*np.ones((N,N))
ax.plot_surface(x, y, z2, alpha=0.9)  #plot a plane z = a.
plt.show()
  

Результат:

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

Поэтому я хотел бы, чтобы поверхность была белой над плоскостью и черной внизу.

Большое спасибо!

Ответ №1:

Вы можете определить пользовательскую цветовую карту и перейти к plot_surface :

 from matplotlib.colors import ListedColormap, BoundaryNorm
cmap = ListedColormap(['r', 'b'])
norm = BoundaryNorm([z.min(), a, z.max()], cmap.N)
ax.plot_surface(x, y, z, cmap=cmap, norm=norm, alpha=.4)  #plot the surface

z2 = a*np.ones((N,N))
ax.plot_surface(x, y, z2, colalpha=0.9)  #plot a plane z = a.
plt.show()
  

Вывод:

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

Комментарии:

1. @Njha Вам также необходимо перейти norm=norm к plot_surface . Пожалуйста, смотрите Обновление.

2. Возможно ли также раскрасить плоскость в соответствии со значениями поверхности? То есть точки плоскости, где поверхность> a, являются синими, а точки плоскости, где поверхность < a, — красными.

3. Я не знаю простого способа для этого.