Необходимо чтобы каждый поверхность в программе становилась более прозрачной ближе к нижней плоскости
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection



def graph_view(ax, sigmaI, muI, sigmaV, muV, Imin, Imax, Vmin, Vmax, alpha, colorPart, color, alphaPart):

    I, V = np.meshgrid(np.linspace(IlimMin, IlimMax, 150), np.linspace(VlimMin, VlimMax, 150))
    F = np.exp((-(I-muI)**2-(np.log(V)-muV)**2)/(2 * sigmaI**2 * sigmaV**2))/(sigmaI * sigmaV * V * 2*np.pi)

    # ax.plot_surface(I, V, F)


    # Определяем диапазон для выделения цветом (например, z_min < z < z_max)
    z_min, z_max = 0.5, 1.0

    # Создаем поверхность
    surface = ax.plot_surface(I, V, F, alpha=alpha, edgecolor='none', color=color)
    


    # # Нахождение максимума
    max_idx = np.unravel_index(np.argmax(F, axis=None), F.shape)
    min_idx = np.unravel_index(np.argmin(F, axis=None), F.shape)
    # max_I = I[max_idx]
    # max_V = V[max_idx]
    max_F = F[max_idx]
    min_F = F[min_idx]


    # # Печатаем координаты максимальной точки для проверки
    # print(f"Max I: {max_I}, Max V: {max_V}, Max F: {max_F}")

    # # Печатаем координаты максимальной точки для проверки
    # print(f"Max I: {max_I}, Max V: {max_V}, Max F: {max_F}")

    # # # Построение вертикальной линии
    # ax.plot([max_I, max_I], [max_V, max_V], [0, max_F], color="r", linestyle="--")

    # # Отметка максимальной точки
    # ax.scatter(max_I, max_V, max_F, color="r", s=50)

    # # Добавление дополнительных отметок на осях
    # ax.text(max_I+0.05, max_V+0.05, max_F, f"P = {max_F:.4f}", color="black")
    # ax.text(max_I, 0, 0, f"{max_I:.2f}", color="black")
    # ax.text(IlimMax, max_V, 0, f"{max_V:.2f}", color="black")

    # # Добавление линий на плоскости
    # ax.plot([max_I, max_I], [0, max_V], [0, 0], color="red", linestyle="--")
    # ax.plot([IlimMax, max_I], [max_V, max_V], [0, 0], color="red", linestyle="--")


    # Определяем маску для выделенного диапазона
    mask = (I >= Imin) & (I <= Imax) & (V >= Vmin) & (V <= Vmax)

    # Копируем данные, чтобы изменить цвет только выделенной части
    x_highlight = np.copy(I)
    y_highlight = np.copy(V)
    z_highlight = np.copy(F)

    # Обнулим значения, которые не входят в диапазон, чтобы они не отображались
    x_highlight[~mask] = np.nan
    y_highlight[~mask] = np.nan
    z_highlight[~mask] = np.nan
    # Добавляем выделенную часть на поверхность другим цветом
    highlight_surface = ax.plot_surface(x_highlight, y_highlight, z_highlight, color=colorPart, alpha = alphaPart, edgecolor='none')

    # # Вычисление среднего значения z (плотности вероятности) для выделенной области
    # mean_F = np.nanmean(z_highlight)  # Используем np.nanmean для игнорирования np.nan

    # # Маска для выделенной области без nan
    # masked_I = I[mask]
    # masked_V = V[mask]
    # masked_F = F[mask]

    # # Вычисляем взвешенные средние координаты
    # mean_I = np.sum(masked_I * masked_F) / np.sum(masked_F)
    # mean_V = np.sum(masked_V * masked_F) / np.sum(masked_F)

    # print('mean_I, mean_V, mean_F', mean_I, mean_V, mean_F)

    # # Отметка средней точки на выделенной части поверхности
    # ax.scatter(mean_I, mean_V, mean_F, color="red", s=50)
    # ax.plot([mean_I, mean_I], [mean_V, mean_V], [0, mean_F], color="red", linestyle="--")
    # ax.plot([mean_I, mean_I], [0, mean_V], [0, 0], color="red", linestyle="--")
    # ax.plot([IlimMax, mean_I], [mean_V, mean_V], [0, 0], color="red", linestyle="--")

    # ax.text(mean_I, mean_V, mean_F+0.0005, f"P = {mean_F:.4f}", color="black")
    # ax.text(mean_I, 0, 0, f"{mean_I:.2f}", color="black")
    # ax.text(IlimMax, mean_V, 0, f"{mean_V:.2f}", color="black")

    # Настраиваем отображение и цветовую карту
    # fig.colorbar(surface, ax=ax, shrink=0.5, aspect=5)

    ax.set_xlabel('Потребляемый ток')
    ax.set_ylabel('Скорость')
    ax.set_zlabel('Плотность веростности')
    # plt.xlim(16.66, 20)
    # plt.ylim(0, 0.75)
    return surface

def graph_view_without_part(ax, sigmaI, muI, sigmaV, muV, alpha, color):
    I, V = np.meshgrid(np.linspace(IlimMin, IlimMax, 150), np.linspace(VlimMin, VlimMax, 150))
    # F = np.exp((-(I-muI)**2-(np.log(V)-muV)**2)/(2 * sigmaI**2 * sigmaV**2))/(sigmaI * sigmaV * V * 2*np.pi)
    # F = (np.exp(-0.5* ((I-muI)/sigmaI)**2 + ((V-muV)/sigmaV)**2 )) / (sigmaI*sigmaV*2*np.pi)
    F1 = np.exp(-0.5*((I-muI)/sigmaI)**2)
    F2 = np.exp(-0.5*((V-muV)/sigmaV)**2)
    F = F1*F2

    # ax.plot_surface(I, V, F)


    # Определяем диапазон для выделения цветом (например, z_min < z < z_max)
    z_min, z_max = 0.5, 1.0

    # Создаем поверхность
    surface = ax.plot_surface(I, V, F, alpha=alpha, edgecolor='none', color=color)


    # Нахождение максимума
    max_idx = np.unravel_index(np.argmax(F, axis=None), F.shape)
    max_I = I[max_idx]
    max_V = V[max_idx]
    max_F = F[max_idx]

    # Печатаем координаты максимальной точки для проверки
    print(f"Max I: {max_I}, Max V: {max_V}, Max F: {max_F}")

    # Печатаем координаты максимальной точки для проверки
    print(f"Max I: {max_I}, Max V: {max_V}, Max F: {max_F}")

    # # Построение вертикальной линии
    # ax.plot([max_I, max_I], [max_V, max_V], [0, max_F], color="r", linestyle="--")

    # # Отметка максимальной точки
    # ax.scatter(max_I, max_V, max_F, color="r", s=50)

    # # Добавление дополнительных отметок на осях
    # ax.text(max_I+0.05, max_V+0.05, max_F, f"P = {max_F:.4f}", color="black")
    # ax.text(max_I, 0, 0, f"{max_I:.2f}", color="black")
    # ax.text(IlimMax, max_V, 0, f"{max_V:.2f}", color="black")

    # # Добавление линий на плоскости
    # ax.plot([max_I, max_I], [0, max_V], [0, 0], color="red", linestyle="--")
    # ax.plot([IlimMax, max_I], [max_V, max_V], [0, 0], color="red", linestyle="--")

    ax.set_xlabel('Потребляемый ток')
    ax.set_ylabel('Скорость')
    ax.set_zlabel('Плотность веростности')
    return surface
    

def background(ax):
    zmin = 0
    square1 = np.array([[0, 0, zmin], [3.33, 0, zmin], [3.33, 0.75, zmin], [0, 0.75, zmin]])
    square2 = np.array([[3.33, 0, zmin], [10, 0, zmin], [10, 0.75, zmin], [3.33, 0.75, zmin]])
    square3 = np.array([[10, 0, zmin], [16.66, 0, zmin], [16.66, 0.75, zmin], [10, 0.75, zmin]])
    square4 = np.array([[16.66, 0, zmin], [20, 0, zmin], [20, 0.75, zmin], [16.66, 0.75, zmin]])

    square5 = np.array([[3.33, 0.75, zmin], [10, 0.75, zmin], [10, 2.25, zmin], [3.33, 2.25, zmin]])
    square6 = np.array([[10, 0.75, zmin], [16.66, 0.75, zmin], [16.66, 2.25, zmin], [10, 2.25, zmin]])
    square7 = np.array([[16.66, 0.75, zmin], [20, 0.75, zmin], [20, 2.25, zmin], [16.66, 2.25, zmin]])

    square8 = np.array([[10, 2.25, zmin], [16.66, 2.25, zmin], [16.66, 3.75, zmin], [10, 3.75, zmin]])
    square9 = np.array([[16.66, 2.25, zmin], [20, 2.25, zmin], [20, 3.75, zmin], [16.66, 3.75, zmin]])

    square10 = np.array([[10, 3.75, zmin], [16.66, 3.75, zmin], [16.66, 4.5, zmin], [10, 4.5, zmin]])
    square11 = np.array([[16.66, 3.75, zmin], [20, 3.75, zmin], [20, 4.5, zmin], [16.66, 4.5, zmin]])

    sq = [square1, square2, square3, square4, square5, square6, square7, square8, square9, square10, square11]
    colors = ['green', 'gold', 'red', 'firebrick', 'gold', 'gold', 'firebrick', 'gold', 'red', 'red', 'red']
    for i in range(len(sq)):
        square = Poly3DCollection([sq[i]], color=colors[i], edgecolor='none', alpha = 0.5)
        ax.add_collection3d(square)

    
    # ax.plot_surface(square1[0], square1[1], square1[2], color = 'green', alpha = 1)

def integrand(I, V):
    return np.exp((-(I-muI)**2-(np.log(V)-muV)**2)/(2 * sigmaI**2 * sigmaV**2))/(sigmaI * sigmaV * V * 2*np.pi) 

def square(Imin, Imax, Vmin, Vmax):
    result, error = integrate.dblquad(integrand, Imin, Imax, lambda x: Vmin, lambda x: Vmax)
    print(f"Result: {result}, Error estimate: {error}")



def calculate_alpha(z_value, F_min, F_max):
    min_alpha = 0.2
    max_alpha = 1.0
    return min_alpha + (max_alpha - min_alpha) * (z_value - F_min) / (F_max - F_min)




fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d', computed_zorder = False)
# IlimMin = 16.66
# IlimMax = 20
# VlimMin = 0.001
# VlimMax = 0.75
IlimMin = 0
IlimMax = 20
VlimMin = 0
VlimMax = 4.5


# # для второго приступа
sigmaI = 2.33
muI = 11.46
sigmaV = 0.755
muV = -0.611
Imin, Imax = 17.04, 19.67 
Vmin, Vmax = 0.55, 0.74 
SecSurf = graph_view(ax, sigmaI, muI, sigmaV, muV, Imin, Imax, Vmin, Vmax, alpha = 0.8, \
           alphaPart = 0.6, colorPart='salmon', color='green')
# square(Imin, Imax, Vmin, Vmax)

# для третьего приступа 
sigmaI = 2.398
muI = 10.32
sigmaV = 0.75
muV = -0.625
Imin, Imax = 16.35, 16.55 
Vmin, Vmax = 0.359, 0.529 
ThirdSurf = graph_view(ax, sigmaI, muI, sigmaV, muV, Imin, Imax, Vmin, Vmax, alpha = 0.7,\
            alphaPart = 1, colorPart='navy', color='violet')
# square(Imin, Imax, Vmin, Vmax)

# для первого приступа
sigmaI = 1.7
muI = 12.8
sigmaV = 0.71
muV = -0.554
Imin, Imax = 17.04, 17.49  
Vmin, Vmax = 0.6, 0.74 
# square(Imin, Imax, Vmin, Vmax)
firstSurf = graph_view(ax, sigmaI, muI, sigmaV, muV, Imin, Imax, Vmin, Vmax, alpha = 0.8,\
           alphaPart=1, colorPart='firebrick', color='royalblue')



sigmaI = 1.7
muI = 18
sigmaV = 0.71
muV = 0.9

# graph_view(ax, sigmaI, muI, sigmaV, muV, Imin, Imax, Vmin, Vmax, alpha = 0.4, alphaPart = 0.6, colorPart='salmon', color='dodgerblue')

modelSurf = graph_view_without_part(ax, sigmaI, muI, sigmaV, muV,  alpha = 0.4, color='tomato')
firstSurf.set_zorder(4)
SecSurf.set_zorder(3)
ThirdSurf.set_zorder(2)
modelSurf.set_zorder(5)
background(ax)

plt.show()