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()
Я выкинул только действительно лишнее (дубли, лишние комментарии, отдельные функции для каждой гифки), но логика и визуальный результат остаются теми же: