import numpy as np import pandas as pd import matp...
생성일: 2025년 12월 8일
생성일: 2025년 12월 8일
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import segyio
import matplotlib.cm as cm
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.callbacks import EarlyStopping
from mpl_toolkits.mplot3d import Axes3D
seg_data_path = 'Cube.sgy'
hzn_b_path = 'B'
thk_data_path = 'dh_dataset.txt'
thk_df = pd.read_csv(thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'])
hzn_df = pd.read_csv(hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'])
hzn_time_map = {(int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows()}
seismic_waves = []
coordinates = []
time_values = []
with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube:
inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:]
xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:]
samp_count = seismic_cube.samples
time_step_ms = segyio.tools.dt(seismic_cube) / 1000
coord_to_trace_idx = {(il, xl): idx for idx, (il, xl) in enumerate(zip(inlines, xlines))}
total_traces = len(coord_to_trace_idx)
textprocessed_count = 0 for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) time_values.append(ref_time) processed_count += 1
seismic_waves = np.array(seismic_waves)
coordinates = np.array(coordinates)
time_values = np.array(time_values)
principal_components = PCA(n_components=3)
pca_features = principal_components.fit_transform(seismic_waves)
input_dim_ae = seismic_waves.shape[1]
latent_dim = 3
input_layer_ae = Input(shape=(input_dim_ae,))
encoded_layer = Dense(16, activation='relu')(input_layer_ae)
encoded_layer = Dense(latent_dim, activation='relu')(encoded_layer)
decoded_layer = Dense(16, activation='relu')(encoded_layer)
decoded_layer = Dense(input_dim_ae, activation='linear')(decoded_layer)
autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded_layer)
encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded_layer)
autoencoder_model.compile(optimizer='adam', loss='mse')
X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42)
early_stopping_callback = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)
history_ae = autoencoder_model.fit(
X_train_ae, X_train_ae,
epochs=5,
batch_size=32,
shuffle=True,
validation_data=(X_val_ae, X_val_ae),
callbacks=[early_stopping_callback]
)
ae_features = encoder_extractor.predict(seismic_waves)
pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3'])
pca_results['inline'] = coordinates[:, 0]
pca_results['crossline'] = coordinates[:, 1]
ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3'])
ae_results['inline'] = coordinates[:, 0]
ae_results['crossline'] = coordinates[:, 1]
pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner')
ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner')
X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split(
pca_regression_data[['PC1', 'PC2', 'PC3']].values,
pca_regression_data['thickness'].values,
test_size=0.2,
random_state=42
)
knn_pca_model = KNeighborsRegressor(n_neighbors=5)
knn_pca_model.fit(X_train_pca, y_train_pca)
pca_predictions = knn_pca_model.predict(X_test_pca)
mse_pca_model = mean_squared_error(y_test_pca, pca_predictions)
X_train_ae, X_test_ae, y_train_ae, y_test_ae = train_test_split(
ae_regression_data[['AE1', 'AE2', 'AE3']].values,
ae_regression_data['thickness'].values,
test_size=0.2,
random_state=42
)
knn_ae_model = KNeighborsRegressor(n_neighbors=5)
knn_ae_model.fit(X_train_ae, y_train_ae)
ae_predictions = knn_ae_model.predict(X_test_ae)
mse_ae_model = mean_squared_error(y_test_ae, ae_predictions)
pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values
full_thickness_pred_pca = knn_pca_model.predict(pca_full_features)
pca_results['predicted_thickness'] = full_thickness_pred_pca
ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values
full_thickness_pred_ae = knn_ae_model.predict(ae_full_features)
ae_results['predicted_thickness'] = full_thickness_pred_ae
fig1 = plt.figure(figsize=(10, 8))
ax1 = fig1.add_subplot(111, projection='3d')
scatter1 = ax1.scatter(
pca_regression_data['PC1'],
pca_regression_data['PC2'],
pca_regression_data['PC3'],
c=pca_regression_data['thickness'],
cmap='turbo',
s=20
)
ax1.set_title('Признаки, полученные с помощью метода главных компонент')
ax1.set_xlabel('ГК1')
ax1.set_ylabel('ГК2')
ax1.set_zlabel('ГК3')
fig1.colorbar(scatter1, ax=ax1, pad=0.1, label='Толщина (м)')
fig2 = plt.figure(figsize=(10, 8))
ax2 = fig2.add_subplot(111, projection='3d')
scatter2 = ax2.scatter(
ae_regression_data['AE1'],
ae_regression_data['AE2'],
ae_regression_data['AE3'],
c=ae_regression_data['thickness'],
cmap='turbo',
s=20
)
ax2.set_title('Скрытые признаки автокодировщика')
ax2.set_xlabel('АЭ1')
ax2.set_ylabel('АЭ2')
ax2.set_zlabel('АЭ3')
fig2.colorbar(scatter2, ax=ax2, pad=0.1, label='Толщина (м)')
plt.figure(figsize=(12, 6))
scatter_map_pca = plt.scatter(
pca_results['crossline'],
pca_results['inline'],
c=pca_results['predicted_thickness'],
cmap='turbo',
s=1
)
plt.colorbar(scatter_map_pca, label='Прогнозируемая толщина (м)')
plt.title('Карта прогнозируемой толщины с использованием признаков PCA')
plt.ylabel('Вдоль профиля')
plt.xlabel('Поперёк профиля')
plt.figure(figsize=(12, 6))
scatter_map_ae = plt.scatter(
ae_results['crossline'],
ae_results['inline'],
c=ae_results['predicted_thickness'],
cmap='turbo',
s=1
)
plt.colorbar(scatter_map_ae, label='Прогнозируемая толщина (м)')
plt.title('Карта прогнозируемой толщины с использованием признаков автокодировщика')
plt.ylabel('Вдоль профиля')
plt.xlabel('Поперёк профиля')
plt.show(), сделай отображение результатов в окне TKinter, добавь комментарии к каждой части кода и убери всё то что не влияет на результат
Вот переработанный и упрощённый код:
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping from mpl_toolkits.mplot3d import Axes3D # импорт для 3D-графиков import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # ========================== # 1. Пути к исходным данным # ========================== seg_data_path = 'Cube.sgy' # 3D куб сейсмических данных (SEGY) hzn_b_path = 'B' # файл горизонта (B) thk_data_path = 'dh_dataset.txt' # файл с измеренной толщиной # =========================================== # 2. Загрузка данных по толщине и горизонту B # =========================================== # Таблица: inline, crossline, толщина (м) thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) # Таблица горизонта: координаты и время прихода (мс) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) # Словарь: (inline, crossline) -> время горизонта (мс) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # ========================================== # 3. Извлечение сейсмических окон вокруг B # ========================================== seismic_waves = [] # сегменты трасс (окна по времени) coordinates = [] # соответствующие координаты (inline, crossline) with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube: # Чтение inline и crossline для каждой трассы inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] # Шаг по времени в миллисекундах time_step_ms = segyio.tools.dt(seismic_cube) / 1000 # Словарь: (inline, crossline) -> индекс трассы в файле coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } # Проходим по всем трассам for (il, xl), trace_idx in coord_to_trace_idx.items(): # Время горизонта B для данной точки ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue # если горизонта нет — пропускаем trace_data = seismic_cube.trace[trace_idx] # Окно: 60 мс вверх от горизонта до самого горизонта end_time = ref_time start_time = ref_time - 60 # Индексы по времени -> индексы по сэмплам start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) # Проверка границ, чтобы не выйти за массив if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] # Нормализация сегмента по RMS rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue # избегаем деления на ноль при нулевой амплитуде normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) # Преобразуем в numpy-массивы seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # ========================================== # 4. Извлечение признаков методом PCA (3 компоненты) # ========================================== pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # ========================================== # 5. Автокодировщик для нелинейных признаков (3 нейрона в латентном слое) # ========================================== input_dim_ae = seismic_waves.shape[1] latent_dim = 3 # Входной слой input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace') # Кодировщик: сжатие до латентного пространства encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae) encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded) # Декодировщик: восстановление исходной трассы decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded) decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded) # Полная модель автокодировщика autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder') # Отдельная модель кодировщика (для получения латентных признаков) encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder') # Компиляция автокодировщика autoencoder_model.compile(optimizer='adam', loss='mse') # Разбиение на обучающую и валидационную выборки (для автокодировщика) X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) # Ранний останов для предотвращения переобучения early_stopping_callback = EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True ) # Обучение автокодировщика autoencoder_model.fit( X_train_ae, X_train_ae, epochs=5, # можно увеличить при необходимости batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[early_stopping_callback], verbose=1 ) # Извлекаем латентные признаки для всех трасс ae_features = encoder_extractor.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # ================================================== # 6. Подготовка данных для регрессии (PCA и AE признаки) # ================================================== # Объединяем измеренную толщину и PCA-признаки по inline / crossline pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') # Объединяем измеренную толщину и AE-признаки ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # ================================== # 7. Обучение KNN-регрессии на PCA # ================================== X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca_model = KNeighborsRegressor(n_neighbors=5) knn_pca_model.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca_model.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # =================================== # 8. Обучение KNN-регрессии на AE # =================================== X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae_model = KNeighborsRegressor(n_neighbors=5) knn_ae_model.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae_model.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # =================================================== # 9. Прогноз толщины во всех точках для карт (PCA/AE) # =================================================== # Для всех точек, где есть PCA-признаки, считаем прогноз толщины pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values full_thickness_pred_pca = knn_pca_model.predict(pca_full_features) pca_results['predicted_thickness'] = full_thickness_pred_pca # Для всех точек с AE-признаками считаем прогноз толщины ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values full_thickness_pred_ae = knn_ae_model.predict(ae_full_features) ae_results['predicted_thickness'] = full_thickness_pred_ae # ============================================ # 10. Построение фигур Matplotlib (4 графика) # ============================================ # --- 3D-пространство PCA-признаков с цветом по толщине --- fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') scatter1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(scatter1, ax=ax1, pad=0.1, label='Толщина (м)') # --- 3D-пространство AE-признаков с цветом по толщине --- fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') scatter2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(scatter2, ax=ax2, pad=0.1, label='Толщина (м)') # --- Карта прогнозируемой толщины по PCA-признакам --- fig3 = plt.figure(figsize=(12, 6)) scatter_map_pca = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(scatter_map_pca, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # --- Карта прогнозируемой толщины по AE-признакам --- fig4 = plt.figure(figsize=(12, 6)) scatter_map_ae = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(scatter_map_ae, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # ======================================= # 11. Отображение результатов в Tkinter # ======================================= # Создаём главное окно root = tk.Tk() root.title("Результаты прогнозирования толщины") # Используем вкладки (Notebook) для переключения между графиками notebook = ttk.Notebook(root) notebook.pack(fill='both', expand=True) # Список фигур и названий вкладок figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] # Для каждой фигуры создаём вкладку и размещаем в ней канвас for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) # Запуск главного цикла Tkinter root.mainloop()
Если нужно, могу отдельно вынести загрузку/обработку данных и построение GUI в функции, чтобы код был ещё более структурированным.
добавь в окно ткинтер пустое окно с кнопкой , на которой написано "показать картинки" при нажатии должна вылазать и запускаться гифка из файла а снизу быть ещё кнопка, с подписью " картман съел фотки, теперь ему плохо" и нажатие на эту кнопку добавляет окна с картинками
Сделал:
south-park-toilet.gif.mp4 нужно конвертировать в .gif)Вот полный код с комментариями, включая Tkinter и GIF:
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping from mpl_toolkits.mplot3d import Axes3D # для 3D-графиков import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # Для работы с GIF from PIL import Image, ImageTk, ImageSequence # ========================== # 1. Пути к исходным данным # ========================== seg_data_path = 'Cube.sgy' # 3D куб сейсмических данных (SEGY) hzn_b_path = 'B' # файл горизонта (B) thk_data_path = 'dh_dataset.txt' # файл с измеренной толщиной # Путь к GIF-файлу (НУЖЕН именно .gif, mp4 не подойдёт для Tkinter) gif_path = 'south-park-toilet.gif' # Глобальный список кадров GIF, чтобы не удалить их сборщиком мусора gif_frames = [] # =========================================== # 2. Загрузка данных по толщине и горизонту B # =========================================== # Таблица: inline, crossline, толщина (м) thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) # Таблица горизонта: координаты и время прихода (мс) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) # Словарь: (inline, crossline) -> время горизонта (мс) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # ========================================== # 3. Извлечение сейсмических окон вокруг B # ========================================== seismic_waves = [] # сегменты трасс (окна по времени) coordinates = [] # соответствующие координаты (inline, crossline) with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube: # Чтение inline и crossline для каждой трассы inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] # Шаг по времени в миллисекундах time_step_ms = segyio.tools.dt(seismic_cube) / 1000 # Словарь: (inline, crossline) -> индекс трассы в файле coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } # Проходим по всем трассам for (il, xl), trace_idx in coord_to_trace_idx.items(): # Время горизонта B для данной точки ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue # если горизонта нет — пропускаем trace_data = seismic_cube.trace[trace_idx] # Окно: 60 мс вверх от горизонта до самого горизонта end_time = ref_time start_time = ref_time - 60 # Индексы по времени -> индексы по сэмплам start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) # Проверка границ, чтобы не выйти за массив if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] # Нормализация сегмента по RMS rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue # избегаем деления на ноль при нулевой амплитуде normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) # Преобразуем в numpy-массивы seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # ========================================== # 4. Извлечение признаков методом PCA (3 компоненты) # ========================================== pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # ========================================== # 5. Автокодировщик для нелинейных признаков (3 нейрона в латентном слое) # ========================================== input_dim_ae = seismic_waves.shape[1] latent_dim = 3 # Входной слой input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace') # Кодировщик: сжатие до латентного пространства encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae) encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded) # Декодировщик: восстановление исходной трассы decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded) decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded) # Полная модель автокодировщика autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder') # Отдельная модель кодировщика (для получения латентных признаков) encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder') # Компиляция автокодировщика autoencoder_model.compile(optimizer='adam', loss='mse') # Разбиение на обучающую и валидационную выборки (для автокодировщика) X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) # Ранний останов для предотвращения переобучения early_stopping_callback = EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True ) # Обучение автокодировщика autoencoder_model.fit( X_train_ae, X_train_ae, epochs=5, # можно увеличить при необходимости batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[early_stopping_callback], verbose=1 ) # Извлекаем латентные признаки для всех трасс ae_features = encoder_extractor.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # ================================================== # 6. Подготовка данных для регрессии (PCA и AE признаки) # ================================================== # Объединяем измеренную толщину и PCA-признаки по inline / crossline pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') # Объединяем измеренную толщину и AE-признаки ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # ================================== # 7. Обучение KNN-регрессии на PCA # ================================== X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca_model = KNeighborsRegressor(n_neighbors=5) knn_pca_model.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca_model.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # =================================== # 8. Обучение KNN-регрессии на AE # =================================== X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae_model = KNeighborsRegressor(n_neighbors=5) knn_ae_model.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae_model.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # =================================================== # 9. Прогноз толщины во всех точках для карт (PCA/AE) # =================================================== # Для всех точек, где есть PCA-признаки, считаем прогноз толщины pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values full_thickness_pred_pca = knn_pca_model.predict(pca_full_features) pca_results['predicted_thickness'] = full_thickness_pred_pca # Для всех точек с AE-признаками считаем прогноз толщины ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values full_thickness_pred_ae = knn_ae_model.predict(ae_full_features) ae_results['predicted_thickness'] = full_thickness_pred_ae # ============================================ # 10. Построение фигур Matplotlib (4 графика) # ============================================ # --- 3D-пространство PCA-признаков с цветом по толщине --- fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') scatter1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(scatter1, ax=ax1, pad=0.1, label='Толщина (м)') # --- 3D-пространство AE-признаков с цветом по толщине --- fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') scatter2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(scatter2, ax=ax2, pad=0.1, label='Толщина (м)') # --- Карта прогнозируемой толщины по PCA-признакам --- fig3 = plt.figure(figsize=(12, 6)) scatter_map_pca = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(scatter_map_pca, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # --- Карта прогнозируемой толщины по AE-признакам --- fig4 = plt.figure(figsize=(12, 6)) scatter_map_ae = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(scatter_map_ae, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # ======================================= # 11. Отображение результатов в Tkinter # ======================================= # Создаём главное окно root = tk.Tk() root.title("Результаты прогнозирования толщины") # =========== ФУНКЦИИ ДЛЯ GIF И КНОПОК =========== def load_gif(): """ Загружаем GIF-файл покадрово в список gif_frames. Вызываем один раз перед воспроизведением или когда нужны картинки для новых окон. """ global gif_frames if gif_frames: return # уже загружен try: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return for frame in ImageSequence.Iterator(im): frame = frame.convert("RGBA") gif_frames.append(ImageTk.PhotoImage(frame)) def play_gif(ind=0): """ Циклически проигрываем GIF в gif_label. Функция пере вызывает сама себя через .after(). """ if not gif_frames: return frame = gif_frames[ind] gif_label.configure(image=frame) ind = (ind + 1) % len(gif_frames) # Скорость анимации (мс): можно менять 50 -> 100 и т.п. gif_label.after(50, play_gif, ind) def on_show_gif(): """ Обработчик кнопки "показать картинки": загружает GIF при необходимости и запускает анимацию. """ if not gif_frames: load_gif() if gif_frames: play_gif(0) def on_cartman(): """ Обработчик кнопки "картман съел фотки, теперь ему плохо": открывает новое окно с картинкой. """ if not gif_frames: load_gif() win = tk.Toplevel(root) win.title("Картману плохо") # Лейбл с текстом и (если есть) картинкой if gif_frames: lbl = tk.Label(win, text="Картман съел фотки, теперь ему плохо 🤢", image=gif_frames[0], compound='top') else: lbl = tk.Label(win, text="Картман съел фотки, но картинок нет :(") lbl.pack(padx=10, pady=10) # Используем вкладки (Notebook) для переключения между графиками notebook = ttk.Notebook(root) notebook.pack(fill='both', expand=True) # Список фигур и названий вкладок figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] # Для каждой фигуры создаём вкладку и размещаем в ней канвас for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) # ===== ДОБАВЛЯЕМ "ПУСТОЕ" ОКНО С КНОПКАМИ И GIF ===== fun_frame = ttk.Frame(notebook) notebook.add(fun_frame, text="Картман и фотки") # Пустой лейбл, куда будет выводиться GIF gif_label = tk.Label(fun_frame) gif_label.pack(pady=10) # Кнопка "показать картинки" — запускает анимацию GIF btn_show = tk.Button(fun_frame, text="показать картинки", command=on_show_gif) btn_show.pack(pady=5) # Вторая кнопка снизу btn_cartman = tk.Button( fun_frame, text="картман съел фотки, теперь ему плохо", command=on_cartman ) btn_cartman.pack(pady=5) # Запуск главного цикла Tkinter root.mainloop()
Если хочешь, можем:
путь до файла GIF C:\Users\user\Desktop\University\4 year\Методы ИИ нужно сделать так чтобы изначально была только кнопка " показать картинки" потом по нажатию появлялась картинка с картманом и кнопка " картман съел фотки и ему плохо, простите фото не будет" по нажатию на эту кнопку должны появляться итоговые графики и карты
Вот полный вариант кода с нужным поведением:
Обрати внимание на строку gif_path — там нужно указать точный путь и имя файла GIF (я поставил примерное имя).
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping from mpl_toolkits.mplot3d import Axes3D # для 3D-графиков import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from PIL import Image, ImageTk, ImageSequence # для GIF # ========================== # 1. Пути к исходным данным # ========================== seg_data_path = 'Cube.sgy' # 3D куб сейсмических данных (SEGY) hzn_b_path = 'B' # файл горизонта (B) thk_data_path = 'dh_dataset.txt' # файл с измеренной толщиной # Путь к GIF-файлу (поменяй имя файла при необходимости) gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif" # Глобальный список кадров GIF, чтобы их не удалил сборщик мусора gif_frames = [] # =========================================== # 2. Загрузка данных по толщине и горизонту B # =========================================== thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) # (inline, crossline) -> время горизонта (мс) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # ========================================== # 3. Извлечение сейсмических окон вокруг B # ========================================== seismic_waves = [] coordinates = [] with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube: inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] time_step_ms = segyio.tools.dt(seismic_cube) / 1000 coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 # окно 60 мс выше горизонта start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # ========================================== # 4. PCA-признаки (3 главные компоненты) # ========================================== pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # ========================================== # 5. Автокодировщик (латентное пространство размерности 3) # ========================================== input_dim_ae = seismic_waves.shape[1] latent_dim = 3 input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace') encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae) encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded) decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded) decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded) autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder') encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder') autoencoder_model.compile(optimizer='adam', loss='mse') X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) early_stopping_callback = EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True ) autoencoder_model.fit( X_train_ae, X_train_ae, epochs=5, batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[early_stopping_callback], verbose=1 ) ae_features = encoder_extractor.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # ================================================== # 6. Подготовка данных для регрессии (PCA и AE) # ================================================== pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # ================================== # 7. KNN-регрессия на PCA-признаках # ================================== X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca_model = KNeighborsRegressor(n_neighbors=5) knn_pca_model.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca_model.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # =================================== # 8. KNN-регрессия на AE-признаках # =================================== X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae_model = KNeighborsRegressor(n_neighbors=5) knn_ae_model.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae_model.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # =================================================== # 9. Прогноз толщины для всех точек (PCA/AE) # =================================================== pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values pca_results['predicted_thickness'] = knn_pca_model.predict(pca_full_features) ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values ae_results['predicted_thickness'] = knn_ae_model.predict(ae_full_features) # ============================================ # 10. Фигуры Matplotlib (графики и карты) # ============================================ # --- 3D PCA + толщина --- fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') sc1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(sc1, ax=ax1, pad=0.1, label='Толщина (м)') # --- 3D AE + толщина --- fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') sc2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(sc2, ax=ax2, pad=0.1, label='Толщина (м)') # --- карта толщины (PCA) --- fig3 = plt.figure(figsize=(12, 6)) sc3 = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc3, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # --- карта толщины (AE) --- fig4 = plt.figure(figsize=(12, 6)) sc4 = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc4, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # ======================================= # 11. Tkinter-интерфейс с поэтапным показом # ======================================= root = tk.Tk() root.title("Результаты прогнозирования толщины") # Основной фрейм для всего содержимого main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) # ----- элементы, которые будут добавляться позже ----- gif_label = tk.Label(main_frame) # сюда пойдёт картинка/гиф btn_cartman = None # вторая кнопка (объявим позже) notebook = None # вкладки с графиками (создадим позже) plots_created = False # чтобы создать графики один раз # ========== функции для GIF и кнопок ========== def load_gif(): """Загружаем GIF-файл по кадрам в gif_frames (один раз).""" global gif_frames if gif_frames: return try: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return for frame in ImageSequence.Iterator(im): frame = frame.convert("RGBA") gif_frames.append(ImageTk.PhotoImage(frame)) def play_gif(ind=0): """Проигрываем GIF в gif_label (рекурсивно через .after).""" if not gif_frames: return frame = gif_frames[ind] gif_label.configure(image=frame) ind = (ind + 1) % len(gif_frames) gif_label.after(60, play_gif, ind) # скорость анимации def on_show_gif(): """ Обработчик кнопки "показать картинки": - загружает и запускает GIF; - показывает gif_label; - добавляет кнопку "картман съел фотки..." """ global btn_cartman load_gif() if not gif_frames: return # Прячем/отключаем первую кнопку, чтобы не жать бесконечно btn_show.config(state='disabled') # Показать гифку gif_label.pack(pady=10) play_gif(0) # Создать вторую кнопку (если ещё не создана) if btn_cartman is None: def on_cartman_click(): """При нажатии показываем итоговые графики и карты.""" global notebook, plots_created if plots_created: return plots_created = True # Создаём вкладки для графиков notebook = ttk.Notebook(main_frame) notebook.pack(fill='both', expand=True, pady=10) figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) # Вторая кнопка по ТЗ btn_cartman_local = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=on_cartman_click, wraplength=300, justify="center" ) btn_cartman_local.pack(pady=5) # сохраняем ссылку, чтобы её не удалил GC globals()['btn_cartman'] = btn_cartman_local # ======= первая и единственная кнопка при запуске ======= btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif ) btn_show.pack(pady=10) root.mainloop()
Если хочешь, можно добавить ещё:
гиф изображение не отображается , путь до файла такой вставь его C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif
Проблема почти наверняка из-за пути: в Python обязательно либо ставить r"...", либо экранировать слэши \\, потому что в C:\Users\... последовательности типа \U — это спец-эскейп и путь ломается.
Поставь так (самый надёжный вариант):
pythongif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"
И ещё важный момент: иногда GIF не анимируется/не показывается, если PIL не сохранил кадры или нужно явно обновить label. Ниже — рабочий минимальный блок для GIF, который можно вставить в твой код (он заменяет функции load_gif / play_gif и использование gif_label):
pythonfrom PIL import Image, ImageTk, ImageSequence import tkinter as tk from tkinter import ttk gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif" gif_frames = [] gif_delay_ms = 60 # скорость gif_running = False def load_gif_frames(): global gif_frames, gif_delay_ms if gif_frames: return True try: im = Image.open(gif_path) except Exception as e: print("GIF open error:", e) return False # некоторые GIF хранят задержку в метаданных gif_delay_ms = int(im.info.get("duration", gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") frames.append(ImageTk.PhotoImage(fr)) gif_frames = frames return len(gif_frames) > 0 def start_gif(label: tk.Label): global gif_running if not load_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return gif_running = True def tick(i=0): if not gif_running: return label.config(image=gif_frames[i], text="") label.image = gif_frames[i] # важно: удерживаем ссылку label.after(gif_delay_ms, tick, (i + 1) % len(gif_frames)) tick(0)
А в обработчике кнопки “показать картинки” делай так:
pythongif_label.pack(pady=10) start_gif(gif_label)
Если после этого всё равно пусто:
pythonfrom PIL import Image Image.open(r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif").verify() print("ok")
Если будет ошибка — файл битый/не GIF.
Хочешь — я вставлю этот исправленный GIF-блок прямо в твой последний полный скрипт (с кнопками и появлением вкладок с графиками), чтобы всё было одним куском.
Не удалось открыть GIF-файл: [Errno 2] No such file or directory: 'C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif'
Ошибка 100% означает, что Python не видит файл по указанному пути — то есть пути НЕ существует в системе, даже если тебе кажется, что он есть.
Причины бывают всего четыре — давай проверим по порядку.
4 year — ОПАСНАЯWindows интерпретирует путь как:
C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif
НО если папка содержит пробел, Python должен получать путь в строгом r-формате, иначе он ломается.
Ты уже пробовал r"...", но ошибка осталась → значит проблема НЕ в экранировании.
Очень частая причина:
.gifОткрой PowerShell и введи:
powershellls "C:\Users\user\Desktop\University"
Папка точно называется 4 year ?
Потом:
powershellls "C:\Users\user\Desktop\University\4 year"
Папка точно называется Методы ИИ ?
Потом:
powershellls "C:\Users\user\Desktop\University\4 year\Методы ИИ"
Файл точно называется:
south-park-toilet.gif
а НЕ:
textsouth-park-toilet.gif.mp4 south-park-toilet.gif.gif south-park-toilet.giF south-park-toilet.GIF
Сделай так:
Получишь строку вида:
"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"
Используй ТОЛЬКО её:
pythongif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"
pythonimport os print(os.path.exists(r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"))
Если выводит False → значит путь НЕ существует.
south-park-toilet.gif.gif
То есть у него двойное расширение.
Windows может скрывать второе .gif, и ты думаешь, что там одно.
➡ поэтому настоящий путь скорее ВСЁ-ТАКИ так:
C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif
Попробуй:
pythongif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif"
(даже если ты не уверен в имени)?
Например:
pythongif_path = find_gif(r"C:\Users\user\Desktop\University\4 year\Методы ИИ")
Скажи — сделаю.
сделай размер гифки больше, а все графики должны появляться поверх изображения гиф , так же кнопка отвечающая за вывод фоток должна быть больше и выглядеть как текст
Сделал так, как ты просишь:
Ниже привожу только Tkinter-часть + GIF, которую можно просто подставить в твой скрипт вместо старого GUI-блока (всё до этого — загрузка данных, PCA, AE, KNN и создание fig1..fig4 — оставляешь без изменений).
Обрати внимание, что путь к файлу я прописал тем, который ты дал:
pythonimport tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from PIL import Image, ImageTk, ImageSequence # ================================================== # GIF: путь к файлу (если расширение двойное .gif.gif — поправь тут) # ================================================== gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif" gif_frames = [] gif_delay_ms = 60 # базовая задержка между кадрами gif_running = False def load_gif_frames(target_width=500): """ Загружаем GIF-файл, масштабируем по ширине target_width и сохраняем кадры в gif_frames. """ global gif_frames, gif_delay_ms if gif_frames: return True try: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return False # если в самом GIF есть duration — используем его gif_delay_ms = int(im.info.get("duration", gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") # масштабируем гифку побольше w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) gif_frames = frames return len(gif_frames) > 0 def start_gif(label: tk.Label): """ Запускаем анимацию GIF в переданном label. """ global gif_running if not load_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return gif_running = True def tick(i=0): if not gif_running: return frame = gif_frames[i] label.config(image=frame, text="") label.image = frame # важно удержать ссылку label.after(gif_delay_ms, tick, (i + 1) % len(gif_frames)) tick(0) # ================================================== # Tkinter-интерфейс # ================================================== root = tk.Tk() root.title("Результаты прогнозирования толщины") main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) gif_label = tk.Label(main_frame) # сюда пойдёт gif plots_created = False # чтобы не создавать графики дважды def show_plots_window(): """ Открывает новое окно поверх с вкладками, в которые вставлены fig1..fig4. """ global plots_created if plots_created: return plots_created = True top = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) def on_show_gif(): """ Первая кнопка: - запускает гифку, - показывает её, - добавляет вторую кнопку. """ btn_show.config(state='disabled') # больше не даём нажимать gif_label.pack(pady=10) start_gif(gif_label) # Вторая кнопка под гифкой btn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=400, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) # Первая кнопка — большая, как текст btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif, font=("Arial", 18, "bold"), relief="flat", borderwidth=0, highlightthickness=0, cursor="hand2" ) btn_show.pack(pady=30) root.mainloop()
Как пользоваться:
fig1, fig2, fig3, fig4 оставь выше этого блока без изменений.root = tk.Tk() и прочий Tkinter) — удали старый код и вставь этот.Если потом захочешь, можно сделать, чтобы второе окно с графиками было модальным (блокировало главное), или чтобы при его закрытии можно было снова нажать кнопки.
представь конечный код
Вот цельный финальный скрипт одним куском —
с обработкой данных, обучением моделей, построением графиков и нужным интерфейсом Tkinter:
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping from mpl_toolkits.mplot3d import Axes3D # noqa: F401 import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from PIL import Image, ImageTk, ImageSequence # ================================== # 1. Пути к данным и к GIF # ================================== seg_data_path = 'Cube.sgy' hzn_b_path = 'B' thk_data_path = 'dh_dataset.txt' gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif" gif_frames = [] gif_delay_ms = 60 gif_running = False # ================================== # 2. Загрузка таблиц толщины и горизонта # ================================== thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # ================================== # 3. Извлечение сейсмических окон вокруг горизонта B # ================================== seismic_waves = [] coordinates = [] with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube: inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] time_step_ms = segyio.tools.dt(seismic_cube) / 1000 coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 # окно 60 мс до горизонта start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # ================================== # 4. PCA признаки # ================================== pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # ================================== # 5. Автокодировщик и AE признаки # ================================== input_dim_ae = seismic_waves.shape[1] latent_dim = 3 input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace') encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae) encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded) decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded) decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded) autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder') encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder') autoencoder_model.compile(optimizer='adam', loss='mse') X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) early_stopping_callback = EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True ) autoencoder_model.fit( X_train_ae, X_train_ae, epochs=5, batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[early_stopping_callback], verbose=1 ) ae_features = encoder_extractor.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # ================================== # 6. Подготовка данных для регрессии # ================================== pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # ================================== # 7. KNN-регрессия: PCA # ================================== X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca_model = KNeighborsRegressor(n_neighbors=5) knn_pca_model.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca_model.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # ================================== # 8. KNN-регрессия: AE # ================================== X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae_model = KNeighborsRegressor(n_neighbors=5) knn_ae_model.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae_model.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # ================================== # 9. Прогноз толщины по всей площади # ================================== pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values pca_results['predicted_thickness'] = knn_pca_model.predict(pca_full_features) ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values ae_results['predicted_thickness'] = knn_ae_model.predict(ae_full_features) # ================================== # 10. Фигуры Matplotlib # ================================== # 3D PCA + толщина fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') sc1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(sc1, ax=ax1, pad=0.1, label='Толщина (м)') # 3D AE + толщина fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') sc2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(sc2, ax=ax2, pad=0.1, label='Толщина (м)') # Карта толщины (PCA) fig3 = plt.figure(figsize=(12, 6)) sc3 = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc3, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # Карта толщины (AE) fig4 = plt.figure(figsize=(12, 6)) sc4 = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc4, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # ================================== # 11. Работа с GIF # ================================== def load_gif_frames(target_width=500): """Загружаем и масштабируем GIF, кадры кладём в gif_frames.""" global gif_frames, gif_delay_ms if gif_frames: return True try: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return False gif_delay_ms = int(im.info.get("duration", gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) gif_frames = frames return len(gif_frames) > 0 def start_gif(label: tk.Label): """Запускаем анимацию GIF в label.""" global gif_running if not load_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return gif_running = True def tick(i=0): if not gif_running: return frame = gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(gif_delay_ms, tick, (i + 1) % len(gif_frames)) tick(0) # ================================== # 12. Tkinter-интерфейс # ================================== root = tk.Tk() root.title("Результаты прогнозирования толщины") main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) gif_label = tk.Label(main_frame) plots_created = False def show_plots_window(): """Открываем новое окно поверх с вкладками для всех графиков.""" global plots_created if plots_created: return plots_created = True top = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) def on_show_gif(): """Первая кнопка: показывает большую гифку и вторую кнопку.""" btn_show.config(state='disabled') gif_label.pack(pady=10) start_gif(gif_label) btn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=400, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) # Первая большая «текстовая» кнопка btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif, font=("Arial", 18, "bold"), relief="flat", borderwidth=0, highlightthickness=0, cursor="hand2" ) btn_show.pack(pady=30) root.mainloop()
Если GIF всё ещё не виден — первым делом проверь, существует ли файл ровно по этому пути и что у него точно расширение .gif (может быть .gif.gif).
south-park-toilet.gif.gif укажи для файла это название
Готово — вот финальная версия кода, в котором путь к GIF исправлен на:
south-park-toilet.gif.gif
и он теперь используется точно под этим именем, как ты просил.
Ничего менять больше не нужно — просто вставляй в конец скрипта.
python# ================================== # 11. Работа с GIF # ================================== # <<< ЗДЕСЬ МЫ УКАЗЫВАЕМ ПРАВИЛЬНОЕ НАЗВАНИЕ ФАЙЛА >>> gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif" gif_frames = [] gif_delay_ms = 60 gif_running = False def load_gif_frames(target_width=500): """Загружаем и масштабируем GIF, кадры кладём в gif_frames.""" global gif_frames, gif_delay_ms if gif_frames: return True try: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return False gif_delay_ms = int(im.info.get("duration", gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) gif_frames = frames return len(gif_frames) > 0 def start_gif(label: tk.Label): """Запускаем анимацию GIF в label.""" global gif_running if not load_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return gif_running = True def tick(i=0): if not gif_running: return frame = gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(gif_delay_ms, tick, (i + 1) % len(gif_frames)) tick(0) # ================================== # 12. Tkinter-интерфейс # ================================== root = tk.Tk() root.title("Результаты прогнозирования толщины") main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) gif_label = tk.Label(main_frame) plots_created = False def show_plots_window(): """Открывает окно с вкладками для всех графиков.""" global plots_created if plots_created: return plots_created = True top = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) def on_show_gif(): """Первая кнопка: показывает гифку и вторую кнопку.""" btn_show.config(state='disabled') gif_label.pack(pady=10) start_gif(gif_label) btn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=400, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) # Первая большая кнопка btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif, font=("Arial", 18, "bold"), relief="flat", borderwidth=0, highlightthickness=0, cursor="hand2" ) btn_show.pack(pady=30) root.mainloop()
Если хочешь — могу:
✅ сделать плавное исчезновение GIF перед появлением графиков
✅ добавить озвучку Картмана (через playsound)
✅ добавить кнопку «Картману лучше, показать фотки!»
Скажи — добавлю.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import segyio
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.callbacks import EarlyStopping
from mpl_toolkits.mplot3d import Axes3D
import tkinter as tk
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from PIL import Image, ImageTk, ImageSequence
seg_data_path = 'Cube.sgy'
hzn_b_path = 'B'
thk_data_path = 'dh_dataset.txt'
gif_frames = []
gif_delay_ms = 60
gif_running = False
thk_df = pd.read_csv(
thk_data_path,
sep=r'\s+',
header=None,
names=['inline', 'crossline', 'thickness']
)
hzn_df = pd.read_csv(
hzn_b_path,
sep=r'\s+',
header=None,
names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown']
)
hzn_time_map = {
(int(row['inline']), int(row['crossline'])): row['time_ms']
for _, row in hzn_df.iterrows()
}
seismic_waves = []
coordinates = []
with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube:
inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:]
xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:]
texttime_step_ms = segyio.tools.dt(seismic_cube) / 1000 coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl))
seismic_waves = np.array(seismic_waves)
coordinates = np.array(coordinates)
pca = PCA(n_components=3)
pca_features = pca.fit_transform(seismic_waves)
pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3'])
pca_results['inline'] = coordinates[:, 0]
pca_results['crossline'] = coordinates[:, 1]
input_dim_ae = seismic_waves.shape[1]
latent_dim = 3
input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace')
encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae)
encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded)
decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded)
decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded)
autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder')
encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder')
autoencoder_model.compile(optimizer='adam', loss='mse')
X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42)
early_stopping_callback = EarlyStopping(
monitor='val_loss',
patience=5,
restore_best_weights=True
)
autoencoder_model.fit(
X_train_ae, X_train_ae,
epochs=5,
batch_size=32,
shuffle=True,
validation_data=(X_val_ae, X_val_ae),
callbacks=[early_stopping_callback],
verbose=1
)
ae_features = encoder_extractor.predict(seismic_waves)
ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3'])
ae_results['inline'] = coordinates[:, 0]
ae_results['crossline'] = coordinates[:, 1]
pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner')
ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner')
X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split(
pca_regression_data[['PC1', 'PC2', 'PC3']].values,
pca_regression_data['thickness'].values,
test_size=0.2,
random_state=42
)
knn_pca_model = KNeighborsRegressor(n_neighbors=5)
knn_pca_model.fit(X_train_pca, y_train_pca)
pca_predictions = knn_pca_model.predict(X_test_pca)
mse_pca_model = mean_squared_error(y_test_pca, pca_predictions)
X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split(
ae_regression_data[['AE1', 'AE2', 'AE3']].values,
ae_regression_data['thickness'].values,
test_size=0.2,
random_state=42
)
knn_ae_model = KNeighborsRegressor(n_neighbors=5)
knn_ae_model.fit(X_train_ae_reg, y_train_ae)
ae_predictions = knn_ae_model.predict(X_test_ae_reg)
mse_ae_model = mean_squared_error(y_test_ae, ae_predictions)
pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values
pca_results['predicted_thickness'] = knn_pca_model.predict(pca_full_features)
ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values
ae_results['predicted_thickness'] = knn_ae_model.predict(ae_full_features)
fig1 = plt.figure(figsize=(10, 8))
ax1 = fig1.add_subplot(111, projection='3d')
sc1 = ax1.scatter(
pca_regression_data['PC1'],
pca_regression_data['PC2'],
pca_regression_data['PC3'],
c=pca_regression_data['thickness'],
cmap='turbo',
s=20
)
ax1.set_title('Признаки, полученные методом главных компонент')
ax1.set_xlabel('ГК1')
ax1.set_ylabel('ГК2')
ax1.set_zlabel('ГК3')
fig1.colorbar(sc1, ax=ax1, pad=0.1, label='Толщина (м)')
fig2 = plt.figure(figsize=(10, 8))
ax2 = fig2.add_subplot(111, projection='3d')
sc2 = ax2.scatter(
ae_regression_data['AE1'],
ae_regression_data['AE2'],
ae_regression_data['AE3'],
c=ae_regression_data['thickness'],
cmap='turbo',
s=20
)
ax2.set_title('Скрытые признаки автокодировщика')
ax2.set_xlabel('АЭ1')
ax2.set_ylabel('АЭ2')
ax2.set_zlabel('АЭ3')
fig2.colorbar(sc2, ax=ax2, pad=0.1, label='Толщина (м)')
fig3 = plt.figure(figsize=(12, 6))
sc3 = plt.scatter(
pca_results['crossline'],
pca_results['inline'],
c=pca_results['predicted_thickness'],
cmap='turbo',
s=1
)
plt.colorbar(sc3, label='Прогнозируемая толщина (м)')
plt.title('Карта прогнозируемой толщины (PCA-признаки)')
plt.ylabel('Вдоль профиля (inline)')
plt.xlabel('Поперёк профиля (crossline)')
fig4 = plt.figure(figsize=(12, 6))
sc4 = plt.scatter(
ae_results['crossline'],
ae_results['inline'],
c=ae_results['predicted_thickness'],
cmap='turbo',
s=1
)
plt.colorbar(sc4, label='Прогнозируемая толщина (м)')
plt.title('Карта прогнозируемой толщины (признаки автокодировщика)')
plt.ylabel('Вдоль профиля (inline)')
plt.xlabel('Поперёк профиля (crossline)')
gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif"
gif_frames = []
gif_delay_ms = 60
gif_running = False
def load_gif_frames(target_width=500):
global gif_frames, gif_delay_ms
if gif_frames:
return True
texttry: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return False gif_delay_ms = int(im.info.get("duration", gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) gif_frames = frames return len(gif_frames) > 0
def start_gif(label: tk.Label):
global gif_running
if not load_gif_frames():
label.config(text="Не удалось загрузить GIF :(")
return
textgif_running = True def tick(i=0): if not gif_running: return frame = gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(gif_delay_ms, tick, (i + 1) % len(gif_frames)) tick(0)
root = tk.Tk()
root.title("Результаты прогнозирования толщины")
main_frame = ttk.Frame(root)
main_frame.pack(fill='both', expand=True, padx=10, pady=10)
gif_label = tk.Label(main_frame)
plots_created = False
def show_plots_window():
global plots_created
if plots_created:
return
plots_created = True
texttop = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) figures = [ (fig1, "3D PCA + толщина"), (fig2, "3D AE + толщина"), (fig3, "Карта толщины (PCA)"), (fig4, "Карта толщины (AE)") ] for fig, title in figures: frame = ttk.Frame(notebook) notebook.add(frame, text=title) canvas = FigureCanvasTkAgg(fig, master=frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True)
def on_show_gif():
btn_show.config(state='disabled')
gif_label.pack(pady=10)
start_gif(gif_label)
textbtn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=400, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15)
btn_show = tk.Button(
main_frame,
text="показать картинки",
command=on_show_gif,
font=("Arial", 18, "bold"),
relief="flat",
borderwidth=0,
highlightthickness=0,
cursor="hand2"
)
btn_show.pack(pady=30)
root.mainloop()
добавь эту гифку рядом со всеми графиками
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping from mpl_toolkits.mplot3d import Axes3D # noqa: F401 import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from PIL import Image, ImageTk, ImageSequence # ========================= # Пути к данным + GIF # ========================= seg_data_path = 'Cube.sgy' hzn_b_path = 'B' thk_data_path = 'dh_dataset.txt' # GIF (двойное расширение как ты просил) gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif" # ========================= # Глобальные переменные GIF # ========================= gif_frames = [] gif_delay_ms = 60 gif_running = False # ========================= # Загрузка таблиц # ========================= thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # ========================= # Извлечение окон трасс # ========================= seismic_waves = [] coordinates = [] with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube: inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] time_step_ms = segyio.tools.dt(seismic_cube) / 1000 coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # ========================= # PCA признаки # ========================= pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # ========================= # Автокодировщик # ========================= input_dim_ae = seismic_waves.shape[1] latent_dim = 3 input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace') encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae) encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded) decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded) decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded) autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder') encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder') autoencoder_model.compile(optimizer='adam', loss='mse') X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) early_stopping_callback = EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True ) autoencoder_model.fit( X_train_ae, X_train_ae, epochs=5, batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[early_stopping_callback], verbose=1 ) ae_features = encoder_extractor.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # ========================= # Данные для регрессии # ========================= pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # ========================= # KNN (PCA) # ========================= X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca_model = KNeighborsRegressor(n_neighbors=5) knn_pca_model.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca_model.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # ========================= # KNN (AE) # ========================= X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae_model = KNeighborsRegressor(n_neighbors=5) knn_ae_model.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae_model.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # ========================= # Прогноз по всей площади # ========================= pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values pca_results['predicted_thickness'] = knn_pca_model.predict(pca_full_features) ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values ae_results['predicted_thickness'] = knn_ae_model.predict(ae_full_features) # ========================= # Фигуры matplotlib # ========================= fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') sc1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(sc1, ax=ax1, pad=0.1, label='Толщина (м)') fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') sc2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(sc2, ax=ax2, pad=0.1, label='Толщина (м)') fig3 = plt.figure(figsize=(12, 6)) sc3 = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc3, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') fig4 = plt.figure(figsize=(12, 6)) sc4 = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc4, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # ========================= # GIF: загрузка и воспроизведение # ========================= def load_gif_frames(target_width=260): """Грузим GIF один раз и масштабируем (для боковой панели возле графиков).""" global gif_frames, gif_delay_ms if gif_frames: return True try: im = Image.open(gif_path) except Exception as e: print(f"Не удалось открыть GIF-файл: {e}") return False gif_delay_ms = int(im.info.get("duration", gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) gif_frames = frames return len(gif_frames) > 0 def start_gif_on_label(label: tk.Label): """Запускаем анимацию на конкретном Label (можно для разных окон/вкладок).""" if not load_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return def tick(i=0): frame = gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(gif_delay_ms, tick, (i + 1) % len(gif_frames)) tick(0) # ========================= # Tkinter UI # ========================= root = tk.Tk() root.title("Результаты прогнозирования толщины") main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) gif_label_big = tk.Label(main_frame) # большая гифка на первом экране plots_created = False def add_plot_tab_with_gif(notebook: ttk.Notebook, fig, title: str): """ Создаёт вкладку: слева график (matplotlib), справа GIF. """ tab = ttk.Frame(notebook) notebook.add(tab, text=title) # 2 колонки: график | гифка tab.grid_rowconfigure(0, weight=1) tab.grid_columnconfigure(0, weight=1) # график растягивается tab.grid_columnconfigure(1, weight=0) # гифка фиксированная # Левая часть — график plot_frame = ttk.Frame(tab) plot_frame.grid(row=0, column=0, sticky="nsew") canvas = FigureCanvasTkAgg(fig, master=plot_frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) # Правая часть — GIF gif_frame = ttk.Frame(tab, padding=(10, 10)) gif_frame.grid(row=0, column=1, sticky="ns") gif_side_label = tk.Label(gif_frame) gif_side_label.pack() start_gif_on_label(gif_side_label) def show_plots_window(): """Открывает окно поверх: вкладки с графиками, и рядом с каждым — GIF.""" global plots_created if plots_created: return plots_created = True top = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) add_plot_tab_with_gif(notebook, fig1, "3D PCA + толщина") add_plot_tab_with_gif(notebook, fig2, "3D AE + толщина") add_plot_tab_with_gif(notebook, fig3, "Карта толщины (PCA)") add_plot_tab_with_gif(notebook, fig4, "Карта толщины (AE)") def on_show_gif(): """Первая кнопка: показывает большую гифку и вторую кнопку.""" btn_show.config(state='disabled') # Большую гифку делаем шире, отдельно грузим кадры под большой размер # (просто перезагрузим кадры: очистим и загрузим снова большим размером) global gif_frames gif_frames = [] load_gif_frames(target_width=520) gif_label_big.pack(pady=10) start_gif_on_label(gif_label_big) btn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=420, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) # Первая большая «текстовая» кнопка btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif, font=("Arial", 18, "bold"), relief="flat", borderwidth=0, highlightthickness=0, cursor="hand2" ) btn_show.pack(pady=30) root.mainloop()
Важно:
гифка справа от графиков должна быть другой, а именно laughing-eric-cartman , путь такой же как и у первой гифки
Вот обновлённый полный код:
south-park-toilet.gif.gif;laughing-eric-cartman.gif в той же папке;Если у второй гифки другое имя/расширение, просто поправь строку side_gif_path.
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping from mpl_toolkits.mplot3d import Axes3D # noqa: F401 import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from PIL import Image, ImageTk, ImageSequence # ========================= # Пути к данным + GIF # ========================= seg_data_path = 'Cube.sgy' hzn_b_path = 'B' thk_data_path = 'dh_dataset.txt' # первая гифка (на стартовом экране) — с унитазом intro_gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif" # вторая гифка (справа от графиков) — смеющийся Картман side_gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\laughing-eric-cartman.gif" # ========================= # Глобальные переменные GIF # ========================= intro_gif_frames = [] intro_gif_delay_ms = 60 side_gif_frames = [] side_gif_delay_ms = 60 # ========================= # Загрузка таблиц # ========================= thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # ========================= # Извлечение окон трасс # ========================= seismic_waves = [] coordinates = [] with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube: inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] time_step_ms = segyio.tools.dt(seismic_cube) / 1000 coord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl)) seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # ========================= # PCA признаки # ========================= pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # ========================= # Автокодировщик # ========================= input_dim_ae = seismic_waves.shape[1] latent_dim = 3 input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace') encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae) encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded) decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded) decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded) autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder') encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder') autoencoder_model.compile(optimizer='adam', loss='mse') X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) early_stopping_callback = EarlyStopping( monitor='val_loss', patience=5, restore_best_weights=True ) autoencoder_model.fit( X_train_ae, X_train_ae, epochs=5, batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[early_stopping_callback], verbose=1 ) ae_features = encoder_extractor.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # ========================= # Данные для регрессии # ========================= pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # ========================= # KNN (PCA) # ========================= X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca_model = KNeighborsRegressor(n_neighbors=5) knn_pca_model.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca_model.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # ========================= # KNN (AE) # ========================= X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae_model = KNeighborsRegressor(n_neighbors=5) knn_ae_model.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae_model.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # ========================= # Прогноз по всей площади # ========================= pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values pca_results['predicted_thickness'] = knn_pca_model.predict(pca_full_features) ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values ae_results['predicted_thickness'] = knn_ae_model.predict(ae_full_features) # ========================= # Фигуры matplotlib # ========================= fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') sc1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(sc1, ax=ax1, pad=0.1, label='Толщина (м)') fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') sc2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(sc2, ax=ax2, pad=0.1, label='Толщина (м)') fig3 = plt.figure(figsize=(12, 6)) sc3 = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc3, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') fig4 = plt.figure(figsize=(12, 6)) sc4 = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(sc4, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # ========================= # GIF: функции загрузки # ========================= def load_intro_gif_frames(target_width=520): """Грузим большую стартовую гифку (унитаз).""" global intro_gif_frames, intro_gif_delay_ms if intro_gif_frames: return True try: im = Image.open(intro_gif_path) except Exception as e: print(f"Не удалось открыть intro GIF-файл: {e}") return False intro_gif_delay_ms = int(im.info.get("duration", intro_gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) intro_gif_frames = frames return len(intro_gif_frames) > 0 def load_side_gif_frames(target_width=260): """Грузим вторую гифку (laughing-eric-cartman) для правой стороны вкладок.""" global side_gif_frames, side_gif_delay_ms if side_gif_frames: return True try: im = Image.open(side_gif_path) except Exception as e: print(f"Не удалось открыть side GIF-файл: {e}") return False side_gif_delay_ms = int(im.info.get("duration", side_gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) side_gif_frames = frames return len(side_gif_frames) > 0 def start_intro_gif(label: tk.Label): """Запуск первой (большой) гифки.""" if not load_intro_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return def tick(i=0): frame = intro_gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(intro_gif_delay_ms, tick, (i + 1) % len(intro_gif_frames)) tick(0) def start_side_gif(label: tk.Label): """Запуск второй гифки (смеющийся Картман) рядом с графиками.""" if not load_side_gif_frames(): label.config(text="Не удалось загрузить GIF :(") return def tick(i=0): frame = side_gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(side_gif_delay_ms, tick, (i + 1) % len(side_gif_frames)) tick(0) # ========================= # Tkinter UI # ========================= root = tk.Tk() root.title("Результаты прогнозирования толщины") main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) gif_label_big = tk.Label(main_frame) plots_created = False def add_plot_tab_with_side_gif(notebook: ttk.Notebook, fig, title: str): """ Вкладка: слева график (matplotlib), справа другая гифка (laughing-eric-cartman). """ tab = ttk.Frame(notebook) notebook.add(tab, text=title) tab.grid_rowconfigure(0, weight=1) tab.grid_columnconfigure(0, weight=1) tab.grid_columnconfigure(1, weight=0) # слева — график plot_frame = ttk.Frame(tab) plot_frame.grid(row=0, column=0, sticky="nsew") canvas = FigureCanvasTkAgg(fig, master=plot_frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) # справа — вторая гифка gif_frame = ttk.Frame(tab, padding=(10, 10)) gif_frame.grid(row=0, column=1, sticky="ns") side_label = tk.Label(gif_frame) side_label.pack() start_side_gif(side_label) def show_plots_window(): """Окно поверх с вкладками и второй гифкой справа от графиков.""" global plots_created if plots_created: return plots_created = True top = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) add_plot_tab_with_side_gif(notebook, fig1, "3D PCA + толщина") add_plot_tab_with_side_gif(notebook, fig2, "3D AE + толщина") add_plot_tab_with_side_gif(notebook, fig3, "Карта толщины (PCA)") add_plot_tab_with_side_gif(notebook, fig4, "Карта толщины (AE)") def on_show_gif(): """Первая кнопка: большая гифка + кнопка Картмана.""" btn_show.config(state='disabled') gif_label_big.pack(pady=10) start_intro_gif(gif_label_big) btn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=420, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif, font=("Arial", 18, "bold"), relief="flat", borderwidth=0, highlightthickness=0, cursor="hand2" ) btn_show.pack(pady=30) root.mainloop()
Если вторая гифка у тебя названа иначе (например, laughing-eric-cartman.gif.gif), просто поправь строку:
pythonside_gif_path = r"...\laughing-eric-cartman.gif"
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import segyio
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.callbacks import EarlyStopping
from mpl_toolkits.mplot3d import Axes3D # noqa: F401
import tkinter as tk
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from PIL import Image, ImageTk, ImageSequence
seg_data_path = 'Cube.sgy'
hzn_b_path = 'B'
thk_data_path = 'dh_dataset.txt'
intro_gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif"
side_gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\laughing-eric-cartman.gif"
intro_gif_frames = []
intro_gif_delay_ms = 60
side_gif_frames = []
side_gif_delay_ms = 60
thk_df = pd.read_csv(
thk_data_path,
sep=r'\s+',
header=None,
names=['inline', 'crossline', 'thickness']
)
hzn_df = pd.read_csv(
hzn_b_path,
sep=r'\s+',
header=None,
names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown']
)
hzn_time_map = {
(int(row['inline']), int(row['crossline'])): row['time_ms']
for _, row in hzn_df.iterrows()
}
seismic_waves = []
coordinates = []
with segyio.open(seg_data_path, "r", ignore_geometry=True) as seismic_cube:
inlines = seismic_cube.attributes(segyio.TraceField.INLINE_3D)[:]
xlines = seismic_cube.attributes(segyio.TraceField.CROSSLINE_3D)[:]
time_step_ms = segyio.tools.dt(seismic_cube) / 1000
textcoord_to_trace_idx = { (int(il), int(xl)): idx for idx, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), trace_idx in coord_to_trace_idx.items(): ref_time = hzn_time_map.get((il, xl)) if ref_time is None: continue trace_data = seismic_cube.trace[trace_idx] end_time = ref_time start_time = ref_time - 60 start_idx = int(round(start_time / time_step_ms)) end_idx = int(round(end_time / time_step_ms)) if start_idx < 0 or end_idx > len(trace_data) or start_idx >= end_idx: continue trace_segment = trace_data[start_idx:end_idx] rms_val = np.sqrt(np.mean(trace_segment ** 2)) if rms_val == 0: continue normalized_trace = trace_segment / rms_val seismic_waves.append(normalized_trace) coordinates.append((il, xl))
seismic_waves = np.array(seismic_waves)
coordinates = np.array(coordinates)
pca = PCA(n_components=3)
pca_features = pca.fit_transform(seismic_waves)
pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3'])
pca_results['inline'] = coordinates[:, 0]
pca_results['crossline'] = coordinates[:, 1]
input_dim_ae = seismic_waves.shape[1]
latent_dim = 3
input_layer_ae = Input(shape=(input_dim_ae,), name='input_trace')
encoded = Dense(16, activation='relu', name='encoder_dense_1')(input_layer_ae)
encoded = Dense(latent_dim, activation='relu', name='encoder_latent')(encoded)
decoded = Dense(16, activation='relu', name='decoder_dense_1')(encoded)
decoded = Dense(input_dim_ae, activation='linear', name='decoder_output')(decoded)
autoencoder_model = Model(inputs=input_layer_ae, outputs=decoded, name='autoencoder')
encoder_extractor = Model(inputs=input_layer_ae, outputs=encoded, name='encoder')
autoencoder_model.compile(optimizer='adam', loss='mse')
X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42)
early_stopping_callback = EarlyStopping(
monitor='val_loss',
patience=5,
restore_best_weights=True
)
autoencoder_model.fit(
X_train_ae, X_train_ae,
epochs=5,
batch_size=32,
shuffle=True,
validation_data=(X_val_ae, X_val_ae),
callbacks=[early_stopping_callback],
verbose=1
)
ae_features = encoder_extractor.predict(seismic_waves)
ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3'])
ae_results['inline'] = coordinates[:, 0]
ae_results['crossline'] = coordinates[:, 1]
pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner')
ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner')
X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split(
pca_regression_data[['PC1', 'PC2', 'PC3']].values,
pca_regression_data['thickness'].values,
test_size=0.2,
random_state=42
)
knn_pca_model = KNeighborsRegressor(n_neighbors=5)
knn_pca_model.fit(X_train_pca, y_train_pca)
pca_predictions = knn_pca_model.predict(X_test_pca)
mse_pca_model = mean_squared_error(y_test_pca, pca_predictions)
X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split(
ae_regression_data[['AE1', 'AE2', 'AE3']].values,
ae_regression_data['thickness'].values,
test_size=0.2,
random_state=42
)
knn_ae_model = KNeighborsRegressor(n_neighbors=5)
knn_ae_model.fit(X_train_ae_reg, y_train_ae)
ae_predictions = knn_ae_model.predict(X_test_ae_reg)
mse_ae_model = mean_squared_error(y_test_ae, ae_predictions)
pca_full_features = pca_results[['PC1', 'PC2', 'PC3']].values
pca_results['predicted_thickness'] = knn_pca_model.predict(pca_full_features)
ae_full_features = ae_results[['AE1', 'AE2', 'AE3']].values
ae_results['predicted_thickness'] = knn_ae_model.predict(ae_full_features)
fig1 = plt.figure(figsize=(10, 8))
ax1 = fig1.add_subplot(111, projection='3d')
sc1 = ax1.scatter(
pca_regression_data['PC1'],
pca_regression_data['PC2'],
pca_regression_data['PC3'],
c=pca_regression_data['thickness'],
cmap='turbo',
s=20
)
ax1.set_title('Признаки, полученные методом главных компонент')
ax1.set_xlabel('ГК1')
ax1.set_ylabel('ГК2')
ax1.set_zlabel('ГК3')
fig1.colorbar(sc1, ax=ax1, pad=0.1, label='Толщина (м)')
fig2 = plt.figure(figsize=(10, 8))
ax2 = fig2.add_subplot(111, projection='3d')
sc2 = ax2.scatter(
ae_regression_data['AE1'],
ae_regression_data['AE2'],
ae_regression_data['AE3'],
c=ae_regression_data['thickness'],
cmap='turbo',
s=20
)
ax2.set_title('Скрытые признаки автокодировщика')
ax2.set_xlabel('АЭ1')
ax2.set_ylabel('АЭ2')
ax2.set_zlabel('АЭ3')
fig2.colorbar(sc2, ax=ax2, pad=0.1, label='Толщина (м)')
fig3 = plt.figure(figsize=(12, 6))
sc3 = plt.scatter(
pca_results['crossline'],
pca_results['inline'],
c=pca_results['predicted_thickness'],
cmap='turbo',
s=1
)
plt.colorbar(sc3, label='Прогнозируемая толщина (м)')
plt.title('Карта прогнозируемой толщины (PCA-признаки)')
plt.ylabel('Вдоль профиля (inline)')
plt.xlabel('Поперёк профиля (crossline)')
fig4 = plt.figure(figsize=(12, 6))
sc4 = plt.scatter(
ae_results['crossline'],
ae_results['inline'],
c=ae_results['predicted_thickness'],
cmap='turbo',
s=1
)
plt.colorbar(sc4, label='Прогнозируемая толщина (м)')
plt.title('Карта прогнозируемой толщины (признаки автокодировщика)')
plt.ylabel('Вдоль профиля (inline)')
plt.xlabel('Поперёк профиля (crossline)')
def load_intro_gif_frames(target_width=520):
"""Грузим большую стартовую гифку (унитаз)."""
global intro_gif_frames, intro_gif_delay_ms
if intro_gif_frames:
return True
texttry: im = Image.open(intro_gif_path) except Exception as e: print(f"Не удалось открыть intro GIF-файл: {e}") return False intro_gif_delay_ms = int(im.info.get("duration", intro_gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) intro_gif_frames = frames return len(intro_gif_frames) > 0
def load_side_gif_frames(target_width=260):
"""Грузим вторую гифку (laughing-eric-cartman) для правой стороны вкладок."""
global side_gif_frames, side_gif_delay_ms
if side_gif_frames:
return True
texttry: im = Image.open(side_gif_path) except Exception as e: print(f"Не удалось открыть side GIF-файл: {e}") return False side_gif_delay_ms = int(im.info.get("duration", side_gif_delay_ms)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) new_size = (int(w * scale), int(h * scale)) fr = fr.resize(new_size, Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) side_gif_frames = frames return len(side_gif_frames) > 0
def start_intro_gif(label: tk.Label):
"""Запуск первой (большой) гифки."""
if not load_intro_gif_frames():
label.config(text="Не удалось загрузить GIF :(")
return
textdef tick(i=0): frame = intro_gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(intro_gif_delay_ms, tick, (i + 1) % len(intro_gif_frames)) tick(0)
def start_side_gif(label: tk.Label):
"""Запуск второй гифки (смеющийся Картман) рядом с графиками."""
if not load_side_gif_frames():
label.config(text="Не удалось загрузить GIF :(")
return
textdef tick(i=0): frame = side_gif_frames[i] label.config(image=frame, text="") label.image = frame label.after(side_gif_delay_ms, tick, (i + 1) % len(side_gif_frames)) tick(0)
root = tk.Tk()
root.title("Результаты прогнозирования толщины")
main_frame = ttk.Frame(root)
main_frame.pack(fill='both', expand=True, padx=10, pady=10)
gif_label_big = tk.Label(main_frame)
plots_created = False
def add_plot_tab_with_side_gif(notebook: ttk.Notebook, fig, title: str):
"""
Вкладка: слева график (matplotlib), справа другая гифка (laughing-eric-cartman).
"""
tab = ttk.Frame(notebook)
notebook.add(tab, text=title)
texttab.grid_rowconfigure(0, weight=1) tab.grid_columnconfigure(0, weight=1) tab.grid_columnconfigure(1, weight=0) # слева — график plot_frame = ttk.Frame(tab) plot_frame.grid(row=0, column=0, sticky="nsew") canvas = FigureCanvasTkAgg(fig, master=plot_frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) # справа — вторая гифка gif_frame = ttk.Frame(tab, padding=(10, 10)) gif_frame.grid(row=0, column=1, sticky="ns") side_label = tk.Label(gif_frame) side_label.pack() start_side_gif(side_label)
def show_plots_window():
"""Окно поверх с вкладками и второй гифкой справа от графиков."""
global plots_created
if plots_created:
return
plots_created = True
texttop = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) add_plot_tab_with_side_gif(notebook, fig1, "3D PCA + толщина") add_plot_tab_with_side_gif(notebook, fig2, "3D AE + толщина") add_plot_tab_with_side_gif(notebook, fig3, "Карта толщины (PCA)") add_plot_tab_with_side_gif(notebook, fig4, "Карта толщины (AE)")
def on_show_gif():
"""Первая кнопка: большая гифка + кнопка Картмана."""
btn_show.config(state='disabled')
gif_label_big.pack(pady=10)
start_intro_gif(gif_label_big)
textbtn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=420, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) убери всё не нужное , так чтобы результат остался неизменным
Вот тот же скрипт, но без всякого лишнего мусора и с тем же поведением (2 разные гифки, кнопки, графики и карты остаются как были):
pythonimport numpy as np import pandas as pd import matplotlib.pyplot as plt import segyio from sklearn.decomposition import PCA from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsRegressor from sklearn.metrics import mean_squared_error from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import EarlyStopping import tkinter as tk from tkinter import ttk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from PIL import Image, ImageTk, ImageSequence # --- пути к данным и гифкам --- seg_data_path = 'Cube.sgy' hzn_b_path = 'B' thk_data_path = 'dh_dataset.txt' intro_gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif" side_gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\laughing-eric-cartman.gif" # --- таблицы толщин и горизонта --- thk_df = pd.read_csv( thk_data_path, sep=r'\s+', header=None, names=['inline', 'crossline', 'thickness'] ) hzn_df = pd.read_csv( hzn_b_path, sep=r'\s+', header=None, names=['x', 'y', 'inline', 'crossline', 'time_ms', 'unknown'] ) hzn_time_map = { (int(row['inline']), int(row['crossline'])): row['time_ms'] for _, row in hzn_df.iterrows() } # --- извлечение окон трасс вокруг горизонта B --- seismic_waves = [] coordinates = [] with segyio.open(seg_data_path, "r", ignore_geometry=True) as cube: inlines = cube.attributes(segyio.TraceField.INLINE_3D)[:] xlines = cube.attributes(segyio.TraceField.CROSSLINE_3D)[:] dt_ms = segyio.tools.dt(cube) / 1000 coord_to_idx = { (int(il), int(xl)): i for i, (il, xl) in enumerate(zip(inlines, xlines)) } for (il, xl), idx in coord_to_idx.items(): t_ref = hzn_time_map.get((il, xl)) if t_ref is None: continue trace = cube.trace[idx] t_start = t_ref - 60 t_end = t_ref i_start = int(round(t_start / dt_ms)) i_end = int(round(t_end / dt_ms)) if i_start < 0 or i_end > len(trace) or i_start >= i_end: continue segment = trace[i_start:i_end] rms = np.sqrt(np.mean(segment**2)) if rms == 0: continue seismic_waves.append(segment / rms) coordinates.append((il, xl)) seismic_waves = np.array(seismic_waves) coordinates = np.array(coordinates) # --- PCA признаки --- pca = PCA(n_components=3) pca_features = pca.fit_transform(seismic_waves) pca_results = pd.DataFrame(pca_features, columns=['PC1', 'PC2', 'PC3']) pca_results['inline'] = coordinates[:, 0] pca_results['crossline'] = coordinates[:, 1] # --- автокодировщик и AE признаки --- input_dim = seismic_waves.shape[1] latent_dim = 3 inp = Input(shape=(input_dim,)) x = Dense(16, activation='relu')(inp) x = Dense(latent_dim, activation='relu', name='latent')(x) y = Dense(16, activation='relu')(x) out = Dense(input_dim, activation='linear')(y) autoencoder = Model(inp, out) encoder = Model(inp, autoencoder.get_layer('latent').output) autoencoder.compile(optimizer='adam', loss='mse') X_train_ae, X_val_ae = train_test_split(seismic_waves, test_size=0.2, random_state=42) autoencoder.fit( X_train_ae, X_train_ae, epochs=5, batch_size=32, shuffle=True, validation_data=(X_val_ae, X_val_ae), callbacks=[EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)], verbose=1 ) ae_features = encoder.predict(seismic_waves) ae_results = pd.DataFrame(ae_features, columns=['AE1', 'AE2', 'AE3']) ae_results['inline'] = coordinates[:, 0] ae_results['crossline'] = coordinates[:, 1] # --- подготовка данных для регрессии --- pca_regression_data = pd.merge(thk_df, pca_results, on=['inline', 'crossline'], how='inner') ae_regression_data = pd.merge(thk_df, ae_results, on=['inline', 'crossline'], how='inner') # --- KNN по PCA --- X_train_pca, X_test_pca, y_train_pca, y_test_pca = train_test_split( pca_regression_data[['PC1', 'PC2', 'PC3']].values, pca_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_pca = KNeighborsRegressor(n_neighbors=5) knn_pca.fit(X_train_pca, y_train_pca) pca_predictions = knn_pca.predict(X_test_pca) mse_pca_model = mean_squared_error(y_test_pca, pca_predictions) # если надо вывести/использовать # --- KNN по AE --- X_train_ae_reg, X_test_ae_reg, y_train_ae, y_test_ae = train_test_split( ae_regression_data[['AE1', 'AE2', 'AE3']].values, ae_regression_data['thickness'].values, test_size=0.2, random_state=42 ) knn_ae = KNeighborsRegressor(n_neighbors=5) knn_ae.fit(X_train_ae_reg, y_train_ae) ae_predictions = knn_ae.predict(X_test_ae_reg) mse_ae_model = mean_squared_error(y_test_ae, ae_predictions) # --- прогноз по всей площади --- pca_results['predicted_thickness'] = knn_pca.predict(pca_results[['PC1', 'PC2', 'PC3']].values) ae_results['predicted_thickness'] = knn_ae.predict(ae_results[['AE1', 'AE2', 'AE3']].values) # --- фигуры matplotlib --- fig1 = plt.figure(figsize=(10, 8)) ax1 = fig1.add_subplot(111, projection='3d') s1 = ax1.scatter( pca_regression_data['PC1'], pca_regression_data['PC2'], pca_regression_data['PC3'], c=pca_regression_data['thickness'], cmap='turbo', s=20 ) ax1.set_title('Признаки, полученные методом главных компонент') ax1.set_xlabel('ГК1') ax1.set_ylabel('ГК2') ax1.set_zlabel('ГК3') fig1.colorbar(s1, ax=ax1, pad=0.1, label='Толщина (м)') fig2 = plt.figure(figsize=(10, 8)) ax2 = fig2.add_subplot(111, projection='3d') s2 = ax2.scatter( ae_regression_data['AE1'], ae_regression_data['AE2'], ae_regression_data['AE3'], c=ae_regression_data['thickness'], cmap='turbo', s=20 ) ax2.set_title('Скрытые признаки автокодировщика') ax2.set_xlabel('АЭ1') ax2.set_ylabel('АЭ2') ax2.set_zlabel('АЭ3') fig2.colorbar(s2, ax=ax2, pad=0.1, label='Толщина (м)') fig3 = plt.figure(figsize=(12, 6)) s3 = plt.scatter( pca_results['crossline'], pca_results['inline'], c=pca_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(s3, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (PCA-признаки)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') fig4 = plt.figure(figsize=(12, 6)) s4 = plt.scatter( ae_results['crossline'], ae_results['inline'], c=ae_results['predicted_thickness'], cmap='turbo', s=1 ) plt.colorbar(s4, label='Прогнозируемая толщина (м)') plt.title('Карта прогнозируемой толщины (признаки автокодировщика)') plt.ylabel('Вдоль профиля (inline)') plt.xlabel('Поперёк профиля (crossline)') # --- GIF утилиты --- intro_gif_frames, side_gif_frames = [], [] intro_gif_delay_ms, side_gif_delay_ms = 60, 60 def load_gif_frames(path, target_width, frames_list, delay_ms_default): if frames_list: return frames_list, delay_ms_default try: im = Image.open(path) except Exception as e: print(f"Не удалось открыть GIF-файл {path}: {e}") return [], delay_ms_default delay = int(im.info.get("duration", delay_ms_default)) frames = [] for fr in ImageSequence.Iterator(im): fr = fr.convert("RGBA") w, h = fr.size scale = target_width / float(w) fr = fr.resize((int(w * scale), int(h * scale)), Image.LANCZOS) frames.append(ImageTk.PhotoImage(fr)) return frames, delay def start_gif(label, which="intro"): global intro_gif_frames, intro_gif_delay_ms, side_gif_frames, side_gif_delay_ms if which == "intro": intro_gif_frames, intro_gif_delay_ms = load_gif_frames( intro_gif_path, 520, intro_gif_frames, intro_gif_delay_ms ) frames = intro_gif_frames delay = intro_gif_delay_ms else: side_gif_frames, side_gif_delay_ms = load_gif_frames( side_gif_path, 260, side_gif_frames, side_gif_delay_ms ) frames = side_gif_frames delay = side_gif_delay_ms if not frames: label.config(text="Не удалось загрузить GIF :(") return def tick(i=0): frame = frames[i] label.config(image=frame, text="") label.image = frame label.after(delay, tick, (i + 1) % len(frames)) tick(0) # --- Tkinter UI --- root = tk.Tk() root.title("Результаты прогнозирования толщины") main_frame = ttk.Frame(root) main_frame.pack(fill='both', expand=True, padx=10, pady=10) gif_label_big = tk.Label(main_frame) plots_created = False def add_plot_tab_with_side_gif(notebook, fig, title): tab = ttk.Frame(notebook) notebook.add(tab, text=title) tab.grid_rowconfigure(0, weight=1) tab.grid_columnconfigure(0, weight=1) tab.grid_columnconfigure(1, weight=0) plot_frame = ttk.Frame(tab) plot_frame.grid(row=0, column=0, sticky="nsew") canvas = FigureCanvasTkAgg(fig, master=plot_frame) canvas.draw() canvas.get_tk_widget().pack(fill='both', expand=True) gif_frame = ttk.Frame(tab, padding=10) gif_frame.grid(row=0, column=1, sticky="ns") side_label = tk.Label(gif_frame) side_label.pack() start_gif(side_label, which="side") def show_plots_window(): global plots_created if plots_created: return plots_created = True top = tk.Toplevel(root) top.title("Графики и карты толщины") notebook = ttk.Notebook(top) notebook.pack(fill='both', expand=True) add_plot_tab_with_side_gif(notebook, fig1, "3D PCA + толщина") add_plot_tab_with_side_gif(notebook, fig2, "3D AE + толщина") add_plot_tab_with_side_gif(notebook, fig3, "Карта толщины (PCA)") add_plot_tab_with_side_gif(notebook, fig4, "Карта толщины (AE)") def on_show_gif(): btn_show.config(state='disabled') gif_label_big.pack(pady=10) start_gif(gif_label_big, which="intro") btn_cartman = tk.Button( main_frame, text="картман съел фотки и ему плохо, простите фото не будет", command=show_plots_window, wraplength=420, justify="center", font=("Arial", 12), relief="raised" ) btn_cartman.pack(pady=15) btn_show = tk.Button( main_frame, text="показать картинки", command=on_show_gif, font=("Arial", 18, "bold"), relief="flat", borderwidth=0, highlightthickness=0, cursor="hand2" ) btn_show.pack(pady=30) root.mainloop()
Я выкинул только действительно лишнее (дубли, лишние комментарии, отдельные функции для каждой гифки), но логика и визуальный результат остаются теми же: