import pickle

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

# 1. 读取并处理数据
bom_nodes = pd.read_csv('input_data/input_product_data/BomNodes.csv')
bom_nodes['Code'] = bom_nodes['Code'].astype(str)
bom_nodes.set_index('Index', inplace=True)

bom_cate_net = pd.read_csv('input_data/input_product_data/合成结点.csv')

# 2. 构建图结构
g_bom = nx.from_pandas_edgelist(bom_cate_net, source='UPID', target='ID', create_using=nx.MultiDiGraph())

# 填充每一个结点的具体内容
bom_labels_dict = {}
for index in g_bom.nodes:
    try:
        bom_labels_dict[index] = bom_nodes.loc[index].to_dict()
    except KeyError:
        print(f"节点 {index} 不存在于 bom_nodes 中")

# 分配属性给每一个结点
nx.set_node_attributes(g_bom, bom_labels_dict)

# 3. 计算每个节点的度数
degrees = dict(g_bom.degree())  # 总度数（适用于有向图）

# 4. 统计每个度数的节点数量
degree_counts = {}
for degree in degrees.values():
    if degree in degree_counts:
        degree_counts[degree] += 1
    else:
        degree_counts[degree] = 1

# 转换为排序后的列表（横坐标：度数，纵坐标：节点数）
sorted_degrees = sorted(degree_counts.keys())
sorted_counts = [degree_counts[d] for d in sorted_degrees]

# 5. 绘制度分布图
plt.figure(figsize=(12, 8))  # 增大画布尺寸
bars = plt.bar(sorted_degrees, sorted_counts, width=0.8)
plt.title('Degree Distribution In Industrial Chain', fontsize=16)
plt.xlabel('Degree', fontsize=14)
plt.ylabel('Number of Nodes', fontsize=14)
plt.grid(True, linestyle='--', alpha=0.5)
plt.xticks(rotation=45)  # 如果度数较多，可以旋转x轴标签
plt.tight_layout()  # 防止标签重叠

# 6. 在每个柱子上方标注数值
for bar in bars:
    height = bar.get_height()
    plt.text(
        bar.get_x() + bar.get_width() / 2,  # x坐标：柱子中心
        height + max(sorted_counts) * 0.02,  # y坐标：柱子顶部上方（留出空间）
        f'{int(height)}',  # 显示数值（转换为整数）
        ha='center',  # 水平居中
        va='bottom',  # 垂直底部对齐
        fontsize=10,  # 字体大小
        color='black'  # 字体颜色
    )

# 7. 保存超高清图片（300 DPI）
output_path = "degree_distribution_with_labels.png"  # 输出文件名
plt.savefig(output_path, dpi=500, bbox_inches='tight')  # dpi=300 确保高分辨率
print(f"图片已保存至: {output_path}")

# 1. 加载企业网络数据
with open("firm_network.pkl", 'rb') as f:
    G_firm = pickle.load(f)
print(f"Successfully loaded cached data from firm_network.pkl")

# 2. 计算企业网络的度分布
degrees_firm = dict(G_firm.degree())  # 总度数
degree_counts_firm = {}
for degree in degrees_firm.values():
    if degree in degree_counts_firm:
        degree_counts_firm[degree] += 1
    else:
        degree_counts_firm[degree] = 1

# 转换为排序后的列表
sorted_degrees_firm = sorted(degree_counts_firm.keys())
sorted_counts_firm = [degree_counts_firm[d] for d in sorted_degrees_firm]

# 3. 绘制企业网络的度分布图
plt.figure(figsize=(12, 6))  # 单独画布尺寸
plt.bar(sorted_degrees_firm, sorted_counts_firm, width=0.8)
plt.title('Degree Distribution of Firm Network', fontsize=16)
plt.xlabel('Degree (Number of Connections)', fontsize=14)
plt.ylabel('Number of Firms', fontsize=14)
plt.grid(True, linestyle='--', alpha=0.5)
plt.xticks(rotation=45)
plt.tight_layout()

# 在柱子上方标注数值
for bar in plt.gca().containers[0]:  # 获取当前图中的柱子对象
    height = bar.get_height()
    plt.text(
        bar.get_x() + bar.get_width() / 2,
        height + max(sorted_counts_firm) * 0.02,
        f'{int(height)}',
        ha='center',
        va='bottom',
        fontsize=10,
        color='black'
    )

# 保存图片
plt.savefig("degree_distribution_firm.png", dpi=500, bbox_inches='tight')
print("企业度分布图已保存至: degree_distribution_firm.png")

