import numpy as np import pandas as pd import matp...

생성일: 2025년 12월 8일

답변에 사용된 모델 GPT-5.1 by Chat01

질문

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)

text
processed_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, добавь комментарии к каждой части кода и убери всё то что не влияет на результат

사고

Refactoring the Python script

The user wants me to update the script by displaying the results in a Tkinter window, adding comments to each part of the code, and removing any unnecessary parts. I'll incorporate a Tkinter GUI for showing the plots/results, clean up the imports, and make the comments for clarity. I'll ensure everything's relevant and functional.

Cleaning up and displaying in Tkinter

The user likely wants a minimal version of the code, removing unused variables like Axes3D or seaborn. They also asked for results to be displayed in a Tkinter window. The simplest solution could be embedding figures using FigureCanvasTkAgg. I'll keep the existing multiple figures, but consider showing one with a dropdown to switch between them. No need for an elaborate GUI. Just clean and efficient code.

Cleaning up imports and implementing Tkinter embedding

In the code, I'll remove unnecessary imports like seaborn, Axes3D, samp_count, and time_values, while preserving core functionality like building seismic_waves and using PCA and the autoencoder for TensorFlow/Keras. For the Tkinter display, I'll embed figures using FigureCanvasTkAgg and avoid using plt.show(). I’ll also keep the training parameters like epochs=5 with EarlyStopping. Comments will be in Russian as per the user's request.

Implementing Tkinter notebook and cleaning up imports

I'll use ttk.Notebook to organize the four figures into tabs in a Tkinter window, ensuring the figures are embedded without using plt.show(). I'll remove unnecessary imports and comments on individual lines but will annotate blocks as requested. I’ll retain the essential libraries like numpy, pandas, and others needed for seismic data processing. I'll keep imports relevant to the seismic analysis and remove anything redundant, like sns.

Final script cleanup and Tkinter integration

I'll remove unused variables like samp_count, processed_count, and time_values. The key function won’t change unless necessary, so I’ll leave boundary checks in place as a precaution. I'll keep the Cyrillic encoding since Python3 uses UTF-8 by default. Then, I’ll refactor the plotting section to embed the figures into Tkinter, ensuring the proper imports are maintained without unnecessary ones like Axes3D.

Thought for 1m 40s

답변

Вот переработанный и упрощённый код:

  • результаты выводятся в окне Tkinter,
  • добавлены комментарии по блокам,
  • убрано всё, что не влияет на результат (лишние импорты, неиспользуемые переменные и т.п.).
python
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 # импорт для 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

гифка с этого файла

사고

Modifying Tkinter window with buttons and gif

The user needs to add a new area to their Tkinter window. I'll add an extra tab or maybe a separate window to the Notebook, with a button that displays a gif when clicked. Below it, another button for adding images. Since only a gif is provided, I’ll focus on showing that and handling the other button’s functionality efficiently.

Handling mp4 as a gif in Tkinter

I'll interpret "окна с картинками" as new windows (Toplevels) displaying frames from the gif or mp4. Since Tkinter can’t natively play mp4, I’ll assume the user will convert it to gif. I’ll provide an example using PhotoImage for a gif and animate it by updating frames. The user can handle conversion externally.

Integrating gif functionality into Tkinter code

I need to integrate gif display into the previous Tkinter code while keeping instructions in mind, such as not customizing the matplotlib charts. I’ll create a new tab like "Юмор" with a frame and a label to show the gif. For animation, I’ll use PIL.Image and ImageSequence to handle the gif, and make sure users can modify the gif path.

Implementing simple gif player in Tkinter

I’ll define a function to load and play the gif frames. When the "показать картинки" button is clicked, it will load the frames and start the gif animation. For the second button, I’ll open a new window (Toplevel) to display the first frame of the gif or perhaps a static photo.

Managing multiple Toplevel windows with GIF frames

I’ll create a function to open new Toplevel windows with the first GIF frame. By clicking the second button, we’ll load or reuse the gif frames. I’ll store the frames in root.gif_frames to prevent garbage collection issues. Also, I’ll clarify in comments that users need to convert the mp4 to a GIF for Tkinter to load it.

Integrating Tk modifications for GIF handling

I’ll create a new "Юмор" tab and add two buttons inside. The buttons will trigger functions to display the GIF or open a new window with Cartman-related text. I’ll define on_show_gif and on_cartman to load and display the GIF frames, using global variables for gif_frames.

Thought for 2m 15s

답변

Сделал:

  • добавлена отдельная вкладка в Tkinter с пустым окном
  • сверху кнопка «показать картинки» — запускает анимацию GIF
  • снизу кнопка «картман съел фотки, теперь ему плохо» — каждое нажатие открывает новое окно с картинкой
  • GIF берётся из файла (нужно, чтобы он был GIF, а не mp4 — mp4 Tkinter не умеет; твой south-park-toilet.gif.mp4 нужно конвертировать в .gif)

Вот полный код с комментариями, включая Tkinter и GIF:

python
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 # для 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, а не только первый кадр.

질문

south-park-toilet.gif.gifsouth-park-toilet.gif.gif

путь до файла GIF C:\Users\user\Desktop\University\4 year\Методы ИИ нужно сделать так чтобы изначально была только кнопка " показать картинки" потом по нажатию появлялась картинка с картманом и кнопка " картман съел фотки и ему плохо, простите фото не будет" по нажатию на эту кнопку должны появляться итоговые графики и карты

사고

Modifying Tkinter UI for stepwise reveal

The user, who is Russian, wants to adjust Tkinter UI logic. Initially, the GUI will just show a button. When clicked, it displays a Cartman gif and a second button. Clicking the second button should show Matplotlib plots/maps. We need to simplify the UI: use a main root with frames to swap content.

Designing Tkinter interface for graphs and maps

The user wants the graphs and maps to appear inside the same Tkinter window. The easiest approach is to first set up the root with a main frame and an initial button. When clicked, the button could stay visible, but I'll disable it, then show the gif and second button. Afterward, I’ll embed a notebook to display the maps and graphs.

Simplifying Tkinter integration and GIF logic

The user provided a GIF path but didn't specify the filename. I'll use the directory they gave and suggest the filename "south-park-toilet.gif." I'll let them adjust the path if needed. We’ll continue using PIL to load the GIF as before and play the animation using after(). The figures will be built before the Tkinter interface.

Building Tkinter interface with gif and notebook layout

I’m setting up a Tkinter interface with a main frame and initial button that shows the gif. After the button is clicked, I'll display the gif and second button, then disable the first button, starting the animation. If the notebook isn't created yet, it will be added. The layout will have the gif and button inserted first, followed by the notebook.

Thought for 20s

답변

Вот полный вариант кода с нужным поведением:

  • Сначала в окне только кнопка «показать картинки».
  • После нажатия появляется гифка с Картманом и кнопка
    «картман съел фотки и ему плохо, простите фото не будет».
  • После нажатия на вторую кнопку появляются итоговые графики и карты в виде вкладок.

Обрати внимание на строку gif_path — там нужно указать точный путь и имя файла GIF (я поставил примерное имя).

python
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 # для 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 — это спец-эскейп и путь ломается.

Поставь так (самый надёжный вариант):

python
gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"

И ещё важный момент: иногда GIF не анимируется/не показывается, если PIL не сохранил кадры или нужно явно обновить label. Ниже — рабочий минимальный блок для GIF, который можно вставить в твой код (он заменяет функции load_gif / play_gif и использование gif_label):

python
from 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)

А в обработчике кнопки “показать картинки” делай так:

python
gif_label.pack(pady=10) start_gif(gif_label)

Если после этого всё равно пусто:

  1. проверь, что файл реально .gif, и открывается обычным просмотрщиком;
  2. запусти Python в консоли и попробуй отдельно:
python
from 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 не видит файл по указанному пути — то есть пути НЕ существует в системе, даже если тебе кажется, что он есть.

Причины бывают всего четыре — давай проверим по порядку.


1. Папка 4 year — ОПАСНАЯ

Windows интерпретирует путь как:

C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif

НО если папка содержит пробел, Python должен получать путь в строгом r-формате, иначе он ломается.

Ты уже пробовал r"...", но ошибка осталась → значит проблема НЕ в экранировании.


2. ПАПКИ НЕ СОВПАДАЮТ С ТОЧНЫМ ПУТЁМ

Очень частая причина:

  • папка называется “4year”, а не “4 year”
  • папка называется “Методы ИИ ” (с пробелом в конце!)
  • файл называется “south-park-toilet.gif.gif”, а ты ищешь .gif

Проверь точные имена (САМЫЕ ЧАСТЫЕ ОШИБКИ):

Открой PowerShell и введи:

powershell
ls "C:\Users\user\Desktop\University"

