summary表生成

1.思路

1.1基于raw data数据规整数据

1.2读取excel (pandas 模块为主)

1.3三层透视数据 图表制作(网上没有案例,此案例足够典型)(plt模块为主)

1.4按指定类型分类

1.5读取HTML模版,把报告按照模版类型进行填充

 

2.关键点

1.原始数据的分类处理

2.三层透视数据的搭建,利用类似关键字(自定义列表)重新分类索引值

3.对三层透视图的渲染分解

4.对每类BIN的处理

5.效果图

 

 

 

 

 

 

 

#---- code start ----#

   1 # -*- coding: utf-8 -*-
   2 # @Time    : 2023/12/5
   3 # @Author  : alex
   4 # @Site    :
   5 # @File    :
   6 # @Software: PyCharm
   7 # This is a sample Python script.
   8 # ============================================================================================================= #
   9 import os
  10 import sys
  11 import datetime
  12 import shutil
  13 import openpyxl
  14 import pdfkit
  15 
  16 import numpy as np
  17 import pandas as pd
  18 import matplotlib
  19 import matplotlib.pyplot as plt
  20 
  21 from jinja2 import Environment, FileSystemLoader
  22 from matplotlib.font_manager import FontProperties
  23 from matplotlib import ticker
  24 
  25 '''
  26 #---------------------------------------------------------------------------------------------------------------#
  27 #  常量 全局变量
  28 #---------------------------------------------------------------------------------------------------------------#
  29 '''
  30 
  31 '''
  32 #---------------------------------------------------------------------------------------------------------------#
  33 #  read_excel
  34 #---------------------------------------------------------------------------------------------------------------#
  35 '''
  36 
  37 
  38 def read_excel(path_s1):
  39     # current_directory = os.path.dirname(os.path.abspath(__file__))
  40     # print("获取当前绝对路径:",current_directory)
  41     input_path_s1 = path_s1
  42     # input_path_s1 = r'./3_summary_ft'   # path定义要获取的文件名称的目录
  43     file_name_list = os.listdir(input_path_s1)  # os.listdir()方法获取文件夹名字,返回数组
  44     print("获取文件夹列表:\n", file_name_list)
  45 
  46     # 拼接路径 -- 仅仅获取第一个
  47     input_path_s2 = input_path_s1 + '\\' + file_name_list[0]
  48 
  49     # print("pandas 版本: ",  pd.__version__)
  50     # 读取一张Sheet  要读取的工作表可以由参数 sheet_name 指定。通过以 0 开头的数字或工作表名称指定。
  51     work_pd1 = pd.read_excel(io=input_path_s2, sheet_name=0, header=None)  #
  52     pd.set_option('display.max_columns', None)  # 显示完整的行
  53     pd.set_option('display.max_rows', None)  # 显示完整的列
  54     pd.set_option('display.expand_frame_repr', False)  # 设置不折叠数据
  55     pd.set_option('display.float_format', lambda x: '%.2f' % x)  # 设置不以科学计数法显示
  56     # 读取导入Excel所有数据,
  57     # print(work_pd1)
  58     # print(type(work_pd1))
  59 
  60     return work_pd1
  61 
  62 
  63 '''
  64 # ====================================================================================================================#
  65 # 按月分类
  66 # ====================================================================================================================#
  67 '''
  68 # 构造二维数组
  69 var_list_month_v12_n = [[], [], [], [], [], [], [], [], [], [], [], [], []]
  70 
  71 
  72 def monthly_class_handle_v12(input_month, intput_index):
  73     # print('传入参数: 月份%s 行号%s' % (input_month, intput_index))
  74     month_def = ['0', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
  75     for index_v1 in range(1, 13):  # 从1开始遍历
  76         # print('遍历每月找到对应月份:',index_v1 , input_month)
  77         if input_month == month_def[index_v1]:
  78             # print("按月分类: %s \t行号:%s" % (month_def[index_v1], intput_index) , '月份类型:',type( month_def[index_v1]))
  79             month_index = int(month_def[index_v1])
  80             # print('转换后int-月份类型: ', type(month_index), month_index)
  81             # 添加数据到二维数组中
  82             var_list_month_v12_n[month_index].append(intput_index)
  83             # print('对应当月的行数汇总:',var_list_month_v12_n[month_index])
  84 
  85             break
  86     # print('显示汇总后每月分类:',var_list_month_v12_n)
  87     return var_list_month_v12_n
  88 
  89 
  90 '''
  91 # ====================================================================================================================#
  92 # 本月测试BIN数据 get_data_bin_v1 获取有效值
  93 # ====================================================================================================================#
  94 '''
  95 
  96 
  97 def get_data_bin_v1(x_column, month_h1_v1, get_data1):
  98     # print(">>> 函数:get_data_bin_v1")
  99     x_bin = x_column
 100     single_month_handle = month_h1_v1
 101     single_data = get_data1
 102     name_clot_value = single_data.columns[x_bin]
 103     print('DataFrame 首行中获取指定名称-无表头 - 索引值:< %s >' % name_clot_value, single_data.loc[0, x_bin])
 104     # 获取值缓存到列表中
 105     list_clot_v3 = []
 106     for index_v12 in range(len(single_month_handle)):
 107         # print("遍历-每月列表-行数值:",single_month_handle[index_v12], single_data.loc[single_month_handle[index_v12]][name_clot_value])
 108         list_clot_v3.append(single_data.loc[single_month_handle[index_v12]][name_clot_value])
 109     # print('list_clot_v3 获取有效值:\n', list_clot_v3)
 110     return list_clot_v3
 111 
 112 
 113 '''
 114 # ====================================================================================================================#
 115 # 本月测试BIN数据 get_data_bin_v2获取有效值
 116 # ====================================================================================================================#
 117 '''
 118 
 119 
 120 def get_data_bin_v2(x_column, month_h1_v1, get_data1):
 121     # print(">>> 函数:get_data_bin_v1")
 122     x_bin = x_column
 123     single_month_handle = month_h1_v1
 124     single_data = get_data1
 125     name_clot_value = single_data.columns[x_bin]
 126     # print('DataFrame 首行中获取指定名称-无表头 - 索引值:< %s >' % name_clot_value,single_data.loc[0,x_bin])
 127     line_name_first = single_data.loc[0, x_bin]
 128     # 获取值缓存到列表中
 129     list_clot_v3 = []
 130     for index_v12 in range(len(single_month_handle)):
 131         # print("遍历-每月列表-行数值:",single_month_handle[index_v12], single_data.loc[single_month_handle[index_v12]][name_clot_value])
 132         list_clot_v3.append(single_data.loc[single_month_handle[index_v12]][name_clot_value])
 133     # print('list_clot_v3 获取有效值:\n', list_clot_v3)
 134     return line_name_first, list_clot_v3
 135 
 136 
 137 '''
 138 # ====================================================================================================================#
 139 # 创建路径/文件夹 -逻辑处理任意问题
 140 # ====================================================================================================================#
 141 '''
 142 
 143 
 144 def crate_monthly_path(z_data):
 145     month_real_s = str(z_data)
 146     month_name_s = "month_" + month_real_s
 147     # print(os.getcwd())  # 获取当前工作目录路径
 148     bin8_p = "\\4_result_ft\\month_report\\" + month_name_s
 149     mk_file_path_v1 = os.getcwd() + bin8_p
 150     if os.path.exists(mk_file_path_v1):
 151         shutil.rmtree(mk_file_path_v1)
 152     os.mkdir(mk_file_path_v1)
 153     print("# 创建报告生成工作目录", mk_file_path_v1)
 154 
 155     return mk_file_path_v1
 156 
 157 
 158 '''
 159 # ====================================================================================================================#
 160 # 本月数据 -生成报告汇总
 161 # ====================================================================================================================#
 162 '''
 163 
 164 
 165 def generate_report_summary(z_y1):
 166     print("#**** generate_report_summary ****#")
 167     # 创建路径 / 文件夹 - 逻辑处理任意问题
 168     month_real = str(z_y1)
 169     mk1_file_name = crate_monthly_path(month_real)
 170     # print("创建新目录:",mk1_file_name)
 171 
 172     # 拷贝文件到对应月份文件中
 173     source_folder1 = r'./4_result_ft/picture'
 174     target_folder2 = mk1_file_name + '/picture'
 175     shutil.copytree(source_folder1, target_folder2)
 176 
 177     # 伟测-vi5300-ft-wc
 178     # 月份+路径
 179     single_month_report_ft_wc(month_real, target_folder2)
 180 
 181 
 182 '''
 183 # ====================================================================================================================#
 184 # 本月数据 -获取本月的汇总数据
 185 # ====================================================================================================================#
 186 '''
 187 
 188 
 189 def get_month_total_info(y_p1, y_p2, y_p4, z_p2, z_p3, z_p4):
 190     print('>>> get_month_total_info ...')
 191     # 1按照总数汇总
 192     y_total_k1 = y_p1
 193     y_total_k2 = y_p2
 194     y_yield_k4 = y_p4
 195     month_u1 = z_p2
 196     single_month_g1 = z_p3
 197     raw_data_t1 = z_p4
 198     print('汇总处理: 月份< %d >' % month_u1, )
 199     print(single_month_g1)
 200     y_name_f1, y_data_j1 = get_data_bin_v2(y_total_k1, single_month_g1, raw_data_t1)
 201     y_name_f2, y_data_j2 = get_data_bin_v2(y_total_k2, single_month_g1, raw_data_t1)
 202     y_name_f4, y_data_j4 = get_data_bin_v2(y_yield_k4, single_month_g1, raw_data_t1)
 203     print('源4:', y_name_f1, y_data_j1)  # Input
 204     print('源5:', y_name_f2, y_data_j2)  # BIN01(Good)
 205 
 206     # ---------------------------------------------------------------------------------------------------------------- #
 207     # 1按照总数汇总
 208     r1_input = np.sum(y_data_j1)
 209     r1_bin1 = np.sum(y_data_j2)
 210     r1_yield = r1_bin1 / r1_input
 211     r1_yield_percent = "{:.2%}".format(r1_yield)
 212     r1_limit = "{:.2%}".format(y_data_j4[0])
 213     r1_state = 'pass' if r1_yield > y_data_j4[0] else 'fail'
 214     print('结果:%s 实际良率:%s  目标良率:%s 投入数量(ea): %d   实际产出(ea):%d \n' % (r1_state, r1_yield_percent, r1_limit, r1_input, r1_bin1,))
 215 
 216 
 217 '''
 218 # ====================================================================================================================#
 219 # html_vi5300_ft_wc  伟测模版
 220 # ====================================================================================================================#
 221 '''
 222 
 223 
 224 def html_vi5300_ft_wc(body, s_t1, e_t2, month_jk1):
 225     env = Environment(loader=FileSystemLoader(r'./4_result_ft/month_report/'))
 226     test_report = env.get_template('vi5300_ft_wc_report_template.html')
 227     monthly_V12_data = "./4_result_ft/month_report/month_" + month_jk1 + "/report_" + month_jk1 + "monthly_result.html"
 228     # open("result.html", 'w+') as fout:
 229     with open(monthly_V12_data, 'w+') as fout:
 230         html_content = test_report.render(start_time=s_t1, stop_time=e_t2, body=body)
 231         fout.write(html_content)
 232 
 233 
 234 '''
 235 # ====================================================================================================================#
 236 # single_month_report_ft_wc 获取html模板-ft伟测
 237 # ====================================================================================================================#
 238 '''
 239 
 240 
 241 def single_month_report_ft_wc(z_y1, z_y2):
 242     print("************ single_month_report_ft_wc **********")
 243     # 获取有效值
 244     source_folder2 = z_y2 + "/月度_汇总统计结果.xlsx"
 245     # print("h获取有效的excel",source_folder2)
 246     work_book2 = openpyxl.load_workbook(source_folder2)
 247     worksheet_b2 = work_book2.active
 248     target_rows_x2 = worksheet_b2.max_row
 249     target_cols_y2 = worksheet_b2.max_column
 250     print("行列:", target_rows_x2, target_cols_y2)
 251     s_status = worksheet_b2.cell(2, 2).value
 252     s_yield = worksheet_b2.cell(2, 3).value
 253     s_limit = worksheet_b2.cell(2, 4).value
 254     s_input = worksheet_b2.cell(2, 5).value
 255     s_output = worksheet_b2.cell(2, 6).value
 256     # print(s_status, s_yield, s_limit, s_input, s_output)
 257 
 258     #
 259     s_month = z_y1
 260     total_status = s_status
 261     total_yield_p = s_yield
 262     total_limit_p = s_limit
 263     total_input = s_input
 264     total_output = s_output
 265     # ----------------------------------------------------------------------------------------------- #
 266 
 267     # vi5300_ft_wc_report_template
 268     # get_data_txt_v1 = open(r'C:\Users\chucheng.cao\Desktop\work\python\test_data\test_month_report_xx\note\bin1.txt', encoding='utf-8')
 269     # txt_v1 = []
 270     # for line in get_data_txt_v1:
 271     #     txt_v1.append(line.strip())
 272     # print('添加测试:',txt_v1[0])
 273 
 274     body = []
 275     # txt_bin1 = "BIN1" + txt_v1[0]
 276     txt_bin1 = "BIN1"
 277     txt_handler = "handler"
 278     txt_lot = "lot"
 279     txt_bin3 = "BIN3"
 280     txt_bin4 = "BIN4"
 281     txt_bin5 = "BIN5"
 282     txt_bin6_1 = "BIN6_1"
 283     txt_bin6_2 = "BIN6_2"
 284     txt_bin7_1 = "BIN7_1"
 285     txt_bin7_2 = "BIN7_2"
 286     txt_bin7_3 = "BIN7_3"
 287     txt_bin9 = "BIN9"
 288     txt_bin13 = "BIN13"
 289     txt_bin14 = "BIN14"
 290     txt_bin_vm = "BIN_vm"
 291     txt_bin_loss = "BIN_loss"
 292     # 图片路径
 293     # 当前绝对路径-建议使用相对路径
 294     source_bin1 = os.getcwd()
 295     Picture_bin1 = "\\4_result_ft\\month_report"
 296     picture_bin2 = "\\month_" + s_month + "\\picture\\"
 297     Picture_bin_route = source_bin1 + Picture_bin1 + picture_bin2
 298     print("图片路径目录:", Picture_bin_route)
 299 
 300     result = {'serial': "1",
 301               'SYL': total_limit_p,
 302               'Total': total_input,
 303               'BIN': total_output,
 304               'Yield': total_yield_p,
 305               'states': total_status,
 306               'Picture_bin1': Picture_bin_route + "BIN1.jpg", 'describe_bin1': txt_bin1,
 307               'Picture_handler': Picture_bin_route + "handler.jpg", 'describe_handler': txt_handler,
 308               'Picture_lot': Picture_bin_route + "lot.jpg", 'describe_lot': txt_lot,
 309               'Picture_bin3': Picture_bin_route + "BIN3.jpg", 'describe_bin3': txt_bin3,
 310               'Picture_bin4': Picture_bin_route + "BIN4.jpg", 'describe_bin4': txt_bin4,
 311               'Picture_bin5': Picture_bin_route + "BIN5.jpg", 'describe_bin5': txt_bin5,
 312               'Picture_bin6_1': Picture_bin_route + "BIN6_1.jpg", 'describe_bin6': txt_bin6_1,
 313               'Picture_bin6_2': Picture_bin_route + "BIN6_2.jpg", 'describe_bin6_2': txt_bin6_2,
 314               'Picture_bin7_1': Picture_bin_route + "BIN7_1.jpg", 'describe_bin7_1': txt_bin7_1,
 315               'Picture_bin7_2': Picture_bin_route + "BIN7_2.jpg", 'describe_bin7_2': txt_bin7_2,
 316               'Picture_bin7_3': Picture_bin_route + "BIN7_3.jpg", 'describe_bin7_3': txt_bin7_3,
 317               'Picture_bin9': Picture_bin_route + "BIN9.jpg", 'describe_bin9': txt_bin9,
 318               'Picture_bin13': Picture_bin_route + "BIN13.jpg", 'describe_bin13': txt_bin13,
 319               'Picture_bin14': Picture_bin_route + "BIN14.jpg", 'describe_bin14': txt_bin14,
 320               'Picture_bin_vm': Picture_bin_route + "BIN_vm.jpg", 'describe_bin_vm': txt_bin_vm,
 321               'Picture_bin_loss': Picture_bin_route + "BIN_loss.jpg", 'describe_bin_loss': txt_bin_loss,
 322 
 323               }
 324     body.append(result)
 325     start_monthly = "2023." + str(s_month) + ".1"
 326     stop_monthly = "2023." + str(s_month) + ".30"
 327     html_vi5300_ft_wc(body, start_monthly, stop_monthly, s_month)
 328 
 329 
 330 '''
 331 # ====================================================================================================================#
 332 # 本月数据汇总
 333 # ====================================================================================================================#
 334 '''
 335 
 336 
 337 def single_month_summary_v1(single_month_m12, get_raw_data):
 338     print('进入函数>>>: single_month_summary_v1 ...')  # 注意索引值从0开始,索引1==第1月
 339     '''
 340     # #  默认值,后续直接修改月份
 341     # month_handle_v1 = 11
 342     # # print('举例11月份数据', single_month_m12[month_handle_v1])
 343     # all_data = get_raw_data
 344 
 345     # # ---------------------------------------------------------------------------------------------------------------- #
 346     # print('打印全部数据\n',pd.DataFrame(all_data))
 347     # print('打印单行数据\n',pd.DataFrame(all_data.iloc[14]))
 348     # print('打印行列标签\n',pd.DataFrame(all_data.axes))
 349     # print('判断输入数据是否为空\n', all_data.empty)
 350     # print('DataFrame 维度的元组(行,列)\n', all_data.shape)
 351     # print('DataFrame具体位置 \n', all_data.loc[12][0])
 352     # print('DataFrame 首行名称 \n',all_data.columns)
 353     # # ---------------------------------------------------------------------------------------------------------------- #
 354     # # 无表头 - 获取CLOT
 355     # # print('DataFrame 首行名称 \n', all_data.columns)
 356     #
 357     # name_clot = 4   # lot id
 358     # print('DataFrame 首行中获取指定名称-无表头:', all_data.columns[name_clot])
 359     # name_clot_value = all_data.columns[name_clot]
 360     # print('索引值:< %s >' % name_clot_value)
 361     #
 362     # # 获取值缓存到列表中
 363     # list_clot_v2 = []
 364     # for index_v12 in range(len(single_month_m12[month_handle_v1])):
 365     #     # print("遍历-每月列表-行数值:",single_month_m12[month_handle_v1][index_v12])
 366     #     # print( all_data.loc[var_list_month_v12_n[month_handle_v1][index_v12]][name_clot_value])
 367     #     # var_list_clot_v2.append(all_data.loc[var_list_month_v12_n[month_handle_v1][index_v12]][name_clot_value])
 368     #     list_clot_v2.append(all_data.loc[single_month_m12[month_handle_v1][index_v12]][name_clot_value])
 369     # print('var_list_clot_v2 获取有效值:\n', list_clot_v2)
 370     # # ---------------------------------------------------------------------------------------------------------------- #
 371     # print('获取全部数据1: \n',all_data.loc[: , :].values)
 372     # print('获取全部数据2: \n', all_data.iloc[:, :].values)
 373     # 无表头- 获取某个值  第i行第j列的值,返回类型依内容而定
 374     # print("无表头- 获取某个值1: ", all_data.loc[1, 0])
 375     # print("无表头- 获取某个值2: ", all_data.iloc[1, 0])
 376     # 获取某一行 第i行数据,返回类型为ndarray(一维)
 377     # print("无表头- 获取某个行1: \n", all_data.loc[12].values)
 378     # print("无表头- 获取某个行2: \n", all_data.iloc[12].values)
 379     # 获取多行:第i1、i2、i3行数据,返回类型为ndarray(二维)
 380     # print("无表头- 获取多行1: \n", all_data.loc[[12,13]].values)
 381     # print("无表头- 获取多行2: \n", all_data.iloc[[12, 13]].values)
 382     # 无表头 -- 获取某一列: 第j列数据,返回类型为ndarray(一维)
 383     # print("无表头- 获取某个列1: \n", all_data.loc[:,0].values)
 384     # print("无表头- 获取某个列2: \n", all_data.iloc[:, 0].values)
 385     # 无表头 -- 获取多列:第j1、j2列数据,返回类型为ndarray(二维)
 386     # print("无表头- 获取多列1: \n", all_data.loc[:, [0 , 1]].values)
 387     # print("无表头- 获取多列2: \n", all_data.iloc[:, [0, 1]].values)
 388     # 无表头 --获取切片:行号[i1,i2]、列号[j1,j2]闭区间内的数据,行号[i1,i2)、列号[j1,j2)左闭右开区间内的数据,类型为ndarray(二维)
 389     # print('无表头 --获取切片1:\n', all_data.loc[10:15, 0:3].values)
 390     # print('无表头 --获取切片2:\n', all_data.iloc[10:15, 0:3].values)
 391     # # 举例:有表头 获取多列:第j1、j2列数据,,‘姓名’、‘性别’列数据, 第j1、j2列数据,返回类型为ndarray(二维)。
 392     # # all_data.loc[:, [“姓名”,“性别”]].values
 393     # # all_data.iloc[:, [0 , 3]].values
 394     # 介绍
 395     # loc和iloc方法是通过索引定位的方式获取数据的,写法为loc[A, B]和iloc[A, B]。
 396     # 其中A表示对行的索引,B表示对列的索引,B可缺省。A、B可为列表或i1:i2(切片)的形式,表示多行或多列。
 397     # 这两个方法的区别是,loc将参数当作标签处理,iloc将参数当作索引号处理。
 398     # 也就是说,在有表头的方式中,当列索引使用str标签时,只可用loc,当列索引使用索引号时,只可用iloc;
 399     # 在无表头的方式中,索引向量也是标签向量,loc和iloc均可使用;在切片中,loc是闭区间,iloc是半开区间。
 400     # # ---------------------------------------------------------------------------------------------------------------- #
 401         #  规整lot_id 参考函数
 402     # lot_list_v1 = []
 403     # wafer_list_v1 = []
 404     # for index_a in range(len(c_g_data1)):
 405     #     # print(index_a,c_g_data1[index_a],type(c_g_data1[index_a]))
 406     #     str_v1_lot = c_g_data1[index_a][0:6]
 407     #     str_v1_wafer =c_g_data1[index_a][7:9]
 408     #     lot_list_v1.append(str_v1_lot)
 409     #     wafer_list_v1.append(str_v1_wafer)
 410     # print('切片lot  : ',lot_list_v1)
 411     # print('wafer: ',wafer_list_v1)
 412     # one_lot = []
 413     # for v2_lot in lot_list_v1 :
 414     #         if v2_lot not in one_lot:
 415     #             one_lot.append(v2_lot)
 416     # print('唯一lot: ', one_lot)
 417     #
 418     # peopleidlistunique = list(set(lot_list_v1))  # 去重
 419     # new_lot = []
 420     # for i_v1 in peopleidlistunique:
 421     #     # print("元素", i_v1, "出现了", lot_list_v1.count(i_v1), "次")  # 统计数量并输出
 422     #     for i in range(lot_list_v1.count(i_v1)):
 423     #         new_lot.append(i_v1)
 424     # print('唯一补齐lot: ', new_lot)
 425     '''
 426 
 427     # # TODO 默认值11,后续直接修改月份
 428     month_h1 = 11
 429     s_m_m12 = single_month_m12[month_h1]  # 获取本月行号索引值
 430     raw_data_h1 = get_raw_data  # 获取整excel表句柄
 431     # ---------------------------------------------------------------------------------------------------------------- #
 432     time_s = datetime.datetime.now()
 433     print("\ntime_1 :", time_s)
 434     # TODO 手动输入实际模版
 435     # 使用无表头,使用数字强制索引
 436     '''
 437     u1_handler = 1
 438     u1_lot = 4
 439     u1_marking = 8
 440     u1_yield = 11
 441     u1_input = 12
 442     u1_bin1 = 13
 443     u1_bin1_p = 14
 444     u1_bin3 = 17
 445     u1_bin3_p = 18
 446     u1_bin4 = 19
 447     u1_bin4_p = 20
 448     u1_bin5 = 21
 449     u1_bin5_p = 22
 450     u1_bin6 = 23
 451     u1_bin6_p = 24
 452     u1_bin7 = 25
 453     u1_bin7_p = 26
 454     u1_bin9 = 29
 455     u1_bin9_p = 30
 456     u1_bin13 = 31
 457     u1_bin13_p = 32
 458     u1_bin14 = 33
 459     u1_bin14_p = 34
 460     u1_bin_vm = 35
 461     u1_bin_vm_p = 36
 462     u1_bin_loss = 37
 463     u1_bin_loss_p = 38
 464     u1_bin3_os = 39
 465     u1_bin3_os_p = 40
 466     u1_bin4_iih = 41
 467     u1_bin4_iih_p = 42
 468     u1_bin5_cal = 43  # calibration
 469     u1_bin5_cal_p = 44
 470     u1_bin6_vf = 45  # verify
 471     u1_bin6_vf_p = 46
 472     u1_bin6_ck = 47  # Crosstalk
 473     u1_bin6_ck_p = 48
 474     u1_bin7_power = 49
 475     u1_bin7_power_p = 50
 476     u1_bin7_os = 51
 477     u1_bin7_os_p = 52
 478     u1_bin7_lk = 53
 479     u1_bin7_lk_p = 54  # Leakage
 480     '''
 481     u1_handler = 1
 482     u1_lot = 4
 483     u1_marking = 9  # xx=9 we=8 ?
 484     u1_yield = 13  # xx=13 xx=12
 485     u1_input = 14
 486     u1_bin1 = 15
 487     u1_bin1_p = 16
 488     u1_bin3 = 19
 489     u1_bin3_p = 20
 490     u1_bin4 = 21
 491     u1_bin4_p = 22
 492     u1_bin5 = 23
 493     u1_bin5_p = 24
 494     u1_bin6 = 25
 495     u1_bin6_p = 26
 496     u1_bin7 = 27
 497     u1_bin7_p = 28
 498     u1_bin9 = 31
 499     u1_bin9_p = 32
 500     u1_bin13 = 33
 501     u1_bin13_p = 34
 502     u1_bin14 = 35
 503     u1_bin14_p = 36
 504     u1_bin_vm = 37
 505     u1_bin_vm_p = 38
 506     u1_bin_loss = 39
 507     u1_bin_loss_p = 40
 508     u1_bin3_os = 41
 509     u1_bin3_os_p = 42
 510     u1_bin4_iih = 43
 511     u1_bin4_iih_p = 44
 512     u1_bin5_cal = 45  # calibration
 513     u1_bin5_cal_p = 46
 514     u1_bin6_vf = 47  # verify
 515     u1_bin6_vf_p = 48
 516     u1_bin6_ck = 49  # Crosstalk
 517     u1_bin6_ck_p = 50
 518     u1_bin7_power = 51
 519     u1_bin7_power_p = 52
 520     u1_bin7_os = 53
 521     u1_bin7_os_p = 54
 522     u1_bin7_lk = 55
 523     u1_bin7_lk_p = 56  # Leakage
 524 
 525     # display_all_header_file_names(53, global_single_month_data, global_all_month_raw_data)
 526     # display_all_header_file_names(54, global_single_month_data, global_all_month_raw_data)
 527     # ---------------------------------------------------------------------------------------------------------------- #
 528     time_s = datetime.datetime.now()
 529     print("\ntime_s :", time_s, )
 530     # ---------------------------------------------------------------------------------------------------------------- #
 531     #  具体BIN1处理  通用处理
 532     # ---------------------------------------------------------------------------------------------------------------- #
 533     name_bin = "BIN1"
 534     reorder_bin_info(u1_marking, u1_handler, u1_lot, u1_input, u1_bin1, u1_bin1_p, u1_yield, name_bin, month_h1, s_m_m12, raw_data_h1)
 535     chart_total_info(u1_marking, u1_handler, u1_lot, u1_input, u1_bin1, u1_bin1_p, u1_yield, name_bin, month_h1, s_m_m12, raw_data_h1)
 536 
 537     # ---------------------------------------------------------------------------------------------------------------- #
 538     # 具体不良品处理  特殊处理
 539     # name_bin = "BIN2"  不存在
 540 
 541     #
 542     name_bin = "BIN3"
 543     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin3, u1_bin3_os, u1_bin3_p, u1_bin3_os_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 544     #
 545     name_bin = "BIN4"
 546     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin4, u1_bin4_iih, u1_bin4_p, u1_bin4_iih_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 547     #
 548     name_bin = "BIN5"
 549     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin5, u1_bin5_cal, u1_bin5_p, u1_bin5_cal_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 550     #
 551     name_bin = "BIN6_1"
 552     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin6, u1_bin6_vf, u1_bin6_p, u1_bin6_vf_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 553     name_bin = "BIN6_2"
 554     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin6, u1_bin6_ck, u1_bin6_p, u1_bin6_ck_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 555     #
 556     name_bin = "BIN7_1"
 557     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin7, u1_bin7_power, u1_bin7_p, u1_bin7_power_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 558     name_bin = "BIN7_2"
 559     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin7, u1_bin7_os, u1_bin7_p, u1_bin7_os_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 560     name_bin = "BIN7_3"
 561     defective_handle_v2(u1_marking, u1_handler, u1_lot, u1_bin7, u1_bin7_lk, u1_bin7_p, u1_bin7_lk_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 562     #
 563     name_bin = "BIN9"
 564     defective_handle_v2_se(u1_marking, u1_handler, u1_lot, u1_bin9, u1_bin9_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 565     name_bin = "BIN13"
 566     defective_handle_v2_se(u1_marking, u1_handler, u1_lot, u1_bin13, u1_bin13_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 567     name_bin = "BIN14"
 568     defective_handle_v2_se(u1_marking, u1_handler, u1_lot, u1_bin14, u1_bin14_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 569     name_bin = "BIN_vm"
 570     defective_handle_v2_se(u1_marking, u1_handler, u1_lot, u1_bin_vm, u1_bin_vm_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 571     name_bin = "BIN_loss"
 572     defective_handle_v2_se(u1_marking, u1_handler, u1_lot, u1_bin_loss, u1_bin_loss_p, name_bin, month_h1, s_m_m12, raw_data_h1)
 573 
 574     # ---------------------------------------------------------------------------------------------------------------- #
 575     time_e = datetime.datetime.now()
 576     print("\ntime_s :", time_e, "耗时:", (time_e - time_s))
 577 
 578 
 579 '''
 580 # ====================================================================================================================#
 581 # 本月-良品BIN1-测试数据汇总分布-通用模板1数据处理
 582 # ====================================================================================================================#
 583 '''
 584 
 585 
 586 def reorder_bin_info(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
 587     # ---------------------------------------------------------------------------------------------------------------- #
 588     # 开始计时
 589     datetime_object_11 = datetime.datetime.now()
 590     print("datetime_object_11 :", datetime_object_11)
 591 
 592     # 使用无表头,使用数字强制索引 -- 第一份引用
 593     x_handler_n2 = x_p2
 594     x_lot_n3 = x_p3
 595     month_n2 = z_p2
 596     single_month_d2 = z_p3
 597     raw_data_a2 = z_p4
 598 
 599     # 使用无表头,使用数字强制索引 -- 第一份引用
 600     u2_marking = x_p1
 601     u2_handler = x_p2
 602     u2_lot = x_p3
 603     u2_input = y_p1
 604     u2_bin1 = y_p2
 605     u2_bin1_p = y_p3
 606     u2_yield = y_p4
 607     u2_name = z_p1
 608     u2_month = z_p2
 609     u2_index_m12 = z_p3
 610     u2_raw_data = z_p4
 611 
 612     # ---------------------------------------------------------------------------------------------------------------------- #
 613     # 处理1 数据归类
 614     print('绘图处理: 月份< %d >' % month_n2, z_p1)
 615 
 616     # 指定月份 - 归类前文件
 617     c_g_name1, c_g_data1 = get_data_bin_v2(x_lot_n3, single_month_d2, raw_data_a2)
 618     c_g_name2, c_g_data2 = get_data_bin_v2(x_handler_n2, single_month_d2, raw_data_a2)
 619     print("源1:", c_g_name1, c_g_data1)
 620     print("源2:", c_g_name2, c_g_data2)
 621 
 622     # ---------------------------------------------------------------------------------------------------------------- #
 623     lot_list_v1 = []
 624     lot_list_v3 = []
 625     for index_a in range(len(c_g_data1)):
 626         num_v1_lot = single_month_d2[index_a]  # 获取本月行号 索引值
 627         str_v1_lot = c_g_data1[index_a][0:6]  # 正则表达获取lot ,去除wafer
 628         lot_handler_t1 = c_g_data2[index_a]  # 获取附属信息 handler
 629         lot_list_v2 = [num_v1_lot, str_v1_lot, lot_handler_t1]  # 3个关键字存储到一维列表中
 630         lot_list_v1.append(lot_list_v2)  # 存储到一维列表到二维列表中
 631         lot_list_v3.append(str_v1_lot)  # 1个关键字存储到一维列表中
 632     # all raw data 有效映射
 633     # print('all data -- 切片lot  : ', len(lot_list_v1), lot_list_v1)
 634 
 635     # 获取同一列表中相同元素,只保留一种类型
 636     one_lot = []
 637     for v2_lot in lot_list_v3:
 638         if v2_lot not in one_lot:
 639             one_lot.append(v2_lot)
 640     print('lot中唯一代表名称: ', one_lot)
 641 
 642     # 先按照 lot 分类 再按照 handler分类 最后索引-行号
 643     lot_handler_m1 = []  # 重新分类聚合的列表
 644     lot_h1_m1 = []
 645     lot_h1_m2 = []
 646     # 先按照 lot 大类分组
 647     for row_v1_w1 in one_lot:
 648         # print('每种类型的lot: ',row_v1_w1)
 649         line_re_lot5 = []
 650 
 651         for row_v1 in lot_list_v1:
 652             # print('切片lot中第1个元素-二维列中每行第1个元素: ',row_v1[1])
 653             if row_v1_w1 == row_v1[1]:
 654                 # print('打印相同的元素名称: ',row_v1_w1,row_v1[0],row_v1[1])
 655                 line_re_lot4 = [row_v1[0], row_v1[1], row_v1[2]]  # 按照每个lot大类重新组合索引值
 656                 line_re_lot5.append(line_re_lot4)
 657                 lot_h1_m1.append(row_v1[0])
 658                 lot_h1_m2.append(line_re_lot4)
 659         # print('每个lot大类-组合: ',line_re_lot5)
 660 
 661         # 每个lot类 再按照 handler 重新分类
 662         re_handler_1 = []
 663         re_handler_2 = []
 664         re_handler_3 = []
 665         re_handler_4 = []
 666         re_handler_x = []
 667         handler_name_d = ["handler0 名称:", "HIP-01", "HIP-02", "HIP-03", "HIP-04", ]  # TODO g根据机台重新添加
 668         for two_m1 in line_re_lot5:
 669             # print('每个lot中 handler元素组合:',two_m1,two_m1[2])
 670             if handler_name_d[1] == two_m1[2]:
 671                 # print('具体handler匹配: ',handler_name_d[1],two_m1[2])
 672                 re_handler_1.append(two_m1[0])  # handler1
 673             elif handler_name_d[2] == two_m1[2]:
 674                 re_handler_2.append(two_m1[0])  # handler2
 675             elif handler_name_d[3] == two_m1[2]:
 676                 re_handler_3.append(two_m1[0])  # handler3
 677             elif handler_name_d[4] == two_m1[2]:
 678                 re_handler_4.append(two_m1[0])  # handler4
 679             else:
 680                 re_handler_x.append(two_m1[0])  # handler x 未知分类
 681 
 682         # 一维列表合并
 683         re_handler_m = re_handler_1 + re_handler_2 + re_handler_3 + re_handler_4 + re_handler_x
 684         # print("按照handler 子归类:", re_handler_m)
 685         lot_handler_m1.append(re_handler_m)  # 一维列表组合成二维列表
 686     # ---------------------------------------------------------------------------------------------------------------- #
 687     # 显示分组情况
 688     # 第1种情况
 689     # print('仅按照大类lot分组:',len(lot_h1_m2),lot_h1_m2)
 690     # print('仅按照大类lot分组-索引行号:', len(lot_h1_m1), lot_h1_m1)
 691 
 692     # 第2种情况
 693     # print("lot_handler_ 分组二维列表:", len(lot_handler_m1), lot_handler_m1)
 694     # 二维列表转一维列表 非常重要
 695     lot_handler_m1_result = [n for a in lot_handler_m1 for n in a]
 696     print('最终结果 -- lot_handler_m1_result: ', lot_handler_m1_result)
 697 
 698     # # 第3种情况 - 仅仅按照handler分类  顺序重新归类
 699     # reclassify_1 = []
 700     # reclassify_2 = []
 701     # reclassify_3 = []
 702     # reclassify_4 = []
 703     # reclassify_x = []
 704     # handler_name = ["handler0 名称:", "HIP-01", "HIP-02", "HIP-03", "HIP-04", ]
 705     # for two_m1 in range(len(single_month_m12[month_h1])):
 706     #     # print('按照handler 分组',single_month_m12[month_h1][two_m1])
 707     #     if handler_name[1] == c_g_data2[two_m1]:
 708     #         reclassify_1.append(single_month_m12[month_h1][two_m1])     # handler1
 709     #     elif handler_name[2] == c_g_data2[two_m1]:
 710     #         reclassify_2.append(single_month_m12[month_h1][two_m1])     # handler2
 711     #     elif handler_name[3] == c_g_data2[two_m1]:
 712     #         reclassify_3.append(single_month_m12[month_h1][two_m1])     # handler3
 713     #     elif handler_name[4] == c_g_data2[two_m1]:
 714     #         reclassify_4.append(single_month_m12[month_h1][two_m1])     # handler4
 715     #     else:
 716     #         reclassify_x.append(single_month_m12[month_h1][two_m1])     # handler x
 717     # handler_merged_result3 = reclassify_1 + reclassify_2 + reclassify_3 + reclassify_4 + reclassify_x
 718     # print("按照handler 重新归类 索引值: ",handler_merged_result3)
 719 
 720     # 用目标值 替换源列表中 行分组
 721     single_month_d2 = lot_handler_m1_result
 722     # single_month_m12[month_h1] = handler_merged_result3
 723     # 显示新月份所有的月度索引值-行号
 724     # for index_a in range(1, 13):
 725     #     print('第%d月数据' % (index_a), single_month_m12[index_a])
 726     # 新索引值重新被引用
 727     index_s_m2 = single_month_d2
 728 
 729     datetime_object_12 = datetime.datetime.now()
 730     print("datetime_object_12 :", datetime_object_12, ' 耗时:', (datetime_object_12 - datetime_object_11))
 731 
 732     # ---------------------------------------------------------------------------------------------------------------------- #
 733     # 绘图  是由上述函数传递的:index_s_m2
 734     histogram_handle_v1(u2_marking, u2_handler, u2_lot, u2_input, u2_bin1, u2_bin1_p, u2_yield, u2_name, u2_month, index_s_m2, u2_raw_data)
 735 
 736     datetime_object_13 = datetime.datetime.now()
 737     print("datetime_object_12 :", datetime_object_13, ' 耗时:', (datetime_object_13 - datetime_object_11))
 738 
 739 
 740 '''
 741 # ====================================================================================================================#
 742 # 本月-良品BIN1-测试数据汇总分布-绘图1
 743 # ====================================================================================================================#
 744 '''
 745 
 746 
 747 def histogram_handle_v1(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
 748     print('#---- histogram_handle_v1 ----#')
 749     x_axle_n1 = x_p1
 750     x_axle_n2 = x_p2
 751     x_axle_n3 = x_p3
 752     y_total_t1 = y_p1
 753     y_total_t2 = y_p2
 754     y_yield_t1 = y_p3
 755     y_yield_t2 = y_p4
 756     bin_name = z_p1
 757     month_n1 = z_p2
 758     single_month_d1 = z_p3
 759     raw_data_a1 = z_p4
 760     print('绘图处理: 月份< %d >' % month_n1, )
 761     # 获取每月函数 有效数据 x_axle_n2
 762     x_name1, x_data1 = get_data_bin_v2(x_axle_n1, single_month_d1, raw_data_a1)
 763     x_name2, x_data2 = get_data_bin_v2(x_axle_n2, single_month_d1, raw_data_a1)
 764     x_name3, x_data3 = get_data_bin_v2(x_axle_n3, single_month_d1, raw_data_a1)
 765     y_name1, y_data1 = get_data_bin_v2(y_total_t1, single_month_d1, raw_data_a1)
 766     y_name2, y_data2 = get_data_bin_v2(y_total_t2, single_month_d1, raw_data_a1)
 767     y_name3, y_data3 = get_data_bin_v2(y_yield_t1, single_month_d1, raw_data_a1)
 768     y_name4, y_data4 = get_data_bin_v2(y_yield_t2, single_month_d1, raw_data_a1)
 769     # print(x_name1, x_data1)
 770     # print(x_name2, x_data2)
 771     # print(y_name1, y_data1)
 772     # print(y_name2, y_data2)
 773     # print(y_name3, y_data3)
 774 
 775     # ======================================================================================== #
 776 
 777     # 整体参数配置
 778     font = FontProperties(size=10)
 779     plt.rcParams["font.sans-serif"] = ['SimHei']
 780     plt.rcParams['axes.unicode_minus'] = False
 781     plt.rcParams['font.family'] = ['SimHei']
 782     plt.rcParams['font.sans-serif'] = ['SimHei']
 783     plt.rcParams['figure.figsize'] = (30, 10)
 784     plt.rc('font', family='SimHei', size=8)
 785 
 786     # 创建一个图形和两个y轴
 787     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
 788 
 789     # 柱状图柱子宽度
 790     bar_width = 0.4
 791     x_ticks = range(len(x_data1))  # x轴刻度位置 | 折线图x位置
 792     bar_1_x = [(ii - bar_width + 0.2) for ii in x_ticks]  # 柱状图1 - x位置
 793     bar_2_x = [(ww - bar_width + 0.6) for ww in x_ticks]
 794 
 795     # 设置x轴刻度字体以及方向-单刻度标签
 796     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
 797     [label.set_fontname('SimHei') for label in labels1]
 798     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
 799 
 800     # 设置x轴刻度字体以及方向- 叠加双刻度标签
 801     labels = []
 802     for two_m1 in range(len(x_data1)):
 803         cell_m2 = x_data3[two_m1][0:6] + '   ' + x_data2[two_m1] + '   ' + x_data1[two_m1]
 804         labels.append(cell_m2)
 805     # labels = x_ticks  # 默认
 806     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
 807     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
 808     # 自适应调整布局+ 指定 解决X轴范围问题
 809     fig.autofmt_xdate(rotation=90)
 810 
 811     # -------------------------------------------------------------------------------------- #
 812     # # 同一刻度标签标记为不同颜色 插孔法
 813     # 第1种方案
 814     # xtick_labels = ax1.get_xticklabels()
 815     # colors = ['red', 'green', 'blue', 'purple', 'orange', 'black', 'brown', 'gray', 'pink', 'yellow', 'cyan', 'magenta']
 816     # for x_colors in range(int(len(x_data1)/4)):
 817     #     # print(0+x_colors*4, 1+x_colors*4, 2+x_colors*4,3+x_colors*4)
 818     #     x_colors_a = 0 + x_colors * 4
 819     #     x_colors_b = 1 + x_colors * 4
 820     #     x_colors_c = 2 + x_colors * 4
 821     #     x_colors_d = 3 + x_colors * 4
 822     #     pass
 823     #     xtick_labels[x_colors_a].set_color('red')
 824     #     xtick_labels[x_colors_b].set_color('blue')
 825     #     xtick_labels[x_colors_c].set_color('orange')
 826     #     xtick_labels[x_colors_d].set_color('magenta')
 827     #
 828     #    升级-适用较为复杂的场景
 829     # 第2种方案
 830     print(x_name1)
 831     print(x_name2)
 832     print(x_name3)
 833 
 834     index_lot_v5 = []
 835     for index_a in range(len(single_month_d1)):
 836         index_lot = single_month_d1[index_a]  # 获取本月行号 索引值
 837         index_m1 = x_data3[index_a][0:6]  # 获取本月行号 索引值
 838         index_lot_v5.append(index_m1)
 839     # all raw data 有效映射
 840     print("all raw data 有效映射:", index_lot_v5)
 841     # 获取同一列表中相同元素,只保留一种类型
 842     one_lot_v1 = []
 843     for v2_lot in index_lot_v5:
 844         if v2_lot not in one_lot_v1:
 845             one_lot_v1.append(v2_lot)
 846     print('lot中唯一代表名称: ', one_lot_v1)
 847     xtick_labels = ax1.get_xticklabels()
 848     colors = ['red', 'green', 'blue', 'purple', 'orange', 'brown', 'gray', 'pink', 'cyan', 'magenta', 'yellow', 'black', ]
 849     # 利用唯一lot去适配列表lot,影射到对应刻度,根据余数去自动识别颜色,默认10种
 850     for x_color in range(len(x_data3)):
 851         # print("x_color: ",x_color,x_data3[x_color][0:6])
 852         for one_c1 in range(len(one_lot_v1)):
 853             # print("Index:", one_c1, "Value:", one_lot_v1[one_c1])
 854             if one_lot_v1[one_c1] == x_data3[x_color][0:6]:
 855                 one_color_v1 = one_c1 % 10
 856                 if one_color_v1 == 0:
 857                     xtick_labels[x_color].set_color(colors[0])
 858                 elif one_color_v1 == 1:
 859                     xtick_labels[x_color].set_color(colors[1])
 860                 elif one_color_v1 == 2:
 861                     xtick_labels[x_color].set_color(colors[2])
 862                 elif one_color_v1 == 3:
 863                     xtick_labels[x_color].set_color(colors[3])
 864                 elif one_color_v1 == 4:
 865                     xtick_labels[x_color].set_color(colors[4])
 866                 elif one_color_v1 == 5:
 867                     xtick_labels[x_color].set_color(colors[5])
 868                 elif one_color_v1 == 6:
 869                     xtick_labels[x_color].set_color(colors[6])
 870                 elif one_color_v1 == 7:
 871                     xtick_labels[x_color].set_color(colors[7])
 872                 elif one_color_v1 == 8:
 873                     xtick_labels[x_color].set_color(colors[8])
 874                 elif one_color_v1 == 9:
 875                     xtick_labels[x_color].set_color(colors[9])
 876         # -------------------------------------------------------------------------------------- #
 877 
 878     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
 879     ax2 = ax1.twinx()
 880 
 881     # 图例文件描述-动态变化
 882     title_up = "本月测试  " + bin_name + "  分布"
 883     legend_x3 = y_name1
 884     legend_x4 = y_name2
 885     legend_y3 = y_name3
 886     legend_y4 = y_name4
 887 
 888     # ====================================================================================================================#
 889     # 绘制柱状图
 890     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
 891     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
 892     bar3 = ax1.bar(bar_1_x, y_data1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
 893     bar4 = ax1.bar(bar_2_x, y_data2, label=legend_x4, color='gold', width=bar_width, linewidth=0.2, edgecolor="white")
 894 
 895     # 绘制折线图
 896     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
 897     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
 898     line3 = ax2.plot(x_data1, y_data3, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
 899     line4 = ax2.plot(x_data1, y_data4, label=legend_y4, color='red', marker='.', markersize='6', ls='-')
 900 
 901     # 折线图点描述
 902     for a_x1, b_y3, c_y4 in zip(x_data1, y_data3, y_data4):
 903         if b_y3 < c_y4:
 904             print("# 低于卡控线: ", a_x1, file=run_log)
 905             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=12, font=font)
 906         else:
 907             # print("# 正常模组: ", a_x1)
 908             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=8, font=font)
 909             ax2.text(1, c_y4, '{:.2f}%'.format(c_y4 * 100), ha='center', va='bottom', fontsize=11, font=font)  # 只显示一个
 910 
 911     # ====================================================================================================================#
 912 
 913     # 设置x轴和y轴的标签,指明坐标含义
 914     ax1.set_xlabel('lot ID', fontdict={'size': 16})
 915     # 左边-y轴为:数量模式
 916     ax1.set_ylabel('模组数量', fontdict={'size': 16})
 917     # 右边-y轴为:百分比形式
 918     ax2.set_ylabel('百分比', fontdict={'size': 16})
 919 
 920     # 左-y轴为:刻度范围,动态调整
 921     max_value_r1 = int(max(y_data1) * 1.3)
 922     min_value_r1 = int(min(y_data1) * 0.9)
 923     if max_value_r1 < 5:
 924         max_value_r1 = 10  # 直接赋值
 925         min_value_r1 = 0  # 直接赋值
 926     ax1.set_ylim(min_value_r1, max_value_r1)
 927     #  右边-y轴为:最大值为100%,小数点2位
 928     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
 929 
 930     # 设置x轴和y轴刻度字体
 931     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
 932     [label.set_fontname('SimHei') for label in labels2]
 933 
 934     # 添加图表题  plt.title('双y轴折线图')
 935     plt.title(title_up, color="red", fontsize=16)
 936 
 937     # 设置轴标签颜色
 938     # ax1.tick_params('x', colors='Black')
 939     ax1.tick_params('y', colors='royalblue')
 940     ax2.tick_params('y', colors='tomato')
 941 
 942     # 设置轴颜色
 943     ax1.spines['left'].set_color('royalblue')
 944     ax2.spines['left'].set_color('royalblue')
 945     ax1.spines['right'].set_color('tomato')
 946     ax2.spines['right'].set_color('tomato')
 947 
 948     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
 949     ax1.spines['top'].set_visible(False)
 950     ax2.spines['top'].set_visible(False)
 951 
 952     # 添加图例函数:  plt.legend()
 953     # 添加图例 - 添加方向改为以下代码
 954     ax1.legend(loc='upper left')
 955     ax2.legend(loc='upper right')
 956     # 添加图例 - 将`图例合并改为以下代码
 957     # lines = line1 + line2 + line3 + line4
 958     # lines = line3 + line4
 959     # labels = [h.get_label() for h in lines]
 960     # plt.legend(lines, labels, loc='upper right')
 961 
 962     # 设置中文显示
 963     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
 964     plt.rcParams['axes.unicode_minus'] = False
 965 
 966     # 虚拟背景线
 967     plt.grid(True, linestyle="--")
 968 
 969     # 展示图片
 970     # plt.show()
 971     # 显示柱状图时间,单位s
 972     time_v1 = 1
 973     while time_v1 != 0:
 974         print('显示倒计时:%d s' % time_v1)
 975         plt.pause(1)
 976         time_v1 = time_v1 - 1
 977     print('直方图显示完成')
 978 
 979     # 图片保存对应文件
 980     picture_m = './4_result_ft/picture/' + bin_name + r".jpg"
 981     plt.savefig(picture_m)
 982     plt.draw()
 983     print('图片保存对应文件-完成')
 984     plt.close()  # 关闭图表显示
 985 
 986 
 987 '''
 988 # ====================================================================================================================#
 989 # 本月-良品BIN1-handler&lot汇总分布-通用2模板数据处理
 990 # ====================================================================================================================#
 991 '''
 992 
 993 
 994 def chart_total_info(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
 995     print('>>> chart_total_info ...')
 996     # u1_marking, u1_handler, u1_lot, u1_input, u1_bin1, u1_bin1_p, u1_yield, name_bin, month_h1, index_s_m0, raw_data_h1
 997     # 开始计时
 998     datetime_object_21 = datetime.datetime.now()
 999     print("datetime_object_21 :", datetime_object_21)
1000     # 1按照总数汇总
1001     # 按照handler类型汇总-4种
1002     # 按照lot类型汇总-动态
1003     x_axle_e1 = x_p1
1004     x_axle_e2 = x_p2
1005     x_axle_e3 = x_p3
1006     y_total_k1 = y_p1
1007     y_total_k2 = y_p2
1008     y_yield_k3 = y_p3
1009     y_yield_k4 = y_p4
1010     bin_name = z_p1
1011     month_u1 = z_p2
1012     single_month_g1 = z_p3
1013     raw_data_t1 = z_p4
1014     print('汇总处理: 月份< %d >' % month_u1, )
1015     print(single_month_g1)
1016     x_name_f1, x_data_j1 = get_data_bin_v2(x_axle_e1, single_month_g1, raw_data_t1)
1017     x_name_f2, x_data_j2 = get_data_bin_v2(x_axle_e2, single_month_g1, raw_data_t1)
1018     x_name_f3, x_data_j3 = get_data_bin_v2(x_axle_e3, single_month_g1, raw_data_t1)
1019     y_name_f1, y_data_j1 = get_data_bin_v2(y_total_k1, single_month_g1, raw_data_t1)
1020     y_name_f2, y_data_j2 = get_data_bin_v2(y_total_k2, single_month_g1, raw_data_t1)
1021     y_name_f3, y_data_j3 = get_data_bin_v2(y_yield_k3, single_month_g1, raw_data_t1)
1022     y_name_f4, y_data_j4 = get_data_bin_v2(y_yield_k4, single_month_g1, raw_data_t1)
1023     # print('源1:', x_name_f1, x_data_j1)  # MARKING
1024     # print('源2:', x_name_f2, x_data_j2)  # HANDLER
1025     # print('源3:', x_name_f3, x_data_j3)  # LOTID
1026     print('源4:', y_name_f1, y_data_j1)  # Input
1027     print('源5:', y_name_f2, y_data_j2)  # BIN01(Good)
1028     # print('源6:', y_name_f3, y_data_j3)  # BIN01(%)
1029     # print('源7:', y_name_f4, y_data_j4)  # YIELDLIMIT
1030 
1031     # def limit
1032     handler_syl = 0.9000
1033     lot_syl = 0.9000
1034 
1035     # 创建一个新的 Excel 文件
1036     workbook = openpyxl.Workbook()
1037     one_sheet = workbook.active
1038     test_result_v0 = ["project_name", "结果", "实际良率", "目标良率", "投入数量(ea)", "实际产出(ea)"]
1039     one_sheet.append(test_result_v0)  # 追加一行数据
1040     # 动态保存路径
1041     # target_name = str(month_u1) + "月_汇总统计结果.xlsx"
1042     target_name = "月度_汇总统计结果.xlsx"
1043     target_path = r'./4_result_ft/picture/' + target_name
1044     # 保存数据
1045     # workbook.save(target_path)
1046 
1047     # ---------------------------------------------------------------------------------------------------------------- #
1048     # 1按照总数汇总
1049     r1_input = np.sum(y_data_j1)
1050     r1_bin1 = np.sum(y_data_j2)
1051     r1_yield = r1_bin1 / r1_input
1052     r1_yield_percent = "{:.2%}".format(r1_yield)
1053     r1_limit = "{:.2%}".format(y_data_j4[0])
1054     r1_state = 'pass' if r1_yield > y_data_j4[0] else 'fail'
1055     print(
1056         'summary 结果:%s 实际良率:%s  目标良率:%s 投入数量(ea): %d   实际产出(ea):%d \n' % (r1_state, r1_yield_percent, r1_limit, r1_input, r1_bin1))
1057 
1058     test_result_v0 = ["summary", r1_state, r1_yield_percent, r1_limit, r1_input, r1_bin1]
1059     one_sheet.append(test_result_v0)  # 追加一行数据
1060     # ---------------------------------------------------------------------------------------------------------------- #
1061     datetime_21_1 = datetime.datetime.now()
1062     print("datetime_21_1 :", datetime_21_1, ' 耗时:', (datetime_21_1 - datetime_object_21))
1063     # ---------------------------------------------------------------------------------------------------------------- #
1064     # 按照handler类型汇总-4种
1065     # 仅按照handler分类  顺序重新归类
1066     re_class_1 = []
1067     re_class_2 = []
1068     re_class_3 = []
1069     re_class_4 = []
1070     re_class_x = []
1071     line_cache_a1 = []
1072     line_cache_b1 = []
1073     line_cache_c1 = []
1074     line_cache_d1 = []
1075     line_cache_x1 = []
1076     handler_name = ["handler0 名称:", "HIP-01", "HIP-02", "HIP-03", "HIP-04", ]
1077     print("handler: ", handler_name[1:])
1078     for handler_h1 in range(len(x_data_j2)):
1079         # print('按照handler 分组',x_data_j2[handler_h1])
1080         if handler_name[1] == x_data_j2[handler_h1]:
1081             re_class_1.append(single_month_g1[handler_h1])  # handler1
1082             line_cache_a = [single_month_g1[handler_h1], y_data_j1[handler_h1], y_data_j2[handler_h1]]
1083             line_cache_a1.append(line_cache_a)
1084         elif handler_name[2] == x_data_j2[handler_h1]:
1085             re_class_2.append(single_month_g1[handler_h1])  # handler2
1086             line_cache_b = [single_month_g1[handler_h1], y_data_j1[handler_h1], y_data_j2[handler_h1]]
1087             line_cache_b1.append(line_cache_b)
1088         elif handler_name[3] == x_data_j2[handler_h1]:
1089             re_class_3.append(single_month_g1[handler_h1])  # handler3
1090             line_cache_c = [single_month_g1[handler_h1], y_data_j1[handler_h1], y_data_j2[handler_h1]]
1091             line_cache_c1.append(line_cache_c)
1092         elif handler_name[4] == x_data_j2[handler_h1]:
1093             re_class_4.append(single_month_g1[handler_h1])  # handler4
1094             line_cache_d = [single_month_g1[handler_h1], y_data_j1[handler_h1], y_data_j2[handler_h1]]
1095             line_cache_d1.append(line_cache_d)
1096         else:
1097             re_class_x.append(single_month_g1[handler_h1])  # handler x
1098             line_cache_x = [single_month_g1[handler_h1], y_data_j1[handler_h1], y_data_j2[handler_h1]]
1099             line_cache_x1.append(line_cache_x)
1100 
1101         # 创建二维数组
1102         line_cache_s = [line_cache_a1, line_cache_b1, line_cache_c1, line_cache_d1]
1103     # 按照handler 重新分组
1104 
1105     # handler_merged_4 = re_class_1 + re_class_2 + re_class_3 + re_class_4 + re_class_x
1106     # print("按照handler 重新归类 索引值: ", len(handler_merged_4), handler_merged_4)
1107     # 显示具体handler分类
1108     # print("handler1", re_class_1)
1109     # print("handler2", re_class_2)
1110     # print("handler3", re_class_3)
1111     # print("handler4", re_class_4)
1112     # print("handlerx", re_class_x)
1113 
1114     # 创建handler 二维列表   实际只有4个  非常重要的列表组合创建
1115     handler_merged_5 = [re_class_1, re_class_2, re_class_3, re_class_4]
1116     # print(len(handler_merged_5), 'handler  二维列表: ', handler_merged_5)
1117     # print(len(line_cache_s)    , 'handler  三维列表: ', line_cache_s)
1118 
1119     #
1120     banana_a1 = []
1121     banana_b1 = []
1122     banana_b2 = []
1123     banana_b3 = []
1124     banana_b4 = []
1125     # 根据handler列表-自动循环方案
1126     for banana in range(len(line_cache_s)):
1127         line_cache21 = []
1128         line_cache22 = []
1129         index_n1 = banana + 1
1130         # print("目的获取handler的个数 -第%d个 "%banana)
1131         for sub_index1 in range(len(line_cache_s[banana])):
1132             # print("目的获取三维数组的每行的列表值(一维):",line_cache_s[banana][sub_index1])
1133             for sub_index2 in range(len(handler_merged_5)):
1134                 # print('打印比对的数值:',handler_merged_5[banana][sub_index2], line_cache_s[banana][sub_index1])
1135                 if handler_merged_5[banana][sub_index2] == line_cache_s[banana][sub_index1][0]:
1136                     line_cache21.append(line_cache_s[banana][sub_index1][1])
1137                     line_cache22.append(line_cache_s[banana][sub_index1][2])
1138         h1_input = np.sum(line_cache21)
1139         h1_output = np.sum(line_cache22)
1140         h1_yield = h1_output / h1_input
1141         h1_yield_percent = "{:.2%}".format(h1_yield)
1142         h1_state = 'pass' if h1_yield > handler_syl else 'fail'
1143         print('Handler HIP-%d >>> \t结果:%s \t实际: %s \t投入数量: %d \t实际产出: %d ' % (banana, h1_state, h1_yield_percent, h1_input, h1_output,))
1144         project_n1 = 'Handler HIP-' + str(banana)
1145         h1_syl = h1_yield_percent = "{:.2%}".format(handler_syl)
1146         test_result_v0 = [project_n1, h1_state, h1_yield, h1_syl, h1_input, h1_output]
1147         one_sheet.append(test_result_v0)  # 追加一行数据
1148 
1149         # 存储列表-绘图
1150         banana_a1.append(handler_name[index_n1])
1151         banana_b1.append(h1_input)
1152         banana_b2.append(h1_output)
1153         banana_b3.append(h1_yield)
1154         banana_b4.append(handler_syl)
1155     # 绘图
1156     t_category = "handler"
1157     histogram_handle_v1_se(banana_a1, banana_b1, banana_b2, banana_b3, banana_b4, t_category)
1158 
1159     # ---------------------------------------------------------------------------------------------------------------- #
1160     datetime_21_2 = datetime.datetime.now()
1161     print("datetime_21_2 :", datetime_21_2, ' 耗时:', (datetime_21_2 - datetime_21_1))
1162     print("\n")
1163     # ---------------------------------------------------------------------------------------------------------------- #
1164     # 按照lot类型汇总-动态
1165     index_lot_lv5 = []
1166     for orange in range(len(single_month_g1)):
1167         index_lot = single_month_g1[orange]  # 获取本月行号 索引值
1168         index_m1 = x_data_j3[orange][0:6]  # 获取本月行号 索引值
1169         index_lot_lv5.append(index_m1)
1170     # all raw data 有效映射
1171     # print('all raw data 有效映射: \n',index_lot_lv5)
1172     # 获取同一列表中相同元素,只保留一种类型
1173     one_lot_orange = []
1174     for orange_lot in index_lot_lv5:
1175         if orange_lot not in one_lot_orange:
1176             one_lot_orange.append(orange_lot)
1177     print('lot 唯一代表 名称: ', one_lot_orange)
1178 
1179     km_lot_all = []
1180     for one_c1 in range(len(one_lot_orange)):
1181         km_lot = []
1182         for watermelon in range(len(x_data_j3)):
1183             # print("Index:", one_c1, "Value:", one_lot_orange[one_c1], x_data_j3[watermelon][0:6])
1184             if one_lot_orange[one_c1] == x_data_j3[watermelon][0:6]:
1185                 # print('匹配:',one_c1 ,one_lot_orange[one_c1], x_data_j3[watermelon][0:6])
1186                 km_lot_element = [single_month_g1[watermelon], x_data_j3[watermelon], y_data_j1[watermelon], y_data_j2[watermelon]]
1187                 km_lot.append(km_lot_element)
1188         # print("打印每行lot的数据:",km_lot)
1189         km_lot_all.append(km_lot)
1190     # print("打印每行lot的数据:",km_lot_all)
1191 
1192     #
1193     banana_a1 = []
1194     banana_b1 = []
1195     banana_b2 = []
1196     banana_b3 = []
1197     banana_b4 = []
1198     # 根据lot列表-自动循环方案
1199     for banana in range(len(km_lot_all)):
1200         line_cache21 = []
1201         line_cache22 = []
1202         # print("目的获取handler的个数 -第%d个 "%banana)
1203         for sub_index1 in range(len(km_lot_all[banana])):
1204             # print("目的获取三维数组的每行的列表值(一维):",km_lot_all[banana][sub_index1])
1205             for sub_index2 in range(len(one_lot_orange)):
1206                 # print('打印比对的数值:',one_lot_orange[sub_index2], km_lot_all[banana][sub_index1][1][0:6])
1207                 if one_lot_orange[sub_index2] == km_lot_all[banana][sub_index1][1][0:6]:
1208                     line_cache21.append(km_lot_all[banana][sub_index1][2])
1209                     line_cache22.append(km_lot_all[banana][sub_index1][3])
1210         l1_input = np.sum(line_cache21)
1211         l1_output = np.sum(line_cache22)
1212         l1_yield = l1_output / l1_input
1213         l1_yield_percent = "{:.2%}".format(l1_yield)
1214         l1_state = 'pass' if l1_yield > lot_syl else 'fail'
1215         print('lot-%s >>> \t结果%s \t良率: %s \t投入数量: %d  \t实际产出: %d ' % (
1216             km_lot_all[banana][0][1][0:6], l1_state, l1_yield_percent, l1_input, l1_output))
1217         project_n1 = 'lot-' + km_lot_all[banana][sub_index1][1][0:6]
1218         l1_syl = "{:.2%}".format(lot_syl)
1219         test_result_v0 = [project_n1, l1_state, l1_yield_percent, l1_syl, l1_input, l1_output]
1220         one_sheet.append(test_result_v0)  # 追加一行数据
1221 
1222         # 存储列表-绘图
1223         banana_a1.append(one_lot_orange[banana])
1224         banana_b1.append(l1_input)
1225         banana_b2.append(l1_output)
1226         banana_b3.append(l1_yield)
1227         banana_b4.append(lot_syl)
1228     # 绘图
1229     t_category = "lot"
1230     histogram_handle_v1_se(banana_a1, banana_b1, banana_b2, banana_b3, banana_b4, t_category)
1231     # ---------------------------------------------------------------------------------------------------------------- #
1232     datetime_21_3 = datetime.datetime.now()
1233     print("datetime_21_3 :", datetime_21_3, ' 耗时:', (datetime_21_3 - datetime_21_2))
1234     # ---------------------------------------------------------------------------------------------------------------- #
1235     # 保存数据
1236     workbook.save(target_path)
1237 
1238     datetime_object_22 = datetime.datetime.now()
1239     print("\n运行结束 :", datetime_object_22, ' 总耗时:', (datetime_object_22 - datetime_object_21))
1240 
1241 
1242 '''
1243 # ====================================================================================================================#
1244 # 本月-良品BIN1-handler&lot汇总分布-绘图2
1245 # ====================================================================================================================#
1246 '''
1247 
1248 
1249 def histogram_handle_v1_se(x_p1, y_p1, y_p2, y_p3, y_p4, z_p1):
1250     print('#---- histogram_handle_v1_se ----#')
1251     x_axle_n1 = x_p1
1252     y_total_t1 = y_p1
1253     y_total_t2 = y_p2
1254     y_yield_t1 = y_p3
1255     y_yield_t2 = y_p4
1256     z_name_km1 = z_p1
1257 
1258     # ======================================================================================== #
1259     # 整体参数配置
1260     font = FontProperties(size=10)
1261     plt.rcParams["font.sans-serif"] = ['SimHei']
1262     plt.rcParams['axes.unicode_minus'] = False
1263     plt.rcParams['font.family'] = ['SimHei']
1264     plt.rcParams['font.sans-serif'] = ['SimHei']
1265     plt.rcParams['figure.figsize'] = (30, 10)
1266     plt.rc('font', family='SimHei', size=8)
1267 
1268     # 创建一个图形和两个y轴
1269     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
1270 
1271     # 柱状图柱子宽度
1272     bar_width = 0.2
1273     x_ticks = range(len(x_axle_n1))  # x轴刻度位置 | 折线图x位置
1274     bar_1_x = [(ii - bar_width + 0.1) for ii in x_ticks]  # 柱状图1 - x位置
1275     bar_2_x = [(ww - bar_width + 0.3) for ww in x_ticks]
1276 
1277     # 设置x轴刻度字体以及方向-单刻度标签
1278     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
1279     [label.set_fontname('SimHei') for label in labels1]
1280     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
1281 
1282     # 设置x轴刻度字体以及方向- 叠加双刻度标签
1283     labels = []
1284     for two_m1 in range(len(x_axle_n1)):
1285         cell_m2 = x_axle_n1[two_m1]
1286         labels.append(cell_m2)
1287     # labels = x_ticks  # 默认
1288     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
1289     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
1290     # 自适应调整布局+ 指定 解决X轴范围问题
1291     fig.autofmt_xdate(rotation=90)
1292 
1293     # -------------------------------------------------------------------------------------- #
1294     # # 同一刻度标签标记为不同颜色 插孔法
1295     # 第1种方案
1296     xtick_labels = ax1.get_xticklabels()
1297     colors = ['red', 'green', 'blue', 'purple', 'orange', 'black', 'brown', 'gray', 'pink', 'yellow', 'cyan', 'magenta']
1298     for x_colors in range(int(len(x_axle_n1) / 4)):
1299         # print(0+x_colors*4, 1+x_colors*4, 2+x_colors*4,3+x_colors*4)
1300         x_colors_a = 0 + x_colors * 4
1301         x_colors_b = 1 + x_colors * 4
1302         x_colors_c = 2 + x_colors * 4
1303         x_colors_d = 3 + x_colors * 4
1304         xtick_labels[x_colors_a].set_color('red')
1305         xtick_labels[x_colors_b].set_color('blue')
1306         xtick_labels[x_colors_c].set_color('orange')
1307         xtick_labels[x_colors_d].set_color('magenta')
1308 
1309     # -------------------------------------------------------------------------------------- #
1310 
1311     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
1312     ax2 = ax1.twinx()
1313 
1314     # 图例文件描述-动态变化
1315     title_up = "本月测试  " + z_name_km1 + "  分布"
1316     legend_x3 = "input"
1317     legend_x4 = "output"
1318     legend_y3 = "yield"
1319     legend_y4 = "limit"
1320 
1321     # ====================================================================================================================#
1322     # 绘制柱状图
1323     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
1324     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
1325     bar3 = ax1.bar(bar_1_x, y_total_t1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
1326     bar4 = ax1.bar(bar_2_x, y_total_t2, label=legend_x4, color='gold', width=bar_width, linewidth=0.2, edgecolor="white")
1327     # 绘制柱描述
1328     for a, b, c in zip(bar_1_x, y_total_t1, y_total_t2):
1329         ax1.text(a - 0.1, b, '%d' % b, ha='center', va='bottom', fontsize=8, font=font, )
1330         ax1.text(a + 0.3, c, '%d' % c, ha='center', va='bottom', fontsize=8, font=font, )
1331 
1332     #
1333     # 绘制折线图
1334     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
1335     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
1336     line3 = ax2.plot(x_axle_n1, y_yield_t1, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
1337     line4 = ax2.plot(x_axle_n1, y_yield_t2, label=legend_y4, color='red', marker='.', markersize='6', ls='-')
1338 
1339     # 折线图点描述
1340     for a_x1, b_y3, c_y4 in zip(x_axle_n1, y_yield_t1, y_yield_t2):
1341         if b_y3 < c_y4:
1342             print("# 低于卡控线: ", a_x1, file=run_log)
1343             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=12, font=font)
1344         else:
1345             # print("# 正常模组: ", a_x1)
1346             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=8, font=font)
1347             ax2.text(1, c_y4, '{:.2f}%'.format(c_y4 * 100), ha='center', va='bottom', fontsize=11, font=font)  # 只显示一个
1348 
1349     # ====================================================================================================================#
1350 
1351     # 设置x轴和y轴的标签,指明坐标含义
1352     ax1.set_xlabel(z_name_km1, fontdict={'size': 16})
1353     # 左边-y轴为:数量模式
1354     ax1.set_ylabel('模组数量', fontdict={'size': 16})
1355     # 右边-y轴为:百分比形式
1356     ax2.set_ylabel('百分比', fontdict={'size': 16})
1357 
1358     # 左-y轴为:刻度范围,动态调整
1359     max_value_r1 = int(max(y_total_t1) * 1.3)
1360     min_value_r1 = int(min(y_total_t2) * 0.9)
1361     if max_value_r1 < 5:
1362         max_value_r1 = 10  # 直接赋值
1363         min_value_r1 = 0  # 直接赋值
1364     ax1.set_ylim(min_value_r1, max_value_r1)
1365     #  右边-y轴为:最大值为100%,小数点2位
1366     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
1367 
1368     # 设置x轴和y轴刻度字体
1369     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
1370     [label.set_fontname('SimHei') for label in labels2]
1371 
1372     # 添加图表题  plt.title('双y轴折线图')
1373     plt.title(title_up, color="red", fontsize=16)
1374 
1375     # 设置轴标签颜色
1376     # ax1.tick_params('x', colors='Black')
1377     ax1.tick_params('y', colors='royalblue')
1378     ax2.tick_params('y', colors='tomato')
1379 
1380     # 设置轴颜色
1381     ax1.spines['left'].set_color('royalblue')
1382     ax2.spines['left'].set_color('royalblue')
1383     ax1.spines['right'].set_color('tomato')
1384     ax2.spines['right'].set_color('tomato')
1385 
1386     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
1387     ax1.spines['top'].set_visible(False)
1388     ax2.spines['top'].set_visible(False)
1389 
1390     # 添加图例函数:  plt.legend()
1391     # 添加图例 - 添加方向改为以下代码
1392     ax1.legend(loc='upper left')
1393     ax2.legend(loc='upper right')
1394     # 添加图例 - 将`图例合并改为以下代码
1395     # lines = line1 + line2 + line3 + line4
1396     # lines = line3 + line4
1397     # labels = [h.get_label() for h in lines]
1398     # plt.legend(lines, labels, loc='upper right')
1399 
1400     # 设置中文显示
1401     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
1402     plt.rcParams['axes.unicode_minus'] = False
1403 
1404     # 虚拟背景线
1405     plt.grid(True, linestyle="--")
1406 
1407     # 展示图片
1408     # plt.show()
1409     # 显示柱状图时间,单位s
1410     time_v1 = 1
1411     while time_v1 != 0:
1412         print('显示倒计时:%d s' % time_v1)
1413         plt.pause(1)
1414         time_v1 = time_v1 - 1
1415     print('直方图显示完成')
1416 
1417     # 图片保存对应文件
1418     picture_m = './4_result_ft/picture/' + z_name_km1 + r".jpg"
1419     plt.savefig(picture_m)
1420     plt.draw()
1421     print('图片保存对应文件-完成')
1422     plt.close()  # 关闭图表显示
1423 
1424 
1425 '''
1426 # ====================================================================================================================#
1427 # 本月测试BIN数据 显示所有头文件名称
1428 # ====================================================================================================================#
1429 '''
1430 
1431 
1432 def display_all_header_file_names(x_p1, z_p1, z_p2):
1433     # 指定月份 - 归类前文件
1434     marking_nb = x_p1
1435     single_month_data = z_p1
1436     all_month_raw_data = z_p2
1437     c_g_name1, c_g_data1 = get_data_bin_v2(marking_nb, single_month_data, all_month_raw_data)
1438     print("指定文件名称:", c_g_name1, c_g_data1)
1439 
1440 
1441 '''
1442 # ====================================================================================================================#
1443 # 本月-良品BIN1-测试数据汇总分布-通用模板1数据处理
1444 # ====================================================================================================================#
1445 '''
1446 
1447 
1448 def defective_reorder_sub(x_p1, x_p2, x_p3, z_p1, z_p2, z_p3, z_p4):
1449     # ---------------------------------------------------------------------------------------------------------------- #
1450     # 开始计时
1451     datetime_object_11 = datetime.datetime.now()
1452     print("datetime_object_11 :", datetime_object_11)
1453 
1454     # 使用无表头,使用数字强制索引 -- 第一份引用
1455     x_handler_n2 = x_p2
1456     x_lot_n3 = x_p3
1457     month_n2 = z_p2
1458     single_month_d2 = z_p3
1459     raw_data_a2 = z_p4
1460 
1461     # ---------------------------------------------------------------------------------------------------------------------- #
1462     # 处理1 数据归类
1463     print('指定月份 - 归类前文件: 月份< %d >' % month_n2, z_p1)
1464 
1465     # 指定月份 - 归类前文件
1466     c_g_name1, c_g_data1 = get_data_bin_v2(x_lot_n3, single_month_d2, raw_data_a2)
1467     c_g_name2, c_g_data2 = get_data_bin_v2(x_handler_n2, single_month_d2, raw_data_a2)
1468     # print("源1:", c_g_name1, c_g_data1)
1469     # print("源2:", c_g_name2, c_g_data2)
1470 
1471     # ---------------------------------------------------------------------------------------------------------------- #
1472     lot_list_v1 = []
1473     lot_list_v3 = []
1474     for index_a in range(len(c_g_data1)):
1475         num_v1_lot = single_month_d2[index_a]  # 获取本月行号 索引值
1476         str_v1_lot = c_g_data1[index_a][0:6]  # 正则表达获取lot ,去除wafer
1477         lot_handler_t1 = c_g_data2[index_a]  # 获取附属信息 handler
1478         lot_list_v2 = [num_v1_lot, str_v1_lot, lot_handler_t1]  # 3个关键字存储到一维列表中
1479         lot_list_v1.append(lot_list_v2)  # 存储到一维列表到二维列表中
1480         lot_list_v3.append(str_v1_lot)  # 1个关键字存储到一维列表中
1481     # all raw data 有效映射
1482     # print('all data -- 切片lot  : ', len(lot_list_v1), lot_list_v1)
1483 
1484     # 获取同一列表中相同元素,只保留一种类型
1485     one_lot = []
1486     for v2_lot in lot_list_v3:
1487         if v2_lot not in one_lot:
1488             one_lot.append(v2_lot)
1489     print('lot中唯一代表名称: ', one_lot)
1490 
1491     # 先按照 lot 分类 再按照 handler分类 最后索引-行号
1492     lot_handler_m1 = []  # 重新分类聚合的列表
1493     lot_h1_m1 = []
1494     lot_h1_m2 = []
1495     # 先按照 lot 大类分组
1496     for row_v1_w1 in one_lot:
1497         # print('每种类型的lot: ',row_v1_w1)
1498         line_re_lot5 = []
1499 
1500         for row_v1 in lot_list_v1:
1501             # print('切片lot中第1个元素-二维列中每行第1个元素: ',row_v1[1])
1502             if row_v1_w1 == row_v1[1]:
1503                 # print('打印相同的元素名称: ',row_v1_w1,row_v1[0],row_v1[1])
1504                 line_re_lot4 = [row_v1[0], row_v1[1], row_v1[2]]  # 按照每个lot大类重新组合索引值
1505                 line_re_lot5.append(line_re_lot4)
1506                 lot_h1_m1.append(row_v1[0])
1507                 lot_h1_m2.append(line_re_lot4)
1508         # print('每个lot大类-组合: ',line_re_lot5)
1509 
1510         # 每个lot类 再按照 handler 重新分类
1511         re_handler_1 = []
1512         re_handler_2 = []
1513         re_handler_3 = []
1514         re_handler_4 = []
1515         re_handler_x = []
1516         handler_name_d = ["handler0 名称:", "HIP-01", "HIP-02", "HIP-03", "HIP-04", ]  # TODO g根据机台重新添加
1517         for two_m1 in line_re_lot5:
1518             # print('每个lot中 handler元素组合:',two_m1,two_m1[2])
1519             if handler_name_d[1] == two_m1[2]:
1520                 # print('具体handler匹配: ',handler_name_d[1],two_m1[2])
1521                 re_handler_1.append(two_m1[0])  # handler1
1522             elif handler_name_d[2] == two_m1[2]:
1523                 re_handler_2.append(two_m1[0])  # handler2
1524             elif handler_name_d[3] == two_m1[2]:
1525                 re_handler_3.append(two_m1[0])  # handler3
1526             elif handler_name_d[4] == two_m1[2]:
1527                 re_handler_4.append(two_m1[0])  # handler4
1528             else:
1529                 re_handler_x.append(two_m1[0])  # handler x 未知分类
1530 
1531         # 一维列表合并
1532         re_handler_m = re_handler_1 + re_handler_2 + re_handler_3 + re_handler_4 + re_handler_x
1533         # print("按照handler 子归类:", re_handler_m)
1534         lot_handler_m1.append(re_handler_m)  # 一维列表组合成二维列表
1535     # ---------------------------------------------------------------------------------------------------------------- #
1536     # 显示分组情况
1537     # 第1种情况
1538     # print('仅按照大类lot分组:',len(lot_h1_m2),lot_h1_m2)
1539     # print('仅按照大类lot分组-索引行号:', len(lot_h1_m1), lot_h1_m1)
1540 
1541     # 第2种情况
1542     # print("lot_handler_ 分组二维列表:", len(lot_handler_m1), lot_handler_m1)
1543     # 二维列表转一维列表 非常重要
1544     lot_handler_m1_result = [n for a in lot_handler_m1 for n in a]
1545     print('最终结果 -- lot_handler_m1_result: ', lot_handler_m1_result)
1546 
1547     # # 第3种情况 - 仅仅按照handler分类  顺序重新归类
1548     # reclassify_1 = []
1549     # reclassify_2 = []
1550     # reclassify_3 = []
1551     # reclassify_4 = []
1552     # reclassify_x = []
1553     # handler_name = ["handler0 名称:", "HIP-01", "HIP-02", "HIP-03", "HIP-04", ]
1554     # for two_m1 in range(len(single_month_m12[month_h1])):
1555     #     # print('按照handler 分组',single_month_m12[month_h1][two_m1])
1556     #     if handler_name[1] == c_g_data2[two_m1]:
1557     #         reclassify_1.append(single_month_m12[month_h1][two_m1])     # handler1
1558     #     elif handler_name[2] == c_g_data2[two_m1]:
1559     #         reclassify_2.append(single_month_m12[month_h1][two_m1])     # handler2
1560     #     elif handler_name[3] == c_g_data2[two_m1]:
1561     #         reclassify_3.append(single_month_m12[month_h1][two_m1])     # handler3
1562     #     elif handler_name[4] == c_g_data2[two_m1]:
1563     #         reclassify_4.append(single_month_m12[month_h1][two_m1])     # handler4
1564     #     else:
1565     #         reclassify_x.append(single_month_m12[month_h1][two_m1])     # handler x
1566     # handler_merged_result3 = reclassify_1 + reclassify_2 + reclassify_3 + reclassify_4 + reclassify_x
1567     # print("按照handler 重新归类 索引值: ",handler_merged_result3)
1568 
1569     # 用目标值 替换源列表中 行分组
1570     single_month_d2 = lot_handler_m1_result
1571     # single_month_m12[month_h1] = handler_merged_result3
1572     # 显示新月份所有的月度索引值-行号
1573     # for index_a in range(1, 13):
1574     #     print('第%d月数据' % (index_a), single_month_m12[index_a])
1575     # 新索引值重新被引用
1576     index_s_m2 = single_month_d2
1577 
1578     datetime_object_12 = datetime.datetime.now()
1579     print("datetime_object_12 :", datetime_object_12, ' 耗时:', (datetime_object_12 - datetime_object_11))
1580 
1581     # ---------------------------------------------------------------------------------------------------------------------- #
1582     return index_s_m2
1583 
1584 
1585 '''
1586 # ====================================================================================================================#
1587 # 本月 --- 不良品BIN --- 测试数据汇总分布-通用模板2数据处理
1588 # ====================================================================================================================#
1589 '''
1590 
1591 
1592 def defective_handle_v2(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
1593     print("#**** handle_v2_pro ****# >>> ", z_p1)
1594     # 按照 仅handler-marking 分类
1595     # 按照 仅lot-marking 分类
1596     # 按照 lot - handler - marking 分类
1597     single_month_z2 = defective_reorder_sub(x_p1, x_p2, x_p3, z_p1, z_p2, z_p3, z_p4)
1598     # 按照 handler - lot - marking 分类
1599     # 按照 summary表-marking 顺序
1600 
1601     # 重新赋值 -single month raw data index
1602     x_axle_n1 = x_p1
1603     x_axle_n2 = x_p2
1604     x_axle_n3 = x_p3
1605     y_total_t1 = y_p1
1606     y_total_t2 = y_p2
1607     y_yield_t1 = y_p3
1608     y_yield_t2 = y_p4
1609     bin_name = z_p1
1610     month_n1 = z_p2
1611     single_month_d1 = single_month_z2
1612     raw_data_a1 = z_p4
1613     print('绘图处理: 月份< %d >  不良品< %s >' % (month_n1, bin_name))
1614     # 获取每月函数 有效数据 x_axle_n2
1615     x_name1, x_data1 = get_data_bin_v2(x_axle_n1, single_month_d1, raw_data_a1)
1616     x_name2, x_data2 = get_data_bin_v2(x_axle_n2, single_month_d1, raw_data_a1)
1617     x_name3, x_data3 = get_data_bin_v2(x_axle_n3, single_month_d1, raw_data_a1)
1618     y_name1, y_data1 = get_data_bin_v2(y_total_t1, single_month_d1, raw_data_a1)
1619     y_name2, y_data2 = get_data_bin_v2(y_total_t2, single_month_d1, raw_data_a1)
1620     y_name3, y_data3 = get_data_bin_v2(y_yield_t1, single_month_d1, raw_data_a1)
1621     y_name4, y_data4 = get_data_bin_v2(y_yield_t2, single_month_d1, raw_data_a1)
1622     # print(x_name1, x_data1)
1623     # print(x_name2, x_data2)
1624     # print(y_name1, y_data1)
1625     # print(y_name2, y_data2)
1626     # print(y_name3, y_data3)
1627 
1628     # ======================================================================================== #
1629 
1630     # 整体参数配置
1631     font = FontProperties(size=10)
1632     plt.rcParams["font.sans-serif"] = ['SimHei']
1633     plt.rcParams['axes.unicode_minus'] = False
1634     plt.rcParams['font.family'] = ['SimHei']
1635     plt.rcParams['font.sans-serif'] = ['SimHei']
1636     plt.rcParams['figure.figsize'] = (30, 10)
1637     plt.rc('font', family='SimHei', size=8)
1638 
1639     # 创建一个图形和两个y轴
1640     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
1641 
1642     # 柱状图柱子宽度
1643     bar_width = 0.4
1644     x_ticks = range(len(x_data1))  # x轴刻度位置 | 折线图x位置
1645     bar_1_x = [(ii - bar_width + 0.2) for ii in x_ticks]  # 柱状图1 - x位置
1646     bar_2_x = [(ww - bar_width + 0.6) for ww in x_ticks]
1647 
1648     # 设置x轴刻度字体以及方向-单刻度标签
1649     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
1650     [label.set_fontname('SimHei') for label in labels1]
1651     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
1652 
1653     # 设置x轴刻度字体以及方向- 叠加双刻度标签
1654     labels = []
1655     for two_m1 in range(len(x_data1)):
1656         cell_m2 = x_data3[two_m1][0:6] + '   ' + x_data2[two_m1] + '   ' + x_data1[two_m1]
1657         labels.append(cell_m2)
1658     # labels = x_ticks  # 默认
1659     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
1660     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
1661     # 自适应调整布局+ 指定 解决X轴范围问题
1662     fig.autofmt_xdate(rotation=90)
1663 
1664     # -------------------------------------------------------------------------------------- #
1665     # # 同一刻度标签标记为不同颜色 插孔法  升级-适用较为复杂的场景  第2种方案
1666     index_lot_v5 = []
1667     for index_a in range(len(single_month_d1)):
1668         index_lot = single_month_d1[index_a]  # 获取本月行号 索引值
1669         index_m1 = x_data3[index_a][0:6]  # 获取本月行号 索引值
1670         index_lot_v5.append(index_m1)
1671     # all raw data 有效映射
1672     # print("all raw data 有效映射:", index_lot_v5)
1673     # 获取同一列表中相同元素,只保留一种类型
1674     one_lot_v1 = []
1675     for v2_lot in index_lot_v5:
1676         if v2_lot not in one_lot_v1:
1677             one_lot_v1.append(v2_lot)
1678     # print('lot中唯一代表名称: ', one_lot_v1)
1679     xtick_labels = ax1.get_xticklabels()
1680     colors = ['red', 'green', 'blue', 'purple', 'orange', 'brown', 'gray', 'pink', 'cyan', 'magenta', 'yellow', 'black', ]
1681     # 利用唯一lot去适配列表lot,影射到对应刻度,根据余数去自动识别颜色,默认10种
1682     for x_color in range(len(x_data3)):
1683         # print("x_color: ",x_color,x_data3[x_color][0:6])
1684         for one_c1 in range(len(one_lot_v1)):
1685             # print("Index:", one_c1, "Value:", one_lot_v1[one_c1])
1686             if one_lot_v1[one_c1] == x_data3[x_color][0:6]:
1687                 one_color_v1 = one_c1 % 10
1688                 if one_color_v1 == 0:
1689                     xtick_labels[x_color].set_color(colors[0])
1690                 elif one_color_v1 == 1:
1691                     xtick_labels[x_color].set_color(colors[1])
1692                 elif one_color_v1 == 2:
1693                     xtick_labels[x_color].set_color(colors[2])
1694                 elif one_color_v1 == 3:
1695                     xtick_labels[x_color].set_color(colors[3])
1696                 elif one_color_v1 == 4:
1697                     xtick_labels[x_color].set_color(colors[4])
1698                 elif one_color_v1 == 5:
1699                     xtick_labels[x_color].set_color(colors[5])
1700                 elif one_color_v1 == 6:
1701                     xtick_labels[x_color].set_color(colors[6])
1702                 elif one_color_v1 == 7:
1703                     xtick_labels[x_color].set_color(colors[7])
1704                 elif one_color_v1 == 8:
1705                     xtick_labels[x_color].set_color(colors[8])
1706                 elif one_color_v1 == 9:
1707                     xtick_labels[x_color].set_color(colors[9])
1708         # -------------------------------------------------------------------------------------- #
1709 
1710     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
1711     ax2 = ax1.twinx()
1712 
1713     # 图例文件描述-动态变化
1714     title_up = "本月测试  " + bin_name + "  分布"
1715     legend_x3 = y_name1
1716     legend_x4 = y_name2
1717     legend_y3 = y_name3
1718     legend_y4 = y_name4
1719 
1720     # ====================================================================================================================#
1721     # 绘制柱状图
1722     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
1723     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
1724     bar3 = ax1.bar(bar_1_x, y_data1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
1725     bar4 = ax1.bar(bar_2_x, y_data2, label=legend_x4, color='gold', width=bar_width, linewidth=0.2, edgecolor="white")
1726 
1727     # 绘制折线图
1728     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
1729     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
1730     line3 = ax2.plot(x_data1, y_data3, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
1731     line4 = ax2.plot(x_data1, y_data4, label=legend_y4, color='royalblue', marker='.', markersize='6', ls='-')
1732 
1733     # ------------------------------------------------------------------------------------------------------------------- #
1734     # #TODO  <特殊情况处理 -20231211>
1735     # ------------------------------------------------------------------------------------------------------------------- #
1736     legend_y5 = "sbl"  # 新增sbl 卡控图例名称
1737 
1738     if bin_name == "BIN3":
1739         y_data5 = []
1740         sbl_data = 0.003
1741         for sbl_avocado in range(len(y_data4)):
1742             y_data5.append(sbl_data)
1743         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1744         # 折线图点描述
1745         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1746             if b_y3 < b_y4:
1747                 print("# BIN3 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1748                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1749             if b_y4 > c_y5:
1750                 print("# BIN3 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1751                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1752             # 只显示一个 sbl
1753             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1754 
1755     elif bin_name == "BIN4":
1756         y_data5 = []
1757         sbl_data = 0.0001
1758         for sbl_avocado in range(len(y_data4)):
1759             y_data5.append(sbl_data)
1760         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1761         # 折线图点描述
1762         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1763             if b_y3 < b_y4:
1764                 print("# BIN4 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1765                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1766             if b_y4 > c_y5:
1767                 print("# BIN4 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1768                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1769             # 只显示一个 sbl
1770             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1771 
1772     elif bin_name == "BIN5":
1773         y_data5 = []
1774         sbl_data = 0.0193
1775         for sbl_avocado in range(len(y_data4)):
1776             y_data5.append(sbl_data)
1777         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1778         # 折线图点描述
1779         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1780             if b_y3 < b_y4:
1781                 print("# BIN5 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1782                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1783             if b_y4 > c_y5:
1784                 print("# BIN5 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1785                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1786             # 只显示一个 sbl
1787             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1788 
1789     elif bin_name == "BIN6_1":
1790         y_data5 = []
1791         sbl_data = 0.0204
1792         for sbl_avocado in range(len(y_data4)):
1793             y_data5.append(sbl_data)
1794         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1795         # 折线图点描述
1796         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1797             if b_y3 < b_y4:
1798                 print("# BIN6_1 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1799                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1800             if b_y4 > c_y5:
1801                 print("# BIN6_1 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1802                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1803             # 只显示一个 sbl
1804             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1805 
1806     elif bin_name == "BIN6_2":
1807         y_data5 = []
1808         sbl_data = 0.0193
1809         for sbl_avocado in range(len(y_data4)):
1810             y_data5.append(sbl_data)
1811         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1812         # 折线图点描述
1813         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1814             if b_y3 < b_y4:
1815                 print("# BIN6_2 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1816                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1817             if b_y4 > c_y5:
1818                 print("# BIN6_2 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1819                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1820             # 只显示一个 sbl
1821             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1822 
1823     elif bin_name == "BIN7_1":
1824         y_data5 = []
1825         sbl_data = 0.0100
1826         for sbl_avocado in range(len(y_data4)):
1827             y_data5.append(sbl_data)
1828         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1829         # 折线图点描述
1830         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1831             if b_y3 < b_y4:
1832                 print("# BIN7_1 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1833                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1834             if b_y4 > c_y5:
1835                 print("# BIN7_1 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1836                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1837             # 只显示一个 sbl
1838             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1839 
1840     elif bin_name == "BIN7_2":
1841         y_data5 = []
1842         sbl_data = 0.001
1843         for sbl_avocado in range(len(y_data4)):
1844             y_data5.append(sbl_data)
1845         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1846         # 折线图点描述
1847         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1848             if b_y3 < b_y4:
1849                 print("# BIN7_2 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1850                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1851             if b_y4 > c_y5:
1852                 print("# BIN7_2 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1853                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1854             # 只显示一个 sbl
1855             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1856 
1857     elif bin_name == "BIN7_3":
1858         y_data5 = []
1859         sbl_data = 0.0001
1860         for sbl_avocado in range(len(y_data4)):
1861             y_data5.append(sbl_data)
1862         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
1863         # 折线图点描述
1864         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
1865             if b_y3 < b_y4:
1866                 print("# BIN7_3 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log)
1867                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1868             if b_y4 > c_y5:
1869                 print("# BIN7_3 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log)
1870                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
1871             # 只显示一个 sbl
1872             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
1873     else:
1874         print("无符合case 的 bin")
1875     #
1876     # ====================================================================================================================#
1877 
1878     # 设置x轴和y轴的标签,指明坐标含义
1879     ax1.set_xlabel('lot ID', fontdict={'size': 16})
1880     # 左边-y轴为:数量模式
1881     ax1.set_ylabel('模组数量', fontdict={'size': 16})
1882     # 右边-y轴为:百分比形式
1883     ax2.set_ylabel('百分比', fontdict={'size': 16})
1884 
1885     # 左-y轴为:刻度范围,动态调整
1886     max_value_r1 = int(max(y_data1) * 1.3)
1887     min_value_r1 = int(min(y_data1) * 0.9)
1888     if max_value_r1 < 5:
1889         max_value_r1 = 10  # 直接赋值
1890         min_value_r1 = 0  # 直接赋值
1891     ax1.set_ylim(min_value_r1, max_value_r1)
1892     #  右边-y轴为:最大值为100%,小数点2位
1893     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
1894 
1895     # 设置x轴和y轴刻度字体
1896     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
1897     [label.set_fontname('SimHei') for label in labels2]
1898 
1899     # 添加图表题  plt.title('双y轴折线图')
1900     plt.title(title_up, color="red", fontsize=16)
1901 
1902     # 设置轴标签颜色
1903     # ax1.tick_params('x', colors='Black')
1904     ax1.tick_params('y', colors='royalblue')
1905     ax2.tick_params('y', colors='tomato')
1906 
1907     # 设置轴颜色
1908     ax1.spines['left'].set_color('royalblue')
1909     ax2.spines['left'].set_color('royalblue')
1910     ax1.spines['right'].set_color('tomato')
1911     ax2.spines['right'].set_color('tomato')
1912 
1913     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
1914     ax1.spines['top'].set_visible(False)
1915     ax2.spines['top'].set_visible(False)
1916 
1917     # 添加图例函数:  plt.legend()
1918     # 添加图例 - 添加方向改为以下代码
1919     ax1.legend(loc='upper left')
1920     ax2.legend(loc='upper right')
1921     # 添加图例 - 将`图例合并改为以下代码
1922     # lines = line1 + line2 + line3 + line4
1923     # lines = line3 + line4
1924     # labels = [h.get_label() for h in lines]
1925     # plt.legend(lines, labels, loc='upper right')
1926 
1927     # 设置中文显示
1928     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
1929     plt.rcParams['axes.unicode_minus'] = False
1930 
1931     # 虚拟背景线
1932     plt.grid(True, linestyle="--")
1933 
1934     # 展示图片
1935     # plt.show()
1936     # 显示柱状图时间,单位s
1937     time_v1 = 1
1938     while time_v1 != 0:
1939         print('显示倒计时:%d s' % time_v1)
1940         plt.pause(1)
1941         time_v1 = time_v1 - 1
1942     print('直方图显示完成')
1943 
1944     # 图片保存对应文件
1945     picture_m = './4_result_ft/picture/' + bin_name + r".jpg"
1946     plt.savefig(picture_m)
1947     plt.draw()
1948     print('图片保存对应文件-完成')
1949     plt.close()  # 关闭图表显示
1950 
1951 
1952 '''
1953 # ====================================================================================================================#
1954 # 本月 --- 不良品BIN --- 测试数据汇总分布-通用模板2_se数据处理
1955 # ====================================================================================================================#
1956 '''
1957 
1958 
1959 def defective_handle_v2_se(x_p1, x_p2, x_p3, y_p1, y_p3, z_p1, z_p2, z_p3, z_p4):
1960     print("#**** handle_v2_pro ****# >>> ", z_p1)
1961     # 按照 仅handler-marking 分类
1962     # 按照 仅lot-marking 分类
1963     # 按照 lot - handler - marking 分类
1964     single_month_z2 = defective_reorder_sub(x_p1, x_p2, x_p3, z_p1, z_p2, z_p3, z_p4)
1965     # 按照 handler - lot - marking 分类
1966     # 按照 summary表-marking 顺序
1967 
1968     # 重新赋值 -single month raw data index
1969     x_axle_n1 = x_p1
1970     x_axle_n2 = x_p2
1971     x_axle_n3 = x_p3
1972     y_total_t1 = y_p1
1973     y_yield_t1 = y_p3
1974     bin_name = z_p1
1975     month_n1 = z_p2
1976     single_month_d1 = single_month_z2
1977     raw_data_a1 = z_p4
1978     print('绘图处理: 月份< %d >  不良品< %s >' % (month_n1, bin_name))
1979     # 获取每月函数 有效数据 x_axle_n2
1980     x_name1, x_data1 = get_data_bin_v2(x_axle_n1, single_month_d1, raw_data_a1)
1981     x_name2, x_data2 = get_data_bin_v2(x_axle_n2, single_month_d1, raw_data_a1)
1982     x_name3, x_data3 = get_data_bin_v2(x_axle_n3, single_month_d1, raw_data_a1)
1983     y_name1, y_data1 = get_data_bin_v2(y_total_t1, single_month_d1, raw_data_a1)
1984     y_name3, y_data3 = get_data_bin_v2(y_yield_t1, single_month_d1, raw_data_a1)
1985     # print(x_name1, x_data1)
1986     # print(x_name2, x_data2)
1987     # print(y_name1, y_data1)
1988     # print(y_name2, y_data2)
1989     # print(y_name3, y_data3)
1990 
1991     # ======================================================================================== #
1992 
1993     # 整体参数配置
1994     font = FontProperties(size=10)
1995     plt.rcParams["font.sans-serif"] = ['SimHei']
1996     plt.rcParams['axes.unicode_minus'] = False
1997     plt.rcParams['font.family'] = ['SimHei']
1998     plt.rcParams['font.sans-serif'] = ['SimHei']
1999     plt.rcParams['figure.figsize'] = (30, 10)
2000     plt.rc('font', family='SimHei', size=8)
2001 
2002     # 创建一个图形和两个y轴
2003     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
2004 
2005     # 柱状图柱子宽度
2006     bar_width = 0.4
2007     x_ticks = range(len(x_data1))  # x轴刻度位置 | 折线图x位置
2008     bar_1_x = [(ii - bar_width + 0.2) for ii in x_ticks]  # 柱状图1 - x位置
2009     bar_2_x = [(ww - bar_width + 0.6) for ww in x_ticks]
2010 
2011     # 设置x轴刻度字体以及方向-单刻度标签
2012     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
2013     [label.set_fontname('SimHei') for label in labels1]
2014     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
2015 
2016     # 设置x轴刻度字体以及方向- 叠加双刻度标签
2017     labels = []
2018     for two_m1 in range(len(x_data1)):
2019         cell_m2 = x_data3[two_m1][0:6] + '   ' + x_data2[two_m1] + '   ' + x_data1[two_m1]
2020         labels.append(cell_m2)
2021     # labels = x_ticks  # 默认
2022     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
2023     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
2024     # 自适应调整布局+ 指定 解决X轴范围问题
2025     fig.autofmt_xdate(rotation=90)
2026 
2027     # -------------------------------------------------------------------------------------- #
2028     # # 同一刻度标签标记为不同颜色 插孔法  升级-适用较为复杂的场景  第2种方案
2029     index_lot_v5 = []
2030     for index_a in range(len(single_month_d1)):
2031         index_lot = single_month_d1[index_a]  # 获取本月行号 索引值
2032         index_m1 = x_data3[index_a][0:6]  # 获取本月行号 索引值
2033         index_lot_v5.append(index_m1)
2034     # all raw data 有效映射
2035     print("all raw data 有效映射:", index_lot_v5)
2036     # 获取同一列表中相同元素,只保留一种类型
2037     one_lot_v1 = []
2038     for v2_lot in index_lot_v5:
2039         if v2_lot not in one_lot_v1:
2040             one_lot_v1.append(v2_lot)
2041     print('lot中唯一代表名称: ', one_lot_v1)
2042     xtick_labels = ax1.get_xticklabels()
2043     colors = ['red', 'green', 'blue', 'purple', 'orange', 'brown', 'gray', 'pink', 'cyan', 'magenta', 'yellow', 'black', ]
2044     # 利用唯一lot去适配列表lot,影射到对应刻度,根据余数去自动识别颜色,默认10种
2045     for x_color in range(len(x_data3)):
2046         # print("x_color: ",x_color,x_data3[x_color][0:6])
2047         for one_c1 in range(len(one_lot_v1)):
2048             # print("Index:", one_c1, "Value:", one_lot_v1[one_c1])
2049             if one_lot_v1[one_c1] == x_data3[x_color][0:6]:
2050                 one_color_v1 = one_c1 % 10
2051                 if one_color_v1 == 0:
2052                     xtick_labels[x_color].set_color(colors[0])
2053                 elif one_color_v1 == 1:
2054                     xtick_labels[x_color].set_color(colors[1])
2055                 elif one_color_v1 == 2:
2056                     xtick_labels[x_color].set_color(colors[2])
2057                 elif one_color_v1 == 3:
2058                     xtick_labels[x_color].set_color(colors[3])
2059                 elif one_color_v1 == 4:
2060                     xtick_labels[x_color].set_color(colors[4])
2061                 elif one_color_v1 == 5:
2062                     xtick_labels[x_color].set_color(colors[5])
2063                 elif one_color_v1 == 6:
2064                     xtick_labels[x_color].set_color(colors[6])
2065                 elif one_color_v1 == 7:
2066                     xtick_labels[x_color].set_color(colors[7])
2067                 elif one_color_v1 == 8:
2068                     xtick_labels[x_color].set_color(colors[8])
2069                 elif one_color_v1 == 9:
2070                     xtick_labels[x_color].set_color(colors[9])
2071         # -------------------------------------------------------------------------------------- #
2072 
2073     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
2074     ax2 = ax1.twinx()
2075 
2076     # 图例文件描述-动态变化
2077     title_up = "本月测试  " + bin_name + "  分布"
2078     legend_x3 = y_name1
2079     legend_y3 = y_name3
2080 
2081     # ====================================================================================================================#
2082     # 绘制柱状图
2083     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
2084     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
2085     bar3 = ax1.bar(bar_1_x, y_data1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
2086 
2087     # 绘制折线图
2088     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
2089     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
2090     line3 = ax2.plot(x_data1, y_data3, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
2091 
2092     # ------------------------------------------------------------------------------------------------------------------- #
2093     # 折线图点描述
2094     for a_x1, b_y3 in zip(x_data1, y_data3):
2095         if b_y3 > 0:
2096             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=9, font=font)
2097 
2098     # ====================================================================================================================#
2099 
2100     # 设置x轴和y轴的标签,指明坐标含义
2101     ax1.set_xlabel('lot ID', fontdict={'size': 16})
2102     # 左边-y轴为:数量模式
2103     ax1.set_ylabel('模组数量', fontdict={'size': 16})
2104     # 右边-y轴为:百分比形式
2105     ax2.set_ylabel('百分比', fontdict={'size': 16})
2106 
2107     # 左-y轴为:刻度范围,动态调整
2108     max_value_r1 = int(max(y_data1) * 1.3)
2109     min_value_r1 = int(min(y_data1) * 0.9)
2110     if max_value_r1 < 5:
2111         max_value_r1 = 10  # 直接赋值
2112         min_value_r1 = 0  # 直接赋值
2113     ax1.set_ylim(min_value_r1, max_value_r1)
2114     #  右边-y轴为:最大值为100%,小数点2位
2115     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
2116 
2117     # 设置x轴和y轴刻度字体
2118     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
2119     [label.set_fontname('SimHei') for label in labels2]
2120 
2121     # 添加图表题  plt.title('双y轴折线图')
2122     plt.title(title_up, color="red", fontsize=16)
2123 
2124     # 设置轴标签颜色
2125     # ax1.tick_params('x', colors='Black')
2126     ax1.tick_params('y', colors='royalblue')
2127     ax2.tick_params('y', colors='tomato')
2128 
2129     # 设置轴颜色
2130     ax1.spines['left'].set_color('royalblue')
2131     ax2.spines['left'].set_color('royalblue')
2132     ax1.spines['right'].set_color('tomato')
2133     ax2.spines['right'].set_color('tomato')
2134 
2135     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
2136     ax1.spines['top'].set_visible(False)
2137     ax2.spines['top'].set_visible(False)
2138 
2139     # 添加图例函数:  plt.legend()
2140     # 添加图例 - 添加方向改为以下代码
2141     ax1.legend(loc='upper left')
2142     ax2.legend(loc='upper right')
2143     # 添加图例 - 将`图例合并改为以下代码
2144     # lines = line1 + line2 + line3 + line4
2145     # lines = line3 + line4
2146     # labels = [h.get_label() for h in lines]
2147     # plt.legend(lines, labels, loc='upper right')
2148 
2149     # 设置中文显示
2150     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
2151     plt.rcParams['axes.unicode_minus'] = False
2152 
2153     # 虚拟背景线
2154     plt.grid(True, linestyle="--")
2155 
2156     # 展示图片
2157     # plt.show()
2158     # 显示柱状图时间,单位s
2159     time_v1 = 1
2160     while time_v1 != 0:
2161         print('显示倒计时:%d s' % time_v1)
2162         plt.pause(1)
2163         time_v1 = time_v1 - 1
2164     print('直方图显示完成')
2165 
2166     # 图片保存对应文件
2167     picture_m = './4_result_ft/picture/' + bin_name + r".jpg"
2168     plt.savefig(picture_m)
2169     plt.draw()
2170     print('图片保存对应文件-完成')
2171     plt.close()  # 关闭图表显示
2172 
2173 
2174 '''
2175 # ====================================================================================================================#
2176 # 本月 --- 不良品BIN --- 索引处理分类
2177 # ====================================================================================================================#
2178 '''
2179 
2180 
2181 def index_processing_c1():
2182     print("#**** index_processing_c1 ****#")
2183 
2184 
2185 '''
2186 #---------------------------------------------------------------------------------------------------------------#
2187 #  vi5300_ft_wc_handle_v1
2188 #---------------------------------------------------------------------------------------------------------------#
2189 '''
2190 
2191 
2192 def vi5300_ft_wc_handle_v1(all_data):
2193     # global list_month_v12_n
2194     print('进入函数>>>: vi5300_ft_wc_handle_v1 ...')
2195     datetime_object_s = datetime.datetime.now()
2196     print("datetime_object_s :", datetime_object_s)
2197 
2198     # print('全部数据显示: ',pd.DataFrame(all_data))   # 全部数据显示
2199     # print(pd.DataFrame(all_data,columns=[0]))   # HANDLER  测试日期
2200     all_raw_data = all_data  # raw data 另外保存
2201     data_columns_C0 = pd.DataFrame(all_data, columns=[0])  # 第0列:测试日期
2202     print("summary number:", len(data_columns_C0))
2203     print("分类存储到不同列表")
2204 
2205     datetime_object_1 = datetime.datetime.now()
2206     # print("datetime_object_1 :", datetime_object_1)
2207     for index_a in range(1, len(data_columns_C0)):  # 第0列:测试日期需要去除
2208         str_v1_name = str(data_columns_C0.values[index_a])
2209 
2210         # TODO 关闭 年 索引
2211         # str_v1_year = str_v1_name[2:6]
2212         str_v1_month = str_v1_name[7:9]
2213         # TODO 关闭 天 索引
2214         # str_v1_day = str_v1_name[10:12]
2215 
2216         # 提取年月日
2217         # print("序号:", index_a, '强制转换: ', str_v1_name)
2218         # print('year:  ', str_v1_name[2:6])
2219         # print('month: ', str_v1_name[7:9])
2220         # print('day:   ',  str_v1_name[10:12])
2221 
2222         # TODO 按年-当前省略,后续添加分类
2223         list_month_v12_n = monthly_class_handle_v12(str_v1_month, index_a)
2224     #
2225     # print('显示汇总后每月分类:',list_month_v12_n)
2226     datetime_object_2 = datetime.datetime.now()
2227     print("datetime_object_2 :", datetime_object_2, '耗时:', (datetime_object_2 - datetime_object_1))
2228 
2229     # # # TODO 统计本年度 按月索引数据-汇总数据
2230     # print("统计本年度 按月索引数据-汇总数据")  # 起始位=1
2231     # for index_a in range(1, 13):
2232     #     print('第%d月数据' % index_a, list_month_v12_n[index_a])
2233 
2234     # 单一月份数据汇总处理
2235     # print("传入1: ", list_month_v12_n)
2236 
2237     # ---------------------------------------------------------------------------------------------------------------- #
2238     print("*** 请输入查询VI5300-FT 伟测月份 ***")
2239     month_in = input()
2240     # month_input1 = 11
2241     month_input1 = int(month_in)
2242     print("传入月份长度:", len(list_month_v12_n[month_input1]))
2243     # 根据raw data 数据生成结果图片和异常数据
2244     single_month_summary_v1(list_month_v12_n, all_raw_data)
2245     # 根据结果图片生成 html 报告
2246     generate_report_summary(month_input1)
2247 
2248 
2249 '''
2250 #---------------------------------------------------------------------------------------------------------------#
2251 #  get_all_files_in_the_folder  备用:获取这个目录下所有文件的名字
2252 #---------------------------------------------------------------------------------------------------------------#
2253 '''
2254 
2255 
2256 def get_all_files_in_the_folder():
2257     # 在对文件进行操作时,某些时候需要获取当前文件夹下所有文件的文件名,如获取这个目录下所有文件的名字
2258     # path定义要获取的文件名称的目录
2259     input_path1 = r'./3_summary_ft'
2260     # os.listdir()方法获取文件夹名字,返回数组
2261     file_name_list = os.listdir(input_path1)
2262     print(file_name_list)
2263     # 转为转为字符串
2264     file_name = str(file_name_list)
2265     # replace替换"["、"]"、" "、"'"
2266     file_name = file_name.replace("[", "").replace("]", "").replace("'", "").replace(",", "\n").replace(" ", "")
2267     # 创建并打开文件list.txt
2268     f = open(input_path1 + "\\" + "文件list.txt", "a")
2269     # 将文件下名称写入到"文件list.txt"
2270     f.write(file_name)
2271 
2272 
2273 '''
2274 # =================================================================================================================================================#
2275 #  上方为vi5300-ft-wc
2276 #  ---------------------------------------- 分割线--------------------------------------------------------------------------------------------------#
2277 #  下方为vi5300-ft-wc
2278 # =================================================================================================================================================#
2279 '''
2280 
2281 '''
2282 #---------------------------------------------------------------------------------------------------------------#
2283 #  read_excel
2284 #---------------------------------------------------------------------------------------------------------------#
2285 '''
2286 
2287 
2288 def read_excel_xx(path_s1):
2289     # current_directory = os.path.dirname(os.path.abspath(__file__))
2290     # print("获取当前绝对路径:",current_directory)
2291     input_path_s1 = path_s1
2292     # input_path_s1 = r'./3_summary_ft'   # path定义要获取的文件名称的目录
2293     file_name_list = os.listdir(input_path_s1)  # os.listdir()方法获取文件夹名字,返回数组
2294     print("获取文件夹列表:\n", file_name_list)
2295 
2296     # 拼接路径 -- 仅仅获取第一个
2297     input_path_s2 = input_path_s1 + '\\' + file_name_list[0]
2298 
2299     # print("pandas 版本: ",  pd.__version__)
2300     # 读取一张Sheet  要读取的工作表可以由参数 sheet_name 指定。通过以 0 开头的数字或工作表名称指定。
2301     work_pd1 = pd.read_excel(io=input_path_s2, sheet_name=0, header=None)  #
2302     pd.set_option('display.max_columns', None)  # 显示完整的行
2303     pd.set_option('display.max_rows', None)  # 显示完整的列
2304     pd.set_option('display.expand_frame_repr', False)  # 设置不折叠数据
2305     pd.set_option('display.float_format', lambda x: '%.2f' % x)  # 设置不以科学计数法显示
2306     # 读取导入Excel所有数据,
2307     # print(work_pd1)
2308     # print(type(work_pd1))
2309 
2310     return work_pd1
2311 
2312 
2313 '''
2314 #---------------------------------------------------------------------------------------------------------------#
2315 #  vi5300_ft_xx_handle_v2
2316 #---------------------------------------------------------------------------------------------------------------#
2317 '''
2318 
2319 
2320 def vi5300_ft_xx_handle_v2(all_data):
2321     print('进入函数>>>: vi5300_ft_xx_handle_v2 ...')
2322     datetime_object_s = datetime.datetime.now()
2323     print("datetime_object_s :", datetime_object_s)
2324 
2325     # print('全部数据显示: ',pd.DataFrame(all_data))   # 全部数据显示
2326     # print(pd.DataFrame(all_data,columns=[0]))   # HANDLER  测试日期
2327     all_raw_data = all_data  # raw data 另外保存
2328     data_columns_C0 = pd.DataFrame(all_data, columns=[0])  # 第0列:测试日期
2329     print("summary number:", len(data_columns_C0))
2330     print("分类存储到不同列表")
2331     # ------------------------------------------------------------------------------------------------------------------ #
2332     datetime_object_1 = datetime.datetime.now()
2333     # print("datetime_object_1 :", datetime_object_1)
2334     # ------------------------------------------------------------------------------------------------------------------ #
2335     for index_a in range(1, len(data_columns_C0)):  # 第0列:测试日期需要去除
2336         str_v1_name = str(data_columns_C0.values[index_a])
2337 
2338         # TODO 关闭 年 索引
2339         # str_v1_year = str_v1_name[2:6]
2340         str_v1_month = str_v1_name[7:9]
2341         # TODO 关闭 天 索引
2342         # str_v1_day = str_v1_name[10:12]
2343 
2344         # 提取年月日
2345         # print("序号:", index_a, '强制转换: ', str_v1_name)
2346         # print('year:  ', str_v1_name[2:6])
2347         # print('month: ', str_v1_name[7:9])
2348         # print('day:   ',  str_v1_name[10:12])
2349 
2350         # TODO 按年-当前省略,后续添加分类
2351         list_month_m12 = monthly_handle_v12_xx(str_v1_month, index_a)
2352     #
2353     # print('显示汇总后每月分类:',list_month_m12)
2354     # ------------------------------------------------------------------------------------------------------------------ #
2355     datetime_object_2 = datetime.datetime.now()
2356     print("datetime_object_2 :", datetime_object_2, '耗时:', (datetime_object_2 - datetime_object_1))
2357     # ------------------------------------------------------------------------------------------------------------------ #
2358 
2359     # # # TODO 统计本年度 按月索引数据-汇总数据
2360     print("统计本年度 按月索引数据-汇总数据")  # 起始位=1
2361     for index_a in range(1, 13):
2362         print('第%d月数据' % index_a, list_month_m12[index_a])
2363 
2364     # 单一月份数据汇总处理
2365     # print("传入1: ", list_month_v12_n)
2366 
2367     # ---------------------------------------------------------------------------------------------------------------- #
2368     print("*** 请输入查询讯芯月份 ***")
2369     month_h1 = input()
2370     # month_input1 = 11
2371     month_input1 = int(month_h1)
2372     # 根据raw data 数据生成结果图片和异常数据
2373     print("输入月份长度:", len(list_month_m12[month_input1]))
2374     single_month_v2_xx(month_input1, list_month_m12, all_raw_data)
2375     #
2376     # # 根据结果图片生成 html 报告
2377     generate_report_ft_xx(month_input1)
2378 
2379 
2380 '''
2381 # ====================================================================================================================#
2382 # 按月分类 monthly_handle_v12_xx 讯芯
2383 # ====================================================================================================================#
2384 '''
2385 # 构造二维数组
2386 
2387 var_month_v12_xx = [[], [], [], [], [], [], [], [], [], [], [], [], []]
2388 
2389 
2390 def monthly_handle_v12_xx(input_month, intput_index):
2391     # print('传入参数: 月份%s 行号%s' % (input_month, intput_index))
2392     month_def = ['0', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
2393     for index_v1 in range(1, 13):  # 从1开始遍历
2394         # print('遍历每月找到对应月份:',index_v1 , input_month)
2395         if input_month == month_def[index_v1]:
2396             # print("按月分类: %s \t行号:%s" % (month_def[index_v1], intput_index) , '月份类型:',type( month_def[index_v1]))
2397             month_index = int(month_def[index_v1])
2398             # print('转换后int-月份类型: ', type(month_index), month_index)
2399             # 添加数据到二维数组中
2400             var_month_v12_xx[month_index].append(intput_index)
2401             # print('对应当月的行数汇总:',var_month_v12_xx[month_index])
2402 
2403             break
2404     # print('显示汇总后每月分类:',var_month_v12_xx)
2405     return var_month_v12_xx
2406 
2407 
2408 '''
2409 # ====================================================================================================================#
2410 # 本月数据汇总 - single_month_v2_xx
2411 # ====================================================================================================================#
2412 '''
2413 
2414 
2415 def single_month_v2_xx(f_d1, f_d2, f_d3):
2416     print('进入函数>>>: single_month_summary_v2_xx ...')  # 注意索引值从0开始,索引1==第1月
2417     month_h1 = f_d1  # 获取月份
2418     s_m_m12 = f_d2[month_h1]  # 获取本月行号索引值 s_m_m12 = single month m12
2419     raw_data_h1 = f_d3  # 获取整excel表句柄
2420 
2421     # ---------------------------------------------------------------------------------------------------------------- #
2422 
2423     time_s = datetime.datetime.now()
2424     print("\ntime_1 :", time_s)
2425     # TODO 手动输入实际模版
2426     # 使用无表头,使用数字强制索引
2427     u1_handler = 1
2428     u1_lot = 4
2429     u1_marking = 9
2430     u1_yield = 13
2431     u1_input = 14
2432     u1_bin1 = 15
2433     u1_bin1_p = 16
2434     u1_bin2 = 17
2435     u1_bin2_p = 18
2436     u1_bin3 = 19
2437     u1_bin3_p = 20
2438     u1_bin4 = 21
2439     u1_bin4_p = 22
2440     u1_bin5 = 23
2441     u1_bin5_p = 24
2442     u1_bin6 = 25
2443     u1_bin6_p = 26
2444     u1_bin7 = 27
2445     u1_bin7_p = 28
2446     u1_bin8 = 29
2447     u1_bin8_p = 30
2448     u1_bin9 = 31
2449     u1_bin9_p = 32
2450     u1_bin13 = 33
2451     u1_bin13_p = 34
2452     u1_bin14 = 35
2453     u1_bin14_p = 36
2454     u1_bin_vm = 37
2455     u1_bin_vm_p = 38
2456     u1_bin_loss = 39
2457     u1_bin_loss_p = 40
2458     u1_bin3_os = 41
2459     u1_bin3_os_p = 42
2460     u1_bin4_iih = 43
2461     u1_bin4_iih_p = 44
2462     u1_bin5_cal = 45  # calibration
2463     u1_bin5_cal_p = 46
2464     u1_bin6_vf = 47  # verify
2465     u1_bin6_vf_p = 48
2466     u1_bin6_ck = 49  # Crosstalk
2467     u1_bin6_ck_p = 50
2468     u1_bin7_power = 51
2469     u1_bin7_power_p = 52
2470     u1_bin7_os = 53
2471     u1_bin7_os_p = 54
2472     u1_bin7_lk = 55
2473     u1_bin7_lk_p = 56  # Leakage
2474 
2475     # display_all_header_file_names(55, s_m_m12, raw_data_h1)
2476     # display_all_header_file_names(56, s_m_m12, raw_data_h1)
2477     # ---------------------------------------------------------------------------------------------------------------- #
2478     time_s = datetime.datetime.now()
2479     print("\ntime_s :", time_s, )
2480     # ---------------------------------------------------------------------------------------------------------------- #
2481     #  具体BIN1处理  通用处理
2482     # ---------------------------------------------------------------------------------------------------------------- #
2483     name_bin = "BIN1"
2484     reorder_bin_info_v2_xx(u1_marking, u1_handler, u1_lot, u1_input, u1_bin1, u1_bin1_p, u1_yield, name_bin, month_h1, s_m_m12, raw_data_h1)
2485     chart_total_info_v2_xx(u1_marking, u1_handler, u1_lot, u1_input, u1_bin1, u1_bin1_p, u1_yield, name_bin, month_h1, s_m_m12, raw_data_h1)
2486 
2487     # # ---------------------------------------------------------------------------------------------------------------- #
2488     # # 具体不良品处理  特殊处理
2489     # # name_bin = "BIN2"  不存在
2490     name_bin = "BIN3"
2491     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin3, u1_bin3_os, u1_bin3_p, u1_bin3_os_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2492     #
2493     name_bin = "BIN4"
2494     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin4, u1_bin4_iih, u1_bin4_p, u1_bin4_iih_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2495     #
2496     name_bin = "BIN5"
2497     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin5, u1_bin5_cal, u1_bin5_p, u1_bin5_cal_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2498     #
2499     name_bin = "BIN6_1"
2500     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin6, u1_bin6_vf, u1_bin6_p, u1_bin6_vf_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2501     name_bin = "BIN6_2"
2502     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin6, u1_bin6_ck, u1_bin6_p, u1_bin6_ck_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2503     #
2504     name_bin = "BIN7_1"
2505     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin7, u1_bin7_power, u1_bin7_p, u1_bin7_power_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2506     name_bin = "BIN7_2"
2507     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin7, u1_bin7_os, u1_bin7_p, u1_bin7_os_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2508     name_bin = "BIN7_3"
2509     defective_h2_xx(u1_marking, u1_handler, u1_lot, u1_bin7, u1_bin7_lk, u1_bin7_p, u1_bin7_lk_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2510     # # 备份
2511     # //name_bin = "BIN_loss"
2512     # //defective_handle_v2_se(u1_marking, u1_handler, u1_lot, u1_bin_loss, u1_bin_loss_p, name_bin, month_h1, s_m_m12, raw_data_h1)
2513 
2514     # ---------------------------------------------------------------------------------------------------------------- #
2515     time_e = datetime.datetime.now()
2516     print("\ntime_s :", time_e, "耗时:", (time_e - time_s))
2517 
2518 
2519 '''
2520 # ====================================================================================================================#
2521 # 本月-良品BIN1-测试数据汇总分布- reorder_bin_info_v2_xx
2522 # ====================================================================================================================#
2523 '''
2524 
2525 
2526 def reorder_bin_info_v2_xx(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
2527     # ---------------------------------------------------------------------------------------------------------------- #
2528     print("#**** reorder_bin_info_v2_xx ****#")
2529     # 开始计时
2530     datetime_object_11 = datetime.datetime.now()
2531     print("datetime_object_11 :", datetime_object_11)
2532 
2533     # 使用无表头,使用数字强制索引 -- 第一份引用
2534     xx_handler_n2 = x_p2
2535     xx_lot_n3 = x_p3
2536     xx_month_n2 = z_p2
2537     xx_single_month_d2 = z_p3
2538     xx_raw_data_a2 = z_p4
2539 
2540     # 使用无表头,使用数字强制索引 -- 第2份引用
2541     u2_marking = x_p1
2542     u2_handler = x_p2
2543     u2_lot = x_p3
2544     u2_input = y_p1
2545     u2_bin1 = y_p2
2546     u2_bin1_p = y_p3
2547     u2_yield = y_p4
2548     u2_name = z_p1
2549     u2_month = z_p2
2550     # u2_index_m12 = z_p3
2551     u2_raw_data = z_p4
2552 
2553     # ---------------------------------------------------------------------------------------------------------------------- #
2554     # 处理1 数据归类
2555     print('绘图处理: 月份< %d >' % xx_month_n2, z_p1)
2556     # 指定月份 - 归类前文件
2557     c_g_name1, c_g_data1 = get_data_bin_v2(xx_lot_n3, xx_single_month_d2, xx_raw_data_a2)
2558     c_g_name2, c_g_data2 = get_data_bin_v2(xx_handler_n2, xx_single_month_d2, xx_raw_data_a2)
2559     print("源1:", c_g_name1, c_g_data1)
2560     print("源2:", c_g_name2, c_g_data2)
2561 
2562     # ---------------------------------------------------------------------------------------------------------------- #
2563     lot_list_v1 = []
2564     lot_list_v3 = []
2565     for index_a in range(len(c_g_data1)):  # len(c_g_data1)
2566         num_v1_lot = xx_single_month_d2[index_a]  # 获取本月行号 索引值
2567         str_v1_lot = c_g_data1[index_a][0:6]  # 正则表达获取lot ,去除wafer
2568         lot_handler_t1 = c_g_data2[index_a]  # 获取附属信息 handler
2569         lot_list_v2 = [num_v1_lot, str_v1_lot, lot_handler_t1]  # 3个关键字存储到一维列表中
2570         lot_list_v1.append(lot_list_v2)  # 存储到一维列表到二维列表中
2571         lot_list_v3.append(str_v1_lot)  # 1个关键字存储到一维列表中
2572     # all raw data 有效映射
2573     print('all data -- 切片lot  : ', len(lot_list_v1), lot_list_v1)
2574 
2575     # 获取同一列表中相同元素,只保留一种类型
2576     one_lot = []
2577     for v2_lot in lot_list_v3:
2578         if v2_lot not in one_lot:
2579             one_lot.append(v2_lot)
2580     print('lot中唯一代表名称: ', one_lot)
2581 
2582     # 先按照 lot 分类 再按照 handler分类 最后索引-行号
2583     lot_handler_m1 = []  # 重新分类聚合的列表
2584     lot_h1_m1 = []
2585     lot_h1_m2 = []
2586     # 先按照 lot 大类分组
2587     for row_v1_w1 in one_lot:
2588         print('每种类型的lot: ', row_v1_w1)
2589         line_re_lot5 = []
2590 
2591         for row_v1 in lot_list_v1:
2592             # print('切片lot中第1个元素-二维列中每行第1个元素: ',row_v1[1])
2593             if row_v1_w1 == row_v1[1]:
2594                 # print('打印相同的元素名称: ',row_v1_w1,row_v1[0],row_v1[1])
2595                 line_re_lot4 = [row_v1[0], row_v1[1], row_v1[2]]  # 按照每个lot大类重新组合索引值
2596                 line_re_lot5.append(line_re_lot4)
2597                 lot_h1_m1.append(row_v1[0])
2598                 lot_h1_m2.append(line_re_lot4)
2599         print('每个lot大类-组合: ', len(line_re_lot5), line_re_lot5)
2600         # -------------------------------------------------------------------------------- #
2601         # # TODO
2602         list_handler_sy1 = line_re_lot5
2603         index_handler_pp = []
2604         for grapefruit in range(len(list_handler_sy1)):
2605             index_handler = list_handler_sy1[grapefruit]  # 获取本月行号 索引值
2606             # print("每列的元素:", index_handler)           # 索引+lot+handler
2607             index_m1 = index_handler[2]  # 获取 handler
2608             index_handler_pp.append(index_m1)
2609         # all raw data 有效映射
2610         print('all raw data 有效映射: \n', len(index_handler_pp),index_handler_pp)
2611         # 获取同一列表中相同元素,只保留一种类型
2612         one_handler_grape = []
2613         for grape in index_handler_pp:
2614             if grape not in one_handler_grape:
2615                 one_handler_grape.append(grape)
2616         print('handler 唯一代表 名称: ', one_handler_grape)
2617 
2618         handler_all = []
2619         for one_c1 in range(len(one_handler_grape)):
2620             papaya = []
2621             papaya_mt = []
2622             for kiwifruit in range(len(list_handler_sy1)):
2623                 # print("Index:", one_c1, "Value:", one_handler_grape[one_c1], list_handler_sy1[kiwifruit][2])
2624                 if one_handler_grape[one_c1] == list_handler_sy1[kiwifruit][2]:
2625                     # print('匹配:',one_c1 ,one_handler_grape[one_c1], list_handler_sy1[kiwifruit][2])
2626                     papaya.append(list_handler_sy1[kiwifruit])
2627             # print("打印每行lot的数据:",papaya)
2628             # 同种handler 合并到一个列表-方案1
2629             # handler_all.append(papaya)
2630             # # 同种handler 放置同一级-方案2
2631             for df_one in range(len(papaya)):
2632                 handler_all.append(papaya[df_one])
2633         # print("同一个lot 所有行lot的数据:", len(handler_all), handler_all)
2634         lot_handler_m1 = lot_handler_m1 + handler_all
2635     # 打印重新组合
2636     print("显示重新新组合: \n", len(lot_handler_m1), lot_handler_m1)
2637     # print("是否继续循环")
2638     # input()
2639     # ---------------------------------------------------------------------------------------------------------------- #
2640 
2641     lot_handler_index = []
2642     for index_lh in range(len(lot_handler_m1)):
2643         lot_handler_index.append(lot_handler_m1[index_lh][0])
2644     # print("lot_handler_index: ", lot_handler_index)
2645     # 替换前
2646     # for index_a in range(1, 13):
2647     #     print('第%d月数据' % (index_a), var_month_v12_xx[index_a])
2648     var_month_v12_xx[xx_month_n2] = lot_handler_index
2649     # 替换后
2650     # for index_a in range(1, 13):
2651     #     print('第%d月数据' % (index_a), var_month_v12_xx[index_a])
2652     index_s_m2 = lot_handler_index
2653 
2654 
2655     datetime_object_12 = datetime.datetime.now()
2656     print("datetime_object_12 :", datetime_object_12, ' 耗时:', (datetime_object_12 - datetime_object_11))
2657     # ---------------------------------------------------------------------------------------------------------------------- #
2658     # 绘图  是由上述函数传递的:index_s_m2
2659     histogram_handle_v2_xx(u2_marking, u2_handler, u2_lot, u2_input, u2_bin1, u2_bin1_p, u2_yield, u2_name, u2_month, index_s_m2, u2_raw_data)
2660 
2661     datetime_object_13 = datetime.datetime.now()
2662     print("datetime_object_12 :", datetime_object_13, ' 耗时:', (datetime_object_13 - datetime_object_11))
2663 
2664 
2665 '''
2666 # ====================================================================================================================#
2667 # 本月-良品BIN1-测试数据汇总分布-绘图v2-xx histogram_handle_v2_xx
2668 # ====================================================================================================================#
2669 '''
2670 
2671 
2672 def histogram_handle_v2_xx(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
2673     print('#---- histogram_handle_v2_xx ----#')
2674     x_axle_n1 = x_p1
2675     x_axle_n2 = x_p2
2676     x_axle_n3 = x_p3
2677     y_total_t1 = y_p1
2678     y_total_t2 = y_p2
2679     y_yield_t1 = y_p3
2680     y_yield_t2 = y_p4
2681     bin_name = z_p1
2682     month_n1 = z_p2
2683     single_month_d1 = z_p3
2684     raw_data_a1 = z_p4
2685     print('绘图处理: 月份< %d >' % month_n1, )
2686     # 获取每月函数 有效数据 x_axle_n2
2687     x_name1, x_data1 = get_data_bin_v2(x_axle_n1, single_month_d1, raw_data_a1)
2688     x_name2, x_data2 = get_data_bin_v2(x_axle_n2, single_month_d1, raw_data_a1)
2689     x_name3, x_data3 = get_data_bin_v2(x_axle_n3, single_month_d1, raw_data_a1)
2690     y_name1, y_data1 = get_data_bin_v2(y_total_t1, single_month_d1, raw_data_a1)
2691     y_name2, y_data2 = get_data_bin_v2(y_total_t2, single_month_d1, raw_data_a1)
2692     y_name3, y_data3 = get_data_bin_v2(y_yield_t1, single_month_d1, raw_data_a1)
2693     y_name4, y_data4 = get_data_bin_v2(y_yield_t2, single_month_d1, raw_data_a1)
2694     # print(x_name1, x_data1)
2695     # print(x_name2, x_data2)
2696     # print(y_name1, y_data1)
2697     # print(y_name2, y_data2)
2698     # print(y_name3, y_data3)
2699 
2700     # ======================================================================================== #
2701 
2702     # 整体参数配置
2703     font = FontProperties(size=10)
2704     plt.rcParams["font.sans-serif"] = ['SimHei']
2705     plt.rcParams['axes.unicode_minus'] = False
2706     plt.rcParams['font.family'] = ['SimHei']
2707     plt.rcParams['font.sans-serif'] = ['SimHei']
2708     plt.rcParams['figure.figsize'] = (30, 10)
2709     plt.rc('font', family='SimHei', size=8)
2710 
2711     # 创建一个图形和两个y轴
2712     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
2713 
2714     # 柱状图柱子宽度
2715     bar_width = 0.4
2716     x_ticks = range(len(x_data1))  # x轴刻度位置 | 折线图x位置
2717     bar_1_x = [(ii - bar_width + 0.2) for ii in x_ticks]  # 柱状图1 - x位置
2718     bar_2_x = [(ww - bar_width + 0.6) for ww in x_ticks]
2719 
2720     # 设置x轴刻度字体以及方向-单刻度标签
2721     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
2722     [label.set_fontname('SimHei') for label in labels1]
2723     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
2724 
2725     # 设置x轴刻度字体以及方向- 叠加双刻度标签
2726     labels = []
2727     for two_m1 in range(len(x_data1)):
2728         cell_m2 = x_data3[two_m1][0:6] + '   ' + x_data2[two_m1] + '   ' + x_data1[two_m1]
2729         labels.append(cell_m2)
2730     # labels = x_ticks  # 默认
2731     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
2732     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
2733     # 自适应调整布局+ 指定 解决X轴范围问题
2734     fig.autofmt_xdate(rotation=90)
2735 
2736     # -------------------------------------------------------------------------------------- #
2737     # # 同一刻度标签标记为不同颜色 插孔法 升级-适用较为复杂的场景
2738     print(x_name1)
2739     print(x_name2)
2740     print(x_name3)
2741 
2742     index_lot_v5 = []
2743     for index_a in range(len(single_month_d1)):
2744         index_lot = single_month_d1[index_a]  # 获取本月行号 索引值
2745         index_m1 = x_data3[index_a][0:6]  # 获取本月行号 索引值
2746         index_lot_v5.append(index_m1)
2747     # all raw data 有效映射
2748     print("all raw data 有效映射:", index_lot_v5)
2749     # 获取同一列表中相同元素,只保留一种类型
2750     one_lot_v1 = []
2751     for v2_lot in index_lot_v5:
2752         if v2_lot not in one_lot_v1:
2753             one_lot_v1.append(v2_lot)
2754     print('lot中唯一代表名称: ', one_lot_v1)
2755     xtick_labels = ax1.get_xticklabels()
2756     colors = ['red', 'green', 'blue', 'purple', 'orange', 'brown', 'gray', 'pink', 'cyan', 'magenta', 'yellow', 'black', ]
2757     # 利用唯一lot去适配列表lot,影射到对应刻度,根据余数去自动识别颜色,默认10种
2758     for x_color in range(len(x_data3)):
2759         # print("x_color: ",x_color,x_data3[x_color][0:6])
2760         for one_c1 in range(len(one_lot_v1)):
2761             # print("Index:", one_c1, "Value:", one_lot_v1[one_c1])
2762             if one_lot_v1[one_c1] == x_data3[x_color][0:6]:
2763                 one_color_v1 = one_c1 % 10
2764                 if one_color_v1 == 0:
2765                     xtick_labels[x_color].set_color(colors[0])
2766                 elif one_color_v1 == 1:
2767                     xtick_labels[x_color].set_color(colors[1])
2768                 elif one_color_v1 == 2:
2769                     xtick_labels[x_color].set_color(colors[2])
2770                 elif one_color_v1 == 3:
2771                     xtick_labels[x_color].set_color(colors[3])
2772                 elif one_color_v1 == 4:
2773                     xtick_labels[x_color].set_color(colors[4])
2774                 elif one_color_v1 == 5:
2775                     xtick_labels[x_color].set_color(colors[5])
2776                 elif one_color_v1 == 6:
2777                     xtick_labels[x_color].set_color(colors[6])
2778                 elif one_color_v1 == 7:
2779                     xtick_labels[x_color].set_color(colors[7])
2780                 elif one_color_v1 == 8:
2781                     xtick_labels[x_color].set_color(colors[8])
2782                 elif one_color_v1 == 9:
2783                     xtick_labels[x_color].set_color(colors[9])
2784         # -------------------------------------------------------------------------------------- #
2785 
2786     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
2787     ax2 = ax1.twinx()
2788 
2789     # 图例文件描述-动态变化
2790     title_up = "本月测试  " + bin_name + "  分布"
2791     legend_x3 = y_name1
2792     legend_x4 = y_name2
2793     legend_y3 = y_name3
2794     legend_y4 = y_name4
2795 
2796     # ====================================================================================================================#
2797     # 绘制柱状图
2798     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
2799     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
2800     bar3 = ax1.bar(bar_1_x, y_data1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
2801     bar4 = ax1.bar(bar_2_x, y_data2, label=legend_x4, color='gold', width=bar_width, linewidth=0.2, edgecolor="white")
2802 
2803     # 绘制折线图
2804     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
2805     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
2806     line3 = ax2.plot(x_data1, y_data3, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
2807     line4 = ax2.plot(x_data1, y_data4, label=legend_y4, color='red', marker='.', markersize='6', ls='-')
2808 
2809     # 折线图点描述
2810     for a_x1, b_y3, c_y4 in zip(x_data1, y_data3, y_data4):
2811         if b_y3 < c_y4:
2812             print("# 低于卡控线: ", a_x1, file=run_log)
2813             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=12, font=font)
2814         else:
2815             # print("# 正常模组: ", a_x1)
2816             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=8, font=font)
2817             ax2.text(1, c_y4, '{:.2f}%'.format(c_y4 * 100), ha='center', va='bottom', fontsize=11, font=font)  # 只显示一个
2818 
2819     # ====================================================================================================================#
2820 
2821     # 设置x轴和y轴的标签,指明坐标含义
2822     ax1.set_xlabel('lot ID', fontdict={'size': 16})
2823     # 左边-y轴为:数量模式
2824     ax1.set_ylabel('模组数量', fontdict={'size': 16})
2825     # 右边-y轴为:百分比形式
2826     ax2.set_ylabel('百分比', fontdict={'size': 16})
2827 
2828     # 左-y轴为:刻度范围,动态调整
2829     max_value_r1 = int(max(y_data1) * 1.3)
2830     min_value_r1 = int(min(y_data1) * 0.9)
2831     if max_value_r1 < 5:
2832         max_value_r1 = 10  # 直接赋值
2833         min_value_r1 = 0  # 直接赋值
2834     ax1.set_ylim(min_value_r1, max_value_r1)
2835     #  右边-y轴为:最大值为100%,小数点2位
2836     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
2837 
2838     # 设置x轴和y轴刻度字体
2839     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
2840     [label.set_fontname('SimHei') for label in labels2]
2841 
2842     # 添加图表题  plt.title('双y轴折线图')
2843     plt.title(title_up, color="red", fontsize=16)
2844 
2845     # 设置轴标签颜色
2846     # ax1.tick_params('x', colors='Black')
2847     ax1.tick_params('y', colors='royalblue')
2848     ax2.tick_params('y', colors='tomato')
2849 
2850     # 设置轴颜色
2851     ax1.spines['left'].set_color('royalblue')
2852     ax2.spines['left'].set_color('royalblue')
2853     ax1.spines['right'].set_color('tomato')
2854     ax2.spines['right'].set_color('tomato')
2855 
2856     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
2857     ax1.spines['top'].set_visible(False)
2858     ax2.spines['top'].set_visible(False)
2859 
2860     # 添加图例函数:  plt.legend()
2861     # 添加图例 - 添加方向改为以下代码
2862     ax1.legend(loc='upper left')
2863     ax2.legend(loc='upper right')
2864     # 添加图例 - 将`图例合并改为以下代码
2865     # lines = line1 + line2 + line3 + line4
2866     # lines = line3 + line4
2867     # labels = [h.get_label() for h in lines]
2868     # plt.legend(lines, labels, loc='upper right')
2869 
2870     # 设置中文显示
2871     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
2872     plt.rcParams['axes.unicode_minus'] = False
2873 
2874     # 虚拟背景线
2875     plt.grid(True, linestyle="--")
2876 
2877     # 展示图片
2878     # plt.show()
2879     # 显示柱状图时间,单位s
2880     time_v1 = 1
2881     while time_v1 != 0:
2882         print('显示倒计时:%d s' % time_v1)
2883         plt.pause(1)
2884         time_v1 = time_v1 - 1
2885     print('直方图显示完成')
2886 
2887     # 图片保存对应文件
2888     picture_m = './6_result_ft_xx/picture/' + bin_name + r".jpg"
2889     plt.savefig(picture_m)
2890     plt.draw()
2891     print('图片保存对应文件-完成')
2892     plt.close()  # 关闭图表显示
2893 
2894 
2895 '''
2896 # ====================================================================================================================#
2897 # 本月-良品BIN1-handler&lot汇总分布-通用2模板数据处理
2898 # ====================================================================================================================#
2899 '''
2900 
2901 
2902 def chart_total_info_v2_xx(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
2903     print('>>> chart_total_info_v2_xx ...')
2904     # u1_marking, u1_handler, u1_lot, u1_input, u1_bin1, u1_bin1_p, u1_yield, name_bin, month_h1, index_s_m0, raw_data_h1
2905     # 开始计时
2906     datetime_object_21 = datetime.datetime.now()
2907     print("datetime_object_21 :", datetime_object_21)
2908     # 1按照总数汇总
2909     # 按照handler类型汇总-4种
2910     # 按照lot类型汇总-动态
2911     x_axle_e1 = x_p1
2912     x_axle_e2 = x_p2
2913     x_axle_e3 = x_p3
2914     y_total_k1 = y_p1
2915     y_total_k2 = y_p2
2916     y_yield_k3 = y_p3
2917     y_yield_k4 = y_p4
2918     bin_name = z_p1
2919     month_u1 = z_p2
2920     single_month_g1 = z_p3
2921     raw_data_t1 = z_p4
2922     print('汇总处理: 月份< %d >' % month_u1, )
2923     print(single_month_g1)
2924     x_name_f1, x_data_j1 = get_data_bin_v2(x_axle_e1, single_month_g1, raw_data_t1)
2925     x_name_f2, x_data_j2 = get_data_bin_v2(x_axle_e2, single_month_g1, raw_data_t1)
2926     x_name_f3, x_data_j3 = get_data_bin_v2(x_axle_e3, single_month_g1, raw_data_t1)
2927     y_name_f1, y_data_j1 = get_data_bin_v2(y_total_k1, single_month_g1, raw_data_t1)
2928     y_name_f2, y_data_j2 = get_data_bin_v2(y_total_k2, single_month_g1, raw_data_t1)
2929     y_name_f3, y_data_j3 = get_data_bin_v2(y_yield_k3, single_month_g1, raw_data_t1)
2930     y_name_f4, y_data_j4 = get_data_bin_v2(y_yield_k4, single_month_g1, raw_data_t1)
2931     # print('源1:', x_name_f1, x_data_j1)  # MARKING
2932     # print('源2:', x_name_f2, x_data_j2)  # HANDLER
2933     # print('源3:', x_name_f3, x_data_j3)  # LOTID
2934     print('源4:', y_name_f1, y_data_j1)  # Input
2935     print('源5:', y_name_f2, y_data_j2)  # BIN01(Good)
2936     # print('源6:', y_name_f3, y_data_j3)  # BIN01(%)
2937     # print('源7:', y_name_f4, y_data_j4)  # YIELDLIMIT
2938 
2939     # def limit
2940     handler_syl = 0.9000
2941     lot_syl = 0.9000
2942 
2943     # 创建一个新的 Excel 文件
2944     workbook = openpyxl.Workbook()
2945     one_sheet = workbook.active
2946     test_result_v0 = ["project_name", "结果", "实际良率", "目标良率", "投入数量(ea)", "实际产出(ea)"]
2947     one_sheet.append(test_result_v0)  # 追加一行数据
2948     # 动态保存路径
2949     # target_name = str(month_u1) + "月_汇总统计结果.xlsx"
2950     target_name = "月度_汇总统计结果.xlsx"
2951     target_path = r'./6_result_ft_xx/picture/' + target_name
2952     # 保存数据
2953     # workbook.save(target_path)
2954 
2955     # ---------------------------------------------------------------------------------------------------------------- #
2956     # 1按照总数汇总
2957     r1_input = np.sum(y_data_j1)
2958     r1_bin1 = np.sum(y_data_j2)
2959     r1_yield = r1_bin1 / r1_input
2960     r1_yield_percent = "{:.2%}".format(r1_yield)
2961     r1_limit = "{:.2%}".format(y_data_j4[0])
2962     r1_state = 'pass' if r1_yield > y_data_j4[0] else 'fail'
2963     print(
2964         'summary 结果:%s 实际良率:%s  目标良率:%s 投入数量(ea): %d   实际产出(ea):%d \n' % (r1_state, r1_yield_percent, r1_limit, r1_input, r1_bin1))
2965 
2966     test_result_v0 = ["summary", r1_state, r1_yield_percent, r1_limit, r1_input, r1_bin1]
2967     one_sheet.append(test_result_v0)  # 追加一行数据
2968     # ---------------------------------------------------------------------------------------------------------------- #
2969     datetime_21_1 = datetime.datetime.now()
2970     print("datetime_21_1 :", datetime_21_1, ' 耗时:', (datetime_21_1 - datetime_object_21))
2971     # ---------------------------------------------------------------------------------------------------------------- #
2972     # # 按照handler类型汇总-4种
2973     # # 仅按照handler分类  顺序重新归类
2974 
2975     index_handler_pp = []
2976     for grapefruit in range(len(single_month_g1)):
2977         index_handler = single_month_g1[grapefruit]  # 获取本月行号 索引值
2978         index_m1 = x_data_j2[grapefruit][0:6]  # 获取本月行号 索引值
2979         index_handler_pp.append(index_m1)
2980     # all raw data 有效映射
2981     # print('all raw data 有效映射: \n',index_lot_hv5)
2982     # 获取同一列表中相同元素,只保留一种类型
2983     one_handler_grape = []
2984     for grape in index_handler_pp:
2985         if grape not in one_handler_grape:
2986             one_handler_grape.append(grape)
2987     print('handler 唯一代表 名称: ', one_handler_grape)
2988 
2989     handler_all = []
2990     for one_c1 in range(len(one_handler_grape)):
2991         papaya = []
2992         for kiwifruit in range(len(x_data_j2)):
2993             # print("Index:", one_c1, "Value:", one_lot_orange[one_c1], x_data_j3[watermelon][0:6])
2994             if one_handler_grape[one_c1] == x_data_j2[kiwifruit]:
2995                 # print('匹配:',one_c1 ,one_lot_orange[one_c1], x_data_j3[watermelon][0:6])
2996                 handler_element = [single_month_g1[kiwifruit], x_data_j2[kiwifruit], y_data_j1[kiwifruit], y_data_j2[kiwifruit]]
2997                 papaya.append(handler_element)
2998         # print("打印每行lot的数据:",papaya)
2999         handler_all.append(papaya)
3000     #
3001     print("打印每行lot的数据:", handler_all)
3002 
3003     # #
3004     strawberry_a1 = []
3005     strawberry_b1 = []
3006     strawberry_b2 = []
3007     strawberry_b3 = []
3008     strawberry_b4 = []
3009     # 根据lot列表-自动循环方案
3010     for strawberry in range(len(handler_all)):
3011         line_cache21 = []
3012         line_cache22 = []
3013         # print("目的获取handler的个数 -第%d个 "%banana)
3014         for sub_index1 in range(len(handler_all[strawberry])):
3015             # print("目的获取三维数组的每行的列表值(一维):",handler_all[strawberry][sub_index1])
3016             for sub_index2 in range(len(one_handler_grape)):
3017                 # print('打印比对的数值:',one_handler_grape[sub_index2], handler_all[strawberry][sub_index1][1])
3018                 if one_handler_grape[sub_index2] == handler_all[strawberry][sub_index1][1]:
3019                     line_cache21.append(handler_all[strawberry][sub_index1][2])
3020                     line_cache22.append(handler_all[strawberry][sub_index1][3])
3021         h1_input = np.sum(line_cache21)
3022         h1_output = np.sum(line_cache22)
3023         h1_yield = h1_output / h1_input
3024         h1_yield_percent = "{:.2%}".format(h1_yield)
3025         h1_state = 'pass' if h1_yield > lot_syl else 'fail'
3026         print('handler  -%s >>> \t结果%s \t良率: %s \t投入数量: %d  \t实际产出: %d ' % (
3027             handler_all[strawberry][0][1][0:6], h1_state, h1_yield_percent, h1_input, h1_output))
3028         project_n1 = 'handler-' + handler_all[strawberry][sub_index1][1][0:6]
3029         h1_syl = "{:.2%}".format(lot_syl)
3030         test_result_v0 = [project_n1, h1_state, h1_yield_percent, h1_syl, h1_input, h1_output]
3031         one_sheet.append(test_result_v0)  # 追加一行数据
3032         # 存储列表-绘图
3033         strawberry_a1.append(one_handler_grape[strawberry])
3034         strawberry_b1.append(h1_input)
3035         strawberry_b2.append(h1_output)
3036         strawberry_b3.append(h1_yield)
3037         strawberry_b4.append(handler_syl)
3038     # 绘图
3039     t_category = "handler"
3040     histogram_handle_v2_xx_se(strawberry_a1, strawberry_b1, strawberry_b2, strawberry_b3, strawberry_b4, t_category)
3041 
3042     #     print('Handler PP-%d >>> \t结果:%s \t实际: %s \t投入数量: %d \t实际产出: %d ' % (banana, h1_state, h1_yield_percent, h1_input, h1_output,))
3043     #     project_n1 = 'Handler PP-' + str(banana)
3044     #     h1_syl = h1_yield_percent = "{:.2%}".format(handler_syl)
3045     #     test_result_v0 = [project_n1, h1_state, h1_yield, h1_syl, h1_input, h1_output]
3046     #     one_sheet.append(test_result_v0)  # 追加一行数据
3047     #
3048     #     # 存储列表-绘图
3049     #     banana_a1.append(handler_name[index_n1])
3050     #     banana_b1.append(h1_input)
3051     #     banana_b2.append(h1_output)
3052     #     banana_b3.append(h1_yield)
3053 
3054     # ---------------------------------------------------------------------------------------------------------------- #
3055     datetime_21_2 = datetime.datetime.now()
3056     print("datetime_21_2 :", datetime_21_2, ' 耗时:', (datetime_21_2 - datetime_21_1))
3057     print("\n")
3058     # ---------------------------------------------------------------------------------------------------------------- #
3059     # 按照lot类型汇总-动态
3060     index_lot_lv5 = []
3061     for orange in range(len(single_month_g1)):
3062         index_lot = single_month_g1[orange]  # 获取本月行号 索引值
3063         index_m1 = x_data_j3[orange][0:6]  # 获取本月行号 索引值
3064         index_lot_lv5.append(index_m1)
3065     # all raw data 有效映射
3066     # print('all raw data 有效映射: \n',index_lot_lv5)
3067     # 获取同一列表中相同元素,只保留一种类型
3068     one_lot_orange = []
3069     for orange_lot in index_lot_lv5:
3070         if orange_lot not in one_lot_orange:
3071             one_lot_orange.append(orange_lot)
3072     print('lot 唯一代表 名称: ', one_lot_orange)
3073 
3074     km_lot_all = []
3075     for one_c1 in range(len(one_lot_orange)):
3076         km_lot = []
3077         for watermelon in range(len(x_data_j3)):
3078             # print("Index:", one_c1, "Value:", one_lot_orange[one_c1], x_data_j3[watermelon][0:6])
3079             if one_lot_orange[one_c1] == x_data_j3[watermelon][0:6]:
3080                 # print('匹配:',one_c1 ,one_lot_orange[one_c1], x_data_j3[watermelon][0:6])
3081                 km_lot_element = [single_month_g1[watermelon], x_data_j3[watermelon], y_data_j1[watermelon], y_data_j2[watermelon]]
3082                 km_lot.append(km_lot_element)
3083         # print("打印每行lot的数据:",km_lot)
3084         km_lot_all.append(km_lot)
3085     # print("打印每行lot的数据:",km_lot_all)
3086 
3087     #
3088     banana_a1 = []
3089     banana_b1 = []
3090     banana_b2 = []
3091     banana_b3 = []
3092     banana_b4 = []
3093     # 根据lot列表-自动循环方案
3094     for banana in range(len(km_lot_all)):
3095         line_cache21 = []
3096         line_cache22 = []
3097         # print("目的获取handler的个数 -第%d个 "%banana)
3098         for sub_index1 in range(len(km_lot_all[banana])):
3099             # print("目的获取三维数组的每行的列表值(一维):",km_lot_all[banana][sub_index1])
3100             for sub_index2 in range(len(one_lot_orange)):
3101                 # print('打印比对的数值:',one_lot_orange[sub_index2], km_lot_all[banana][sub_index1][1][0:6])
3102                 if one_lot_orange[sub_index2] == km_lot_all[banana][sub_index1][1][0:6]:
3103                     line_cache21.append(km_lot_all[banana][sub_index1][2])
3104                     line_cache22.append(km_lot_all[banana][sub_index1][3])
3105         l1_input = np.sum(line_cache21)
3106         l1_output = np.sum(line_cache22)
3107         l1_yield = l1_output / l1_input
3108         l1_yield_percent = "{:.2%}".format(l1_yield)
3109         l1_state = 'pass' if l1_yield > lot_syl else 'fail'
3110         print('lot-%s >>> \t结果%s \t良率: %s \t投入数量: %d  \t实际产出: %d ' % (
3111             km_lot_all[banana][0][1][0:6], l1_state, l1_yield_percent, l1_input, l1_output))
3112         project_n1 = 'lot-' + km_lot_all[banana][sub_index1][1][0:6]
3113         l1_syl = "{:.2%}".format(lot_syl)
3114         test_result_v0 = [project_n1, l1_state, l1_yield_percent, l1_syl, l1_input, l1_output]
3115         one_sheet.append(test_result_v0)  # 追加一行数据
3116 
3117         # 存储列表-绘图
3118         banana_a1.append(one_lot_orange[banana])
3119         banana_b1.append(l1_input)
3120         banana_b2.append(l1_output)
3121         banana_b3.append(l1_yield)
3122         banana_b4.append(lot_syl)
3123     # 绘图
3124     t_category = "lot"
3125     histogram_handle_v2_xx_se(banana_a1, banana_b1, banana_b2, banana_b3, banana_b4, t_category)
3126     # ---------------------------------------------------------------------------------------------------------------- #
3127     datetime_21_3 = datetime.datetime.now()
3128     print("datetime_21_3 :", datetime_21_3, ' 耗时:', (datetime_21_3 - datetime_21_2))
3129     # ---------------------------------------------------------------------------------------------------------------- #
3130     # 保存数据
3131     workbook.save(target_path)
3132 
3133     datetime_object_22 = datetime.datetime.now()
3134     print("\n运行结束 :", datetime_object_22, ' 总耗时:', (datetime_object_22 - datetime_object_21))
3135 
3136 
3137 '''
3138 # ====================================================================================================================#
3139 # 本月-良品BIN1-handler&lot汇总分布-绘图2
3140 # ====================================================================================================================#
3141 '''
3142 
3143 
3144 def histogram_handle_v2_xx_se(x_p1, y_p1, y_p2, y_p3, y_p4, z_p1):
3145     print('#---- histogram_handle_v2_xx_se ----#')
3146     x_axle_n1 = x_p1
3147     y_total_t1 = y_p1
3148     y_total_t2 = y_p2
3149     y_yield_t1 = y_p3
3150     y_yield_t2 = y_p4
3151     z_name_km1 = z_p1
3152 
3153     # ======================================================================================== #
3154     # 整体参数配置
3155     font = FontProperties(size=10)
3156     plt.rcParams["font.sans-serif"] = ['SimHei']
3157     plt.rcParams['axes.unicode_minus'] = False
3158     plt.rcParams['font.family'] = ['SimHei']
3159     plt.rcParams['font.sans-serif'] = ['SimHei']
3160     plt.rcParams['figure.figsize'] = (30, 10)
3161     plt.rc('font', family='SimHei', size=8)
3162 
3163     # 创建一个图形和两个y轴
3164     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
3165 
3166     # 柱状图柱子宽度
3167     bar_width = 0.2
3168     x_ticks = range(len(x_axle_n1))  # x轴刻度位置 | 折线图x位置
3169     bar_1_x = [(ii - bar_width + 0.1) for ii in x_ticks]  # 柱状图1 - x位置
3170     bar_2_x = [(ww - bar_width + 0.3) for ww in x_ticks]
3171 
3172     # 设置x轴刻度字体以及方向-单刻度标签
3173     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
3174     [label.set_fontname('SimHei') for label in labels1]
3175     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
3176 
3177     # 设置x轴刻度字体以及方向- 叠加双刻度标签
3178     labels = []
3179     for two_m1 in range(len(x_axle_n1)):
3180         cell_m2 = x_axle_n1[two_m1]
3181         labels.append(cell_m2)
3182     # labels = x_ticks  # 默认
3183     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
3184     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
3185     # 自适应调整布局+ 指定 解决X轴范围问题
3186     fig.autofmt_xdate(rotation=90)
3187 
3188     # -------------------------------------------------------------------------------------- #
3189     # # 同一刻度标签标记为不同颜色 插孔法
3190     # 第1种方案
3191     xtick_labels = ax1.get_xticklabels()
3192     colors = ['red', 'green', 'blue', 'purple', 'orange', 'black', 'brown', 'gray', 'pink', 'yellow', 'cyan', 'magenta']
3193     for x_colors in range(int(len(x_axle_n1) / 4)):
3194         # print(0+x_colors*4, 1+x_colors*4, 2+x_colors*4,3+x_colors*4)
3195         x_colors_a = 0 + x_colors * 4
3196         x_colors_b = 1 + x_colors * 4
3197         x_colors_c = 2 + x_colors * 4
3198         x_colors_d = 3 + x_colors * 4
3199         xtick_labels[x_colors_a].set_color('red')
3200         xtick_labels[x_colors_b].set_color('blue')
3201         xtick_labels[x_colors_c].set_color('orange')
3202         xtick_labels[x_colors_d].set_color('magenta')
3203 
3204     # -------------------------------------------------------------------------------------- #
3205 
3206     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
3207     ax2 = ax1.twinx()
3208 
3209     # 图例文件描述-动态变化
3210     title_up = "本月测试  " + z_name_km1 + "  分布"
3211     legend_x3 = "input"
3212     legend_x4 = "output"
3213     legend_y3 = "yield"
3214     legend_y4 = "limit"
3215 
3216     # ====================================================================================================================#
3217     # 绘制柱状图
3218     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
3219     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
3220     bar3 = ax1.bar(bar_1_x, y_total_t1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
3221     bar4 = ax1.bar(bar_2_x, y_total_t2, label=legend_x4, color='gold', width=bar_width, linewidth=0.2, edgecolor="white")
3222     # 绘制柱描述
3223     for a, b, c in zip(bar_1_x, y_total_t1, y_total_t2):
3224         ax1.text(a - 0.1, b, '%d' % b, ha='center', va='bottom', fontsize=8, font=font, )
3225         ax1.text(a + 0.3, c, '%d' % c, ha='center', va='bottom', fontsize=8, font=font, )
3226 
3227     #
3228     # 绘制折线图
3229     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
3230     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
3231     line3 = ax2.plot(x_axle_n1, y_yield_t1, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
3232     line4 = ax2.plot(x_axle_n1, y_yield_t2, label=legend_y4, color='red', marker='.', markersize='6', ls='-')
3233 
3234     # 折线图点描述
3235     for a_x1, b_y3, c_y4 in zip(x_axle_n1, y_yield_t1, y_yield_t2):
3236         if b_y3 < c_y4:
3237             print("# 低于卡控线: ", a_x1, file=run_log)
3238             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=12, font=font)
3239         else:
3240             # print("# 正常模组: ", a_x1)
3241             ax2.text(a_x1, b_y3, '{:.2f}%'.format(b_y3 * 100), ha='center', va='bottom', fontsize=8, font=font)
3242             ax2.text(1, c_y4, '{:.2f}%'.format(c_y4 * 100), ha='center', va='bottom', fontsize=11, font=font)  # 只显示一个
3243 
3244     # ====================================================================================================================#
3245 
3246     # 设置x轴和y轴的标签,指明坐标含义
3247     ax1.set_xlabel(z_name_km1, fontdict={'size': 16})
3248     # 左边-y轴为:数量模式
3249     ax1.set_ylabel('模组数量', fontdict={'size': 16})
3250     # 右边-y轴为:百分比形式
3251     ax2.set_ylabel('百分比', fontdict={'size': 16})
3252 
3253     # 左-y轴为:刻度范围,动态调整
3254     max_value_r1 = int(max(y_total_t1) * 1.3)
3255     min_value_r1 = int(min(y_total_t2) * 0.9)
3256     if max_value_r1 < 5:
3257         max_value_r1 = 10  # 直接赋值
3258         min_value_r1 = 0  # 直接赋值
3259     ax1.set_ylim(min_value_r1, max_value_r1)
3260     #  右边-y轴为:最大值为100%,小数点2位
3261     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
3262 
3263     # 设置x轴和y轴刻度字体
3264     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
3265     [label.set_fontname('SimHei') for label in labels2]
3266 
3267     # 添加图表题  plt.title('双y轴折线图')
3268     plt.title(title_up, color="red", fontsize=16)
3269 
3270     # 设置轴标签颜色
3271     # ax1.tick_params('x', colors='Black')
3272     ax1.tick_params('y', colors='royalblue')
3273     ax2.tick_params('y', colors='tomato')
3274 
3275     # 设置轴颜色
3276     ax1.spines['left'].set_color('royalblue')
3277     ax2.spines['left'].set_color('royalblue')
3278     ax1.spines['right'].set_color('tomato')
3279     ax2.spines['right'].set_color('tomato')
3280 
3281     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
3282     ax1.spines['top'].set_visible(False)
3283     ax2.spines['top'].set_visible(False)
3284 
3285     # 添加图例函数:  plt.legend()
3286     # 添加图例 - 添加方向改为以下代码
3287     ax1.legend(loc='upper left')
3288     ax2.legend(loc='upper right')
3289     # 添加图例 - 将`图例合并改为以下代码
3290     # lines = line1 + line2 + line3 + line4
3291     # lines = line3 + line4
3292     # labels = [h.get_label() for h in lines]
3293     # plt.legend(lines, labels, loc='upper right')
3294 
3295     # 设置中文显示
3296     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
3297     plt.rcParams['axes.unicode_minus'] = False
3298 
3299     # 虚拟背景线
3300     plt.grid(True, linestyle="--")
3301 
3302     # 展示图片
3303     # plt.show()
3304     # 显示柱状图时间,单位s
3305     time_v1 = 1
3306     while time_v1 != 0:
3307         print('显示倒计时:%d s' % time_v1)
3308         plt.pause(1)
3309         time_v1 = time_v1 - 1
3310     print('直方图显示完成')
3311 
3312     # 图片保存对应文件
3313     picture_m = './6_result_ft_xx/picture/' + z_name_km1 + r".jpg"
3314     plt.savefig(picture_m)
3315     plt.draw()
3316     print('图片保存对应文件-完成')
3317     plt.close()  # 关闭图表显示
3318 
3319 
3320 '''
3321 # ====================================================================================================================#
3322 # 本月 --- 不良品BIN --- 测试数据汇总分布-通用模板2数据处理
3323 # ====================================================================================================================#
3324 '''
3325 
3326 
3327 def defective_h2_xx(x_p1, x_p2, x_p3, y_p1, y_p2, y_p3, y_p4, z_p1, z_p2, z_p3, z_p4):
3328     print("#**** defective_h2_xx ****# >>> ", z_p1)
3329     # 按照 仅handler-marking 分类
3330     # 按照 仅lot-marking 分类
3331     # 按照 lot - handler - marking 分类
3332     single_month_z2 = defective_reorder_sub(x_p1, x_p2, x_p3, z_p1, z_p2, z_p3, z_p4)
3333     # 按照 handler - lot - marking 分类
3334     # 按照 summary表-marking 顺序
3335 
3336     # 重新赋值 -single month raw data index
3337     x_axle_n1 = x_p1
3338     x_axle_n2 = x_p2
3339     x_axle_n3 = x_p3
3340     y_total_t1 = y_p1
3341     y_total_t2 = y_p2
3342     y_yield_t1 = y_p3
3343     y_yield_t2 = y_p4
3344     bin_name = z_p1
3345     month_n1 = z_p2
3346     single_month_d1 = single_month_z2
3347     raw_data_a1 = z_p4
3348     print('绘图处理: 月份< %d >  不良品< %s >' % (month_n1, bin_name))
3349     # 获取每月函数 有效数据 x_axle_n2
3350     x_name1, x_data1 = get_data_bin_v2(x_axle_n1, single_month_d1, raw_data_a1)
3351     x_name2, x_data2 = get_data_bin_v2(x_axle_n2, single_month_d1, raw_data_a1)
3352     x_name3, x_data3 = get_data_bin_v2(x_axle_n3, single_month_d1, raw_data_a1)
3353     y_name1, y_data1 = get_data_bin_v2(y_total_t1, single_month_d1, raw_data_a1)
3354     y_name2, y_data2 = get_data_bin_v2(y_total_t2, single_month_d1, raw_data_a1)
3355     y_name3, y_data3 = get_data_bin_v2(y_yield_t1, single_month_d1, raw_data_a1)
3356     y_name4, y_data4 = get_data_bin_v2(y_yield_t2, single_month_d1, raw_data_a1)
3357     # print(x_name1, x_data1)
3358     # print(x_name2, x_data2)
3359     # print(y_name1, y_data1)
3360     # print(y_name2, y_data2)
3361     # print(y_name3, y_data3)
3362 
3363     # ======================================================================================== #
3364 
3365     # 整体参数配置
3366     font = FontProperties(size=10)
3367     plt.rcParams["font.sans-serif"] = ['SimHei']
3368     plt.rcParams['axes.unicode_minus'] = False
3369     plt.rcParams['font.family'] = ['SimHei']
3370     plt.rcParams['font.sans-serif'] = ['SimHei']
3371     plt.rcParams['figure.figsize'] = (30, 10)
3372     plt.rc('font', family='SimHei', size=8)
3373 
3374     # 创建一个图形和两个y轴
3375     fig, ax1 = plt.subplots(1, 1)  # 绘制双Y轴 表示一次性在figure上创建成1*1的网格
3376 
3377     # 柱状图柱子宽度
3378     bar_width = 0.4
3379     x_ticks = range(len(x_data1))  # x轴刻度位置 | 折线图x位置
3380     bar_1_x = [(ii - bar_width + 0.2) for ii in x_ticks]  # 柱状图1 - x位置
3381     bar_2_x = [(ww - bar_width + 0.6) for ww in x_ticks]
3382 
3383     # 设置x轴刻度字体以及方向-单刻度标签
3384     labels1 = ax1.get_xticklabels() + ax1.get_yticklabels()
3385     [label.set_fontname('SimHei') for label in labels1]
3386     # plt.xticks(x_ticks, list(x_data1), rotation=90, )  #x轴刻度位置 | 刻度标签 | 旋转90度
3387 
3388     # 设置x轴刻度字体以及方向- 叠加双刻度标签
3389     labels = []
3390     for two_m1 in range(len(x_data1)):
3391         cell_m2 = x_data3[two_m1][0:6] + '   ' + x_data2[two_m1] + '   ' + x_data1[two_m1]
3392         labels.append(cell_m2)
3393     # labels = x_ticks  # 默认
3394     # print('2个叠加后的刻度标签: ',labels)   # 2个叠加后的刻度标签
3395     plt.xticks(x_ticks, labels, rotation=90, )  # x轴刻度位置 | 刻度标签 | 旋转90度
3396     # 自适应调整布局+ 指定 解决X轴范围问题
3397     fig.autofmt_xdate(rotation=90)
3398 
3399     # -------------------------------------------------------------------------------------- #
3400     # # 同一刻度标签标记为不同颜色 插孔法  升级-适用较为复杂的场景  第2种方案
3401     index_lot_v5 = []
3402     for index_a in range(len(single_month_d1)):
3403         index_lot = single_month_d1[index_a]  # 获取本月行号 索引值
3404         index_m1 = x_data3[index_a][0:6]  # 获取本月行号 索引值
3405         index_lot_v5.append(index_m1)
3406     # all raw data 有效映射
3407     # print("all raw data 有效映射:", index_lot_v5)
3408     # 获取同一列表中相同元素,只保留一种类型
3409     one_lot_v1 = []
3410     for v2_lot in index_lot_v5:
3411         if v2_lot not in one_lot_v1:
3412             one_lot_v1.append(v2_lot)
3413     # print('lot中唯一代表名称: ', one_lot_v1)
3414     xtick_labels = ax1.get_xticklabels()
3415     colors = ['red', 'green', 'blue', 'purple', 'orange', 'brown', 'gray', 'pink', 'cyan', 'magenta', 'yellow', 'black', ]
3416     # 利用唯一lot去适配列表lot,影射到对应刻度,根据余数去自动识别颜色,默认10种
3417     for x_color in range(len(x_data3)):
3418         # print("x_color: ",x_color,x_data3[x_color][0:6])
3419         for one_c1 in range(len(one_lot_v1)):
3420             # print("Index:", one_c1, "Value:", one_lot_v1[one_c1])
3421             if one_lot_v1[one_c1] == x_data3[x_color][0:6]:
3422                 one_color_v1 = one_c1 % 10
3423                 if one_color_v1 == 0:
3424                     xtick_labels[x_color].set_color(colors[0])
3425                 elif one_color_v1 == 1:
3426                     xtick_labels[x_color].set_color(colors[1])
3427                 elif one_color_v1 == 2:
3428                     xtick_labels[x_color].set_color(colors[2])
3429                 elif one_color_v1 == 3:
3430                     xtick_labels[x_color].set_color(colors[3])
3431                 elif one_color_v1 == 4:
3432                     xtick_labels[x_color].set_color(colors[4])
3433                 elif one_color_v1 == 5:
3434                     xtick_labels[x_color].set_color(colors[5])
3435                 elif one_color_v1 == 6:
3436                     xtick_labels[x_color].set_color(colors[6])
3437                 elif one_color_v1 == 7:
3438                     xtick_labels[x_color].set_color(colors[7])
3439                 elif one_color_v1 == 8:
3440                     xtick_labels[x_color].set_color(colors[8])
3441                 elif one_color_v1 == 9:
3442                     xtick_labels[x_color].set_color(colors[9])
3443         # -------------------------------------------------------------------------------------- #
3444 
3445     # 绘制双Y轴 让2个X轴一样,同时创建副坐标轴
3446     ax2 = ax1.twinx()
3447 
3448     # 图例文件描述-动态变化
3449     title_up = "本月测试  " + bin_name + "  分布"
3450     legend_x3 = y_name1
3451     legend_x4 = y_name2
3452     legend_y3 = y_name3
3453     legend_y4 = y_name4
3454 
3455     # ====================================================================================================================#
3456     # 绘制柱状图
3457     # bar1 = ax1.bar(bar_1_x, y_data1, label='y1轴', color='lightblue', width=0.4)
3458     # bar2 = ax1.bar(bar_2_x, y_data2, label='y2轴', color='gold', width=0.4)
3459     bar3 = ax1.bar(bar_1_x, y_data1, label=legend_x3, color='lightblue', width=bar_width, linewidth=0.2, edgecolor="white")
3460     bar4 = ax1.bar(bar_2_x, y_data2, label=legend_x4, color='gold', width=bar_width, linewidth=0.2, edgecolor="white")
3461 
3462     # 绘制折线图
3463     # line1 = ax1.plot(x_data1, y_data1, label='y1轴', color='royalblue', marker='o', ls='-.')
3464     # line2 = ax2.plot(x_data1, y_data2, label='y2轴', color='tomato', marker='o', ls='--')
3465     line3 = ax2.plot(x_data1, y_data3, label=legend_y3, color='Lightgreen', marker='o', markersize='6', ls='--')
3466     line4 = ax2.plot(x_data1, y_data4, label=legend_y4, color='royalblue', marker='.', markersize='6', ls='-')
3467 
3468     # ------------------------------------------------------------------------------------------------------------------- #
3469     # #TODO  <特殊情况处理 -20231211>
3470     # ------------------------------------------------------------------------------------------------------------------- #
3471     legend_y5 = "sbl"  # 新增sbl 卡控图例名称
3472 
3473     if bin_name == "BIN3":
3474         y_data5 = []
3475         sbl_data = 0.0021
3476         for sbl_avocado in range(len(y_data4)):
3477             y_data5.append(sbl_data)
3478         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3479         # 折线图点描述
3480         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3481             if b_y3 < b_y4:
3482                 print("# BIN3 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3483                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3484             if b_y4 > c_y5:
3485                 print("# BIN3 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3486                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3487             # 只显示一个 sbl
3488             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3489 
3490     elif bin_name == "BIN4":
3491         y_data5 = []
3492         sbl_data = 0.0004
3493         for sbl_avocado in range(len(y_data4)):
3494             y_data5.append(sbl_data)
3495         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3496         # 折线图点描述
3497         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3498             if b_y3 < b_y4:
3499                 print("# BIN4 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3500                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3501             if b_y4 > c_y5:
3502                 print("# BIN4 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3503                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3504             # 只显示一个 sbl
3505             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3506 
3507     elif bin_name == "BIN5":
3508         y_data5 = []
3509         sbl_data = 0.033
3510         for sbl_avocado in range(len(y_data4)):
3511             y_data5.append(sbl_data)
3512         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3513         # 折线图点描述
3514         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3515             if b_y3 < b_y4:
3516                 print("# BIN5 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3517                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3518             if b_y4 > c_y5:
3519                 print("# BIN5 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3520                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3521             # 只显示一个 sbl
3522             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3523 
3524     elif bin_name == "BIN6_1":
3525         y_data5 = []
3526         sbl_data = 0.0489
3527         for sbl_avocado in range(len(y_data4)):
3528             y_data5.append(sbl_data)
3529         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3530         # 折线图点描述
3531         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3532             if b_y3 < b_y4:
3533                 print("# BIN6_1 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3534                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3535             if b_y4 > c_y5:
3536                 print("# BIN6_1 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3537                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3538             # 只显示一个 sbl
3539             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3540 
3541     elif bin_name == "BIN6_2":
3542         y_data5 = []
3543         sbl_data = 0.0031
3544         for sbl_avocado in range(len(y_data4)):
3545             y_data5.append(sbl_data)
3546         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3547         # 折线图点描述
3548         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3549             if b_y3 < b_y4:
3550                 print("# BIN6_2 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3551                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3552             if b_y4 > c_y5:
3553                 print("# BIN6_2 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3554                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3555             # 只显示一个 sbl
3556             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3557 
3558     elif bin_name == "BIN7_1":
3559         y_data5 = []
3560         sbl_data = 0.0010
3561         for sbl_avocado in range(len(y_data4)):
3562             y_data5.append(sbl_data)
3563         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3564         # 折线图点描述
3565         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3566             if b_y3 < b_y4:
3567                 print("# BIN7_1 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3568                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3569             if b_y4 > c_y5:
3570                 print("# BIN7_1 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3571                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3572             # 只显示一个 sbl
3573             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3574 
3575     elif bin_name == "BIN7_2":
3576         y_data5 = []
3577         sbl_data = 0.001
3578         for sbl_avocado in range(len(y_data4)):
3579             y_data5.append(sbl_data)
3580         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3581         # 折线图点描述
3582         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3583             if b_y3 < b_y4:
3584                 print("# BIN7_2 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3585                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3586             if b_y4 > c_y5:
3587                 print("# BIN7_2 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3588                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3589             # 只显示一个 sbl
3590             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3591 
3592     elif bin_name == "BIN7_3":
3593         y_data5 = []
3594         sbl_data = 0.0001
3595         for sbl_avocado in range(len(y_data4)):
3596             y_data5.append(sbl_data)
3597         line5 = ax2.plot(x_data1, y_data5, label=legend_y5, color='tomato', marker='.', markersize='6', ls='-')
3598         # 折线图点描述
3599         for a_x1, b_y3, b_y4, c_y5 in zip(x_data1, y_data3, y_data4, y_data5):
3600             if b_y3 < b_y4:
3601                 print("# BIN7_3 sbl卡控 fail 良率高于 实际bin fail良率: ", a_x1, file=run_log2)
3602                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3603             if b_y4 > c_y5:
3604                 print("# BIN7_3 sbl卡控 fail 良率高于SBL卡控线: ", a_x1, file=run_log2)
3605                 ax2.text(a_x1, b_y4, '{:.2f}%'.format(b_y4 * 100), ha='center', va='bottom', fontsize=9, font=font)
3606             # 只显示一个 sbl
3607             ax2.text(1, c_y5, '{:.2f}%'.format(c_y5 * 100), ha='center', va='bottom', fontsize=9, font=font)  # 只显示一个
3608     else:
3609         print("无符合case 的 bin")
3610     #
3611     # ====================================================================================================================#
3612 
3613     # 设置x轴和y轴的标签,指明坐标含义
3614     ax1.set_xlabel('lot ID', fontdict={'size': 16})
3615     # 左边-y轴为:数量模式
3616     ax1.set_ylabel('模组数量', fontdict={'size': 16})
3617     # 右边-y轴为:百分比形式
3618     ax2.set_ylabel('百分比', fontdict={'size': 16})
3619 
3620     # 左-y轴为:刻度范围,动态调整
3621     max_value_r1 = int(max(y_data1) * 1.3)
3622     min_value_r1 = int(min(y_data1) * 0.9)
3623     if max_value_r1 < 5:
3624         max_value_r1 = 10  # 直接赋值
3625         min_value_r1 = 0  # 直接赋值
3626     ax1.set_ylim(min_value_r1, max_value_r1)
3627     #  右边-y轴为:最大值为100%,小数点2位
3628     ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=2))
3629 
3630     # 设置x轴和y轴刻度字体
3631     labels2 = ax2.get_xticklabels() + ax2.get_yticklabels()
3632     [label.set_fontname('SimHei') for label in labels2]
3633 
3634     # 添加图表题  plt.title('双y轴折线图')
3635     plt.title(title_up, color="red", fontsize=16)
3636 
3637     # 设置轴标签颜色
3638     # ax1.tick_params('x', colors='Black')
3639     ax1.tick_params('y', colors='royalblue')
3640     ax2.tick_params('y', colors='tomato')
3641 
3642     # 设置轴颜色
3643     ax1.spines['left'].set_color('royalblue')
3644     ax2.spines['left'].set_color('royalblue')
3645     ax1.spines['right'].set_color('tomato')
3646     ax2.spines['right'].set_color('tomato')
3647 
3648     # 两个y轴的颜色改变确实要好看一点,但是上轴线有点突兀,把它去掉
3649     ax1.spines['top'].set_visible(False)
3650     ax2.spines['top'].set_visible(False)
3651 
3652     # 添加图例函数:  plt.legend()
3653     # 添加图例 - 添加方向改为以下代码
3654     ax1.legend(loc='upper left')
3655     ax2.legend(loc='upper right')
3656     # 添加图例 - 将`图例合并改为以下代码
3657     # lines = line1 + line2 + line3 + line4
3658     # lines = line3 + line4
3659     # labels = [h.get_label() for h in lines]
3660     # plt.legend(lines, labels, loc='upper right')
3661 
3662     # 设置中文显示
3663     plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来设置字体样式以正常显示中文标签(黑体)
3664     plt.rcParams['axes.unicode_minus'] = False
3665 
3666     # 虚拟背景线
3667     plt.grid(True, linestyle="--")
3668 
3669     # 展示图片
3670     # plt.show()
3671     # 显示柱状图时间,单位s
3672     time_v1 = 1
3673     while time_v1 != 0:
3674         print('显示倒计时:%d s' % time_v1)
3675         plt.pause(1)
3676         time_v1 = time_v1 - 1
3677     print('直方图显示完成')
3678 
3679     # 图片保存对应文件
3680     picture_m = './6_result_ft_xx/picture/' + bin_name + r".jpg"
3681     plt.savefig(picture_m)
3682     plt.draw()
3683     print('图片保存对应文件-完成')
3684     plt.close()  # 关闭图表显示
3685 
3686 
3687 '''
3688 # ====================================================================================================================#
3689 # 本月数据 -生成报告汇总
3690 # ====================================================================================================================#
3691 '''
3692 
3693 
3694 def generate_report_ft_xx(z_y1):
3695     print("#**** generate_report_ft_xx ****#")
3696     month_real = str(z_y1)
3697     # ---------------------------------------------------------- #
3698     # 创建路径 / 文件夹 - 逻辑处理任意问题
3699     month_name_s = "month_" + month_real
3700     bin8_p = "\\6_result_ft_xx\\month_report\\" + month_name_s
3701     mk_file_path_v1 = os.getcwd() + bin8_p  # 获取当前工作目录路径
3702     if os.path.exists(mk_file_path_v1):
3703         shutil.rmtree(mk_file_path_v1)
3704     os.mkdir(mk_file_path_v1)
3705     print("# 创建报告生成工作目录", mk_file_path_v1)
3706     mk1_file_name = mk_file_path_v1
3707     # ---------------------------------------------------------- #
3708 
3709     # 拷贝文件到对应月份文件中
3710     source_folder1 = r'./6_result_ft_xx/picture'
3711     target_folder2 = mk1_file_name + '/picture'
3712     shutil.copytree(source_folder1, target_folder2)
3713 
3714     # 讯芯-vi5300-ft-xx    月份+路径
3715     month_report_ft_xx(month_real, target_folder2)
3716 
3717 
3718 '''
3719 # ====================================================================================================================#
3720 # month_report_ft_xx 获取html模板-ft伟测
3721 # ====================================================================================================================#
3722 '''
3723 
3724 
3725 def month_report_ft_xx(z_y1, z_y2):
3726     print("************ month_report_ft_xx **********")
3727     # 获取有效值
3728     source_folder2 = z_y2 + "/月度_汇总统计结果.xlsx"
3729     # print("h获取有效的excel",source_folder2)
3730     work_book2 = openpyxl.load_workbook(source_folder2)
3731     worksheet_b2 = work_book2.active
3732     target_rows_x2 = worksheet_b2.max_row
3733     target_cols_y2 = worksheet_b2.max_column
3734     print("行列:", target_rows_x2, target_cols_y2)
3735     s_status = worksheet_b2.cell(2, 2).value
3736     s_yield = worksheet_b2.cell(2, 3).value
3737     s_limit = worksheet_b2.cell(2, 4).value
3738     s_input = worksheet_b2.cell(2, 5).value
3739     s_output = worksheet_b2.cell(2, 6).value
3740     # print(s_status, s_yield, s_limit, s_input, s_output)
3741 
3742     #
3743     s_month = z_y1
3744     total_status = s_status
3745     total_yield_p = s_yield
3746     total_limit_p = s_limit
3747     total_input = s_input
3748     total_output = s_output
3749     # ----------------------------------------------------------------------------------------------- #
3750 
3751     # vi5300_ft_wc_report_template
3752     # get_data_txt_v1 = open(r'C:\Users\chucheng.cao\Desktop\work\python\test_data\test_month_report_xx\note\bin1.txt', encoding='utf-8')
3753     # txt_v1 = []
3754     # for line in get_data_txt_v1:
3755     #     txt_v1.append(line.strip())
3756     # print('添加测试:',txt_v1[0])
3757 
3758     body = []
3759     # txt_bin1 = "BIN1" + txt_v1[0]
3760     txt_bin1 = "BIN1"
3761     txt_handler = "handler"
3762     txt_lot = "lot"
3763     txt_bin3 = "BIN3"
3764     txt_bin4 = "BIN4"
3765     txt_bin5 = "BIN5"
3766     txt_bin6_1 = "BIN6_1"
3767     txt_bin6_2 = "BIN6_2"
3768     txt_bin7_1 = "BIN7_1"
3769     txt_bin7_2 = "BIN7_2"
3770     txt_bin7_3 = "BIN7_3"
3771     txt_bin9 = "BIN9"
3772     txt_bin13 = "BIN13"
3773     txt_bin14 = "BIN14"
3774     txt_bin_vm = "BIN_vm"
3775     txt_bin_loss = "BIN_loss"
3776     # 图片路径
3777     # 当前绝对路径-建议使用相对路径
3778     source_bin1 = os.getcwd()
3779     Picture_bin1 = "\\6_result_ft_xx\\month_report"
3780     picture_bin2 = "\\month_" + s_month + "\\picture\\"
3781     Picture_bin_route = source_bin1 + Picture_bin1 + picture_bin2
3782     print("图片路径目录:", Picture_bin_route)
3783 
3784     result = {'serial': "1",
3785               'SYL': total_limit_p,
3786               'Total': total_input,
3787               'BIN': total_output,
3788               'Yield': total_yield_p,
3789               'states': total_status,
3790               'Picture_bin1': Picture_bin_route + "BIN1.jpg", 'describe_bin1': txt_bin1,
3791               'Picture_handler': Picture_bin_route + "handler.jpg", 'describe_handler': txt_handler,
3792               'Picture_lot': Picture_bin_route + "lot.jpg", 'describe_lot': txt_lot,
3793               'Picture_bin3': Picture_bin_route + "BIN3.jpg", 'describe_bin3': txt_bin3,
3794               'Picture_bin4': Picture_bin_route + "BIN4.jpg", 'describe_bin4': txt_bin4,
3795               'Picture_bin5': Picture_bin_route + "BIN5.jpg", 'describe_bin5': txt_bin5,
3796               'Picture_bin6_1': Picture_bin_route + "BIN6_1.jpg", 'describe_bin6': txt_bin6_1,
3797               'Picture_bin6_2': Picture_bin_route + "BIN6_2.jpg", 'describe_bin6_2': txt_bin6_2,
3798               'Picture_bin7_1': Picture_bin_route + "BIN7_1.jpg", 'describe_bin7_1': txt_bin7_1,
3799               'Picture_bin7_2': Picture_bin_route + "BIN7_2.jpg", 'describe_bin7_2': txt_bin7_2,
3800               'Picture_bin7_3': Picture_bin_route + "BIN7_3.jpg", 'describe_bin7_3': txt_bin7_3,
3801               }
3802     body.append(result)
3803     start_monthly = "2023." + str(s_month) + ".1"
3804     stop_monthly = "2023." + str(s_month) + ".30"
3805     # html_vi5300_ft_wc(body, start_monthly, stop_monthly, s_month)
3806 
3807     env = Environment(loader=FileSystemLoader(r'./6_result_ft_xx/month_report/'))
3808     test_report = env.get_template('vi5300_ft_xx_report_template.html')
3809     monthly_V12_data = "./6_result_ft_xx/month_report/month_" + s_month + "/report_" + s_month + "monthly_result.html"
3810     with open(monthly_V12_data, 'w+') as fout:
3811         html_content = test_report.render(start_time=start_monthly, stop_time=stop_monthly, body=body)
3812         fout.write(html_content)
3813 
3814     # 将HTML文件转换为PDF文件
3815     # pdfkit.from_file( 'report_11monthly_result.html', 'report_11monthly_result.pdf')
3816     # --------------------------------------------------------------------------------------------------------------#
3817     datetime_object_21 = datetime.datetime.now()
3818     print("datetime_object_21 :", datetime_object_21)
3819 
3820 
3821 '''
3822 #---------------------------------------------------------------------------------------------------------------#
3823 #  sop_s1_s1   
3824 #---------------------------------------------------------------------------------------------------------------#
3825 '''
3826 
3827 
3828 def sop_s1_s1():
3829     global run_log
3830     run_log = open('./4_result_ft/picture/run_data_log.txt', 'w')
3831     # C:\Users\chucheng.cao\Desktop\work\python\test_data\handle_vi5300_ft_wc\1_version\20231212-1015-完成报告生成\4_result_ft\picture
3832     print("读取summary表生成可视化图表", file=run_log)
3833     input_path_t0 = r'./3_summary_ft'  # path定义要获取的文件名称的目录
3834     print("定义要获取的文件名称的目录: ", input_path_t0, file=run_log)
3835     all_data = read_excel(input_path_t0)  # 读取文件,并且获取所有内容
3836     vi5300_ft_wc_handle_v1(all_data)
3837     run_log.close()
3838 
3839 
3840 '''
3841 #---------------------------------------------------------------------------------------------------------------#
3842 #  sop_s2_s1   
3843 #---------------------------------------------------------------------------------------------------------------#
3844 '''
3845 
3846 
3847 def sop_s2_s1():
3848     global run_log2
3849     run_log2 = open('./6_result_ft_xx/picture/run_data_log2.txt', 'w')
3850     print("读取summary表生成可视化图表", file=run_log2)
3851 
3852     input_path_xx = r'./5_summary_ft_xx'  # path定义要获取的文件名称的目录
3853     print("定义要获取的文件名称的目录: ", input_path_xx, file=run_log2)
3854 
3855     file_name_list = os.listdir(input_path_xx)  # os.listdir()方法获取文件夹名字,返回数组
3856     print("获取文件夹列表:\n", file_name_list)
3857 
3858     # 拼接路径 -- 仅仅获取第一个
3859     input_path_s2 = input_path_xx + '\\' + file_name_list[0]
3860     # 读取文件
3861     work_pd2 = pd.read_excel(io=input_path_s2, sheet_name=0, header=None)  #
3862     pd.set_option('display.max_columns', None)  # 显示完整的行
3863     pd.set_option('display.max_rows', None)  # 显示完整的列
3864     pd.set_option('display.expand_frame_repr', False)  # 设置不折叠数据
3865     pd.set_option('display.float_format', lambda x: '%.2f' % x)  # 设置不以科学计数法显示
3866     # print("显示读取excel全部内容: \n",work_pd2)
3867 
3868     vi5300_ft_xx_handle_v2(work_pd2)
3869     run_log2.close()
3870 
3871 
3872 '''
3873 #==================================================================================================================#
3874 #
3875 #main
3876 #
3877 #==================================================================================================================#
3878 '''
3879 if __name__ == '__main__':
3880     print("开始测试")
3881 
3882     # sop_s1_s1()
3883     # sop_s2_s1()
3884 
3885     run_big_cycle1 = 1
3886     while run_big_cycle1:
3887         print("请选择以下场景: [提示 0:表示退出]")
3888         print("scenario 1: VI5300 FT 伟测(wc) summary表自动生成报表 ")
3889         print("scenario 2: VI5300 FT 讯芯(xx) summary表自动生成报表")
3890         print(">>> 请输入功能:")
3891         function_order = input()
3892         if function_order == "0":
3893             print("退出运行")
3894             run_big_cycle1 = 0
3895         elif function_order == "1":
3896             print("scenario 1")
3897             run_s1 = 1
3898             while run_s1:
3899                 print("scenario_1场景: [提示 0:表示退出]")
3900                 print("scenario_1  1: VI5300 FT 伟测(wc) summary表自动生成报表 - auto·")
3901                 print(">>> 请输入功能:")
3902                 function_order_s1 = input()
3903                 if function_order_s1 == "0":
3904                     print("退出运行")
3905                     run_s1 = 0
3906                 elif function_order_s1 == "1":
3907                     sop_s1_s1()
3908                     print("完成s1 1功能")
3909                 else:
3910                     print("输入无效数值!")
3911 
3912                 print("继续执行: y  返回上一级:b")
3913                 mean_m = input()
3914                 if mean_m == "b":
3915                     function_order_s1 = "0"
3916                     run_s1 = 0
3917         # --------------------------------------------- 2 #
3918         elif function_order == "2":
3919             print("scenario 2")
3920             run_s2 = 1
3921             while run_s2:
3922                 print("scenario_2场景: [提示 0:表示退出]")
3923                 print("scenario_2  1: VI5300 FT 讯芯(xx) summary表自动生成报表 -auto.")
3924                 print(">>> 请输入功能:")
3925                 function_order_s2 = input()
3926                 if function_order_s2 == "0":
3927                     print("退出运行")
3928                     run_s2 = 0
3929                 elif function_order_s2 == "1":
3930                     sop_s2_s1()
3931                     print("完成s2 1功能")
3932                 else:
3933                     print("输入无效数值!")
3934 
3935                 print("继续执行: y  返回上一级:b")
3936                 mean_m = input()
3937                 if mean_m == "b":
3938                     function_order_s2 = "0"
3939                     run_s2 = 0
3940         # --------------------------------------------- 2 #
3941         else:
3942             print("没有此功能请重新选择")

 

#---- code end ----#

交互界面套用固定模版复用

 

posted @ 2023-12-15 19:50  楚格  阅读(35)  评论(0编辑  收藏  举报