Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

1 / main

.py
Скачиваний:
0
Добавлен:
27.12.2025
Размер:
4.77 Кб
Скачать
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

def calculate_partitioned_entropy(time_col, signal_col, k=6, Nt=4):
    Y = signal_col.reshape(-1, 1)
    N = len(Y)
    h_step = np.mean(np.diff(time_col))
    tau_end = time_col[-1] * 0.2 

    # 1. Кластеризация фазового пространства
    kmeans = KMeans(n_clusters=k, n_init=10, random_state=42)
    idx = kmeans.fit_predict(Y)

    # Вероятности нахождения в кластерах (вес кластера)
    _, counts = np.unique(idx, return_counts=True)
    rho = counts / N

    # Инициализация массивов для расчета
    tauspan = np.arange(h_step, tau_end, h_step)
    NL = N - int(np.ceil(tau_end / h_step))
    tL = np.zeros(NL) # Время первого выхода из кластера
    hp = np.zeros(len(tauspan))

    for j, tau in enumerate(tauspan):
        ns = int(np.round(tau / h_step))
        if ns == 0: continue
        if N - ns <= 0: break

        idxold = idx[:N-ns]
        idxnew = idx[ns:]
        limit_len = min(len(idxold), NL)

        # Определение времени покидания исходного кластера (tL)
        cngs = (idxold[:limit_len] != idxnew[:limit_len])
        idleave = (tL[:limit_len] == 0) & cngs
        tL[:limit_len][idleave] = tau

        # Вычисление условной энтропии
        S = 0
        for i in range(k):
            mask_i = (idxold == i)
            if not np.any(mask_i): continue

            transitions = idxnew[mask_i]
            _, target_counts = np.unique(transitions, return_counts=True)
            p_cond = target_counts / np.sum(target_counts)
            
            # Взвешенная сумма по формуле Шеннона: -rho_i * sum(p * ln p)
            rho_i = rho[i] if i < len(rho) else 0
            hi = -rho_i * np.sum(p_cond * np.log(p_cond))
            S += hi
        
        hp[j] = S

    # Аппроксимация наклона
    # tau0 - время, за которое все точки успевают покинуть начальные кластеры
    tau0 = np.max(tL) if np.max(tL) > 0 else h_step
    
    # Выбор линейного участка [tau0, Nt * tau0] для оценки производной
    indices_fit = np.where((tauspan >= tau0) & (tauspan <= Nt * tau0))[0]
    
    # Fallback для слишком коротких диапазонов
    if len(indices_fit) < 2:
        indices_fit = np.where(tauspan >= tau0)[0]
        if len(indices_fit) < 2:
            indices_fit = range(len(tauspan)//2, len(tauspan))

    ts_fit = tauspan[indices_fit]
    hp_fit = hp[indices_fit]
    
    slope, intercept = np.polyfit(ts_fit, hp_fit, 1)

    return tauspan, hp, ts_fit, slope, intercept, slope

def process_files(files):
    for filename in files:
        if not os.path.exists(filename):
            print(f"Файл {filename} не найден.")
            continue
            
        print(f"Обработка файла: {filename}...")
        
        try:
            # Чтение и очистка данных
            df = pd.read_excel(filename, header=None, usecols=[0, 2])
            df.columns = ['Time', 'Signal']
            df = df.dropna()
            
            time_data = df['Time'].values
            signal_data = df['Signal'].values
        except Exception as e:
            print(f"Ошибка при чтении: {e}")
            continue

        # Расчет энтропии
        taus, hp, t_fit, slope, intercept, val_hks = calculate_partitioned_entropy(
            time_data, signal_data, k=8, Nt=5
        )
        
        # Визуализация результатов
        plt.figure(figsize=(10, 6))
        plt.plot(taus, hp, label=r'$h_p(\tau)$', color='blue', linewidth=2)
        plt.plot(t_fit, slope * t_fit + intercept, 'r--', linewidth=2, label='Аппроксимация')
        plt.title(f'Файл: {filename}. Оценка $h_{{KS}} \\approx {val_hks:.4f}$', fontsize=14)
        plt.xlabel(r'$\tau$ (сек)', fontsize=12)
        plt.ylabel(r'$h_p(\tau)$', fontsize=12)
        plt.legend()
        plt.grid(True)
        
        output_name = f'F{filename.replace(".xlsx", "")}.png'
        plt.savefig(output_name)
        plt.close()
        print(f"Результат сохранен: {output_name}, h_KS = {val_hks:.4f}")

if __name__ == "__main__":
    files_to_process = ['1.xlsx', '2.xlsx', '3.xlsx']
    process_files(files_to_process)
Соседние файлы в папке 1