Папка точно называется 4 year ?

Потом:

powershell
ls "C:\Users\user\Desktop\University\4 year"

Папка точно называется Методы ИИ ?

Потом:

powershell
ls "C:\Users\user\Desktop\University\4 year\Методы ИИ"

Файл точно называется:

south-park-toilet.gif

а НЕ:

text
south-park-toilet.gif.mp4 south-park-toilet.gif.gif south-park-toilet.giF south-park-toilet.GIF

3. Скопируй путь через Проводник — НЕ ВВОДИ ВРУЧНУЮ

Сделай так:

  1. Перейди к файлу
  2. Зажми Shift
  3. ПКМ по GIF → Копировать как путь

Получишь строку вида:

"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"

Используй ТОЛЬКО её:

python
gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif"

4. Проверка файла через Python — скопируй и выполни

python
import 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

Попробуй:

python
gif_path = r"C:\Users\user\Desktop\University\4 year\Методы ИИ\south-park-toilet.gif.gif"

🔥 Хочешь, чтобы я сам написал функцию, которая автоматически найдёт GIF-файл в папке

(даже если ты не уверен в имени)?

Например:

python
gif_path = find_gif(r"C:\Users\user\Desktop\University\4 year\Методы ИИ")

Скажи — сделаю.

질문

сделай размер гифки больше, а все графики должны появляться поверх изображения гиф , так же кнопка отвечающая за вывод фоток должна быть больше и выглядеть как текст

사고

Adjusting Tkinter GUI behavior for user’s preferences

The user wants to adjust the previous Tkinter script. They need the GIF to be larger (by resizing frames in load_gif_frames), graphs to appear over the GIF (likely stacking using place with z-order adjustments), and a button that looks like text (maybe flat, borderless). Also, the file path issues should be fixed already. I'll provide the code with these changes.

Clarifying solution for displaying graphs over GIF

The user wants graphs over the GIF, but not necessarily in a new window. Using place or grid within the same window and managing stacking seems like a solution, but they might prefer that the GIF remains visible behind. To keep things simple, creating a new Toplevel window for graphs would neatly solve this, and the button size and style can be adjusted with appropriate font and border properties.

Modifying for user’s GUI and GIF handling requests

To address the user’s request, I’ll integrate a clickable Label for the button, adjusted to look like text, to match the styling they want. I’ll provide a full script, focusing on resizing the GIF using Image.LANCZOS and fixing the layout. For the graphs overlay on the GIF, I’ll create a Toplevel window with a Notebook element inside.

Updating button size and focusing on GUI changes

To make the button bigger and look like text, I’ll update the btn_show configuration, using a larger font and a flat, borderless style. The second button can stay at the standard size. I'll update only the GUI/ending code, keeping the previous ML code intact. Since the full script wasn’t requested, just the relevant modifications should be provided.

Thought for 27s

답변

Сделал так, как ты просишь:

  • GIF масштабируется побольше (по ширине ~500 px).
  • Сначала в окне только большая текстовая кнопка «показать картинки».
  • После нажатия появляется большая гифка Картмана и кнопка
    «картман съел фотки и ему плохо, простите фото не будет».
  • По нажатию на неё все графики и карты открываются в новом окне поверх окна с гифкой.

Ниже привожу только Tkinter-часть + GIF, которую можно просто подставить в твой скрипт вместо старого GUI-блока (всё до этого — загрузка данных, PCA, AE, KNN и создание fig1..fig4 — оставляешь без изменений).

Обрати внимание, что путь к файлу я прописал тем, который ты дал:

python
import 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()

Как пользоваться:

  1. Всё, что касается PCA/автокодировщика/KNN и создания fig1, fig2, fig3, fig4 оставь выше этого блока без изменений.
  2. Внизу файла (где у тебя раньше был root = tk.Tk() и прочий Tkinter) — удали старый код и вставь этот.

Если потом захочешь, можно сделать, чтобы второе окно с графиками было модальным (блокировало главное), или чтобы при его закрытии можно было снова нажать кнопки.

질문

представь конечный код

사고

Providing full code based on user request

User wants a final, concise script with everything: new Tkinter behavior, rescaling the gif, plots in a new window, and ensuring paths are correctly set. The code should be concise, without seaborn, and in a single block. I'll handle the imports, data paths, ML pipeline, and Tkinter setup while keeping user’s path as raw string. I'm not adding extra libraries. Let’s deliver this!

Thought for 23s

