import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics.pairwise import cosine_similarity


# 读取npy文件，并提取出相同标签对应的索引
def process_labels(file_path):
    # 读取npy文件
    labels = np.load(file_path)

    # 统计0, 1, 2对应的索引
    indices = {
        0: np.where(labels == 0)[0].tolist(),
        1: np.where(labels == 1)[0].tolist(),
        2: np.where(labels == 2)[0].tolist()
    }

    return indices


# 根据相同标签的索引，取出对应的特征向量npy文件
def process_features(file_path, indices, label, fe_num):
    index = indices[label]
    fea_list = []
    # 遍历索引,取出对应的特征向量
    for i in index:
        fea = np.load(f'{file_path}/{i}_fe{fe_num}.npy')
        fea_list.append(fea.squeeze(-2))
    
    return np.array(fea_list)


def pca_similarity(sequence_vectors, n_components=None):
    num, seq, dim = sequence_vectors.shape

    # 1. 重塑序列向量为2D数组
    vectors = sequence_vectors.reshape(num, seq * dim)

    # 2. 标准化特征
    scaler = StandardScaler()
    scaled_vectors = scaler.fit_transform(vectors)

    # 3. PCA降维
    if n_components is None:
        n_components = min(num, seq * dim)

    pca = PCA(n_components=n_components)
    reduced_vectors = pca.fit_transform(scaled_vectors)

    # 4. 计算降维后向量的余弦相似度
    similarity_matrix = cosine_similarity(reduced_vectors)

    # 5. 计算平均相似度（排除自身与自身的相似度）
    total_similarity = (np.sum(similarity_matrix) - num) / (num * (num - 1))

    return total_similarity, pca.explained_variance_ratio_

def plot_radar_chart(similarities, ax, title):
    categories = list(similarities.keys())
    values = list(similarities.values())

    # 雷达图设置
    N = len(categories)
    angles = np.linspace(0, 2 * np.pi, N, endpoint=False).tolist()
    values += values[:1]
    angles += angles[:1]

    ax.set_theta_offset(np.pi / 2)
    ax.set_theta_direction(-1)
    ax.set_rgrids([0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], 
                 labels=['0','0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1.0'])
    ax.set_rlabel_position(0)
    ax.plot(angles, values, linewidth=2, linestyle='solid')
    ax.fill(angles, values, alpha=0.25)

    ax.set_xticks(angles[:-1])
    ax.set_xticklabels(categories)
    ax.set_title(title)

    # 固定径向轴的范围
    ax.set_ylim(-0.1, 1)


if __name__ == "__main__":
    indices = process_labels(r'features_save_4\results.npy')
    fig, axes = plt.subplots(1, 3, subplot_kw=dict(polar=True), figsize=(24, 8))
    # index = indices[2]
    # label = 2
    # fea_1 = process_features('features_save_4', indices, label, 1)
    # total_similarity_1, _ = pca_similarity(fea_1)
    # fea_2 = process_features('features_save_4', indices, label, 2)
    # total_similarity_2, _ = pca_similarity(fea_2)
    # fea_3 = process_features('features_save_4', indices, label, 3)
    # total_similarity_3, _ = pca_similarity(fea_3)
    # fea_4 = process_features('features_save_4', indices, label, 4)
    # total_similarity_4, _ = pca_similarity(fea_4)
    # similarities = {
    #         'chest.Resp': total_similarity_1,
    #         'wrist.BVP': total_similarity_2,
    #         'chest.ECG': total_similarity_3,
    #         'wrist.EDA': total_similarity_4
    #         }
    # similarities = {k: v / np.sum(list(similarities.values())) for k, v in similarities.items()}
    # plot_radar_chart(similarities, axes[1], title=f'Label {label}')

    for i in range(3):
        index = indices[i]
        # 为空则跳过
        if len(index) == 0:
            label = i
            total_similarity_1 = 0
            total_similarity_2 = 0
            total_similarity_3 = 0
            total_similarity_4 = 0
            similarities = {
            'chest.Resp': total_similarity_1,
            'wrist.BVP': total_similarity_2,
            'chest.ECG': total_similarity_3,
            'wrist.EDA': total_similarity_4
            }
            plot_radar_chart(similarities, axes[i], title=f'Label {label}')
        else:    
            label = i
            fea_1 = process_features('features_save_4', indices, label, 1)
            total_similarity_1, _ = pca_similarity(fea_1)
            fea_2 = process_features('features_save_4', indices, label, 2)
            total_similarity_2, _ = pca_similarity(fea_2)
            fea_3 = process_features('features_save_4', indices, label, 3)
            total_similarity_3, _ = pca_similarity(fea_3)
            fea_4 = process_features('features_save_4', indices, label, 4)
            total_similarity_4, _ = pca_similarity(fea_4)
            similarities = {
            'chest.Resp': total_similarity_1,
            'wrist.BVP': total_similarity_2,
            'chest.ECG': total_similarity_3,
            'wrist.EDA': total_similarity_4
            }
            # 将similarities的各个值进行归一化
            similarities = {k: v / np.sum(list(similarities.values())) for k, v in similarities.items()}
        plot_radar_chart(similarities, axes[i], title=f'Label {label}')


    # 调整整体布局
    plt.tight_layout()  # 增加边距
    plt.savefig('radar_chart_4.png')  # 保存时确保边缘完整
怎么调整轴标签和雷达图的距离