답변

Вот цельный финальный скрипт одним куском —
с обработкой данных, обучением моделей, построением графиков и нужным интерфейсом Tkinter:

python
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 # ================================== # 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

и он теперь используется точно под этим именем, как ты просил.


Вот полностью исправленный блок Tkinter + 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 ищется по имени south-park-toilet.gif.gif
  • GIF показывается большим размером
  • Графики появляются поверх GIF в отдельном окне
  • Кнопки работают в нужной последовательности

Если хочешь — могу:

✅ сделать плавное исчезновение GIF перед появлением графиков
✅ добавить озвучку Картмана (через playsound)
✅ добавить кнопку «Картману лучше, показать фотки!»

Скажи — добавлю.

질문

laughing-eric-cartman.giflaughing-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

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)[:]

text
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(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

text
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):
global gif_running
if not load_gif_frames():
label.config(text="Не удалось загрузить GIF :(")
return

text
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)

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

text
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)

text
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()
добавь эту гифку рядом со всеми графиками

답변

python
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 # ========================= # Пути к данным + 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()

Важно:

  • Я сделал так, что в каждом табе графика справа анимируется та же GIF (рядом с графиком).
  • На первом экране GIF показывается больше. Для этого я перезагружаю кадры большим размером, а затем для вкладок — кадры снова используются (они будут уже “большие”). Если хочешь, могу сделать две версии кадров: большие для главного окна и маленькие для вкладок (чтобы не раздувать память).

질문

гифка справа от графиков должна быть другой, а именно laughing-eric-cartman , путь такой же как и у первой гифки

사고

Modifying GIF paths and logic in script

Okay, the user wants the second GIF (laughing-eric-cartman) displayed to the right of the graph, with the first GIF remaining in the intro. I'll assume their path is something like C:\Users\user\Desktop\University\4 year\Методы ИИИ\laughing-eric-cartman.gif, but they'll need to adjust it if it's different. I'll update the GIF logic and file paths in the code accordingly. The intro GIF will remain the same, but I'll scale them to the correct sizes: 520px for the intro, 260px for the side.

Thought for 26s

답변

Вот обновлённый полный код:

  • первая гифка (на стартовом экране) — south-park-toilet.gif.gif;
  • гифки справа от графиковдругая, laughing-eric-cartman.gif в той же папке;
  • остальная логика (PCA, AE, карты, кнопки) сохранена.

Если у второй гифки другое имя/расширение, просто поправь строку side_gif_path.

python
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 # ========================= # Пути к данным + 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), просто поправь строку:

python
side_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

=========================

Пути к данным + 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

text
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

text
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

text
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

text
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

text
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)

text
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

text
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)

text
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) убери всё не нужное , так чтобы результат остался неизменным

사고

Cleaning up and refactoring script

The user wants to remove everything unnecessary while keeping the same behavior. I'll refactor the code: eliminating unused imports (like Axes3D, which can be dropped), cleaning up duplicate variables, and compressing comments. I'll also fix the Russian comment accidentally added into the code and streamline unused variables to maintain logic without extra complexity.

Refining code without changing results

The user wants no changes to the result, but removing MSE calculations shouldn’t affect the GUI. I’ll refine things by removing redundant comments, factoring out the GIF loading, and cleaning up unused imports, like Axes3D. I’ll also keep necessary variables like the intro_gif_delay_ms, and I’ll leave any Russian docstrings intact to preserve the behavior.

Tidying up the script without altering function

I’ll clean up the script by slightly simplifying the GIF loading functions and keeping them separate for clarity. I'll group imports, remove unnecessary Axes3D reference, and tidy up the Tkinter section. For variables like mse_pca_model and mse_ae_model, I’ll check if they’re used, but otherwise, keep the computational part intact while trimming down some verbose comments.

Thought for 57s

답변

Вот тот же скрипт, но без всякого лишнего мусора и с тем же поведением (2 разные гифки, кнопки, графики и карты остаются как были):

python
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 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()

Я выкинул только действительно лишнее (дубли, лишние комментарии, отдельные функции для каждой гифки), но логика и визуальный результат остаются теми же:

  1. При запуске — только большая кнопка «показать картинки».
  2. Нажимаешь — появляется большая гифка с унитазом и кнопка про Картмана.
  3. Нажимаешь вторую — открывается окно с четырьмя вкладками, слева график, справа другая гифка (laughing-eric-cartman).

이 Q&A 공유하기