# # coding = utf-8
# import os
# try:
#     import tensorboardX
#     tbx = tensorboardX
# except:
#     print('WARNING: no tensorboardX installed, tensorboard file may not be saved.')
#     tbx = ''

# import argparse
# import xml.etree.ElementTree as ET
# import time
# import json
# import shutil
# import numpy as np
# from multiprocessing import Process, Manager


# class DLAlgBase(object):
#     """
#         算法集成的功能类，只是基础类
#     Args:

#     """
#     @classmethod
#     def init(cls, save_dir=None):
#         global tbx
#         if not save_dir:
#             cls.save_dir = os.getenv("save_dir")
#         else:
#             cls.save_dir = save_dir
#         if not cls.save_dir:
#             print('[ERROR] please input save_dir or set env of it.')
#             return
#         print('[ENV] save_dir', cls.save_dir)
#         cls._init_model_package()

#         if tbx:
#             # tensorbordX 写入
#             cls.writer = tbx.SummaryWriter(cls.save_log_dir)

#         # 获取数据集信息
#         cls.dataloader_type = os.getenv('dataloader_type')
#         if cls.dataloader_type == 'hikmars3':
#             cls.dataset_type = os.getenv("dataset_type")
#             cls.dataset_usage = os.getenv("dataset_usage")
#             cls.dataset_name = os.getenv("dataset_name")
#             cls.dataset_version = os.getenv("dataset_version")
#             cls.dataset_dir = os.path.join('/hikmars3', 'public', 'dataset', 'data_mng',
#                                            cls.dataset_type, cls.dataset_name, cls.dataset_version)
#         else:
#             cls.dataset_dir = os.getenv("data_dir")
#             cls.dataset_type = ""
#             cls.dataset_usage = ""
#             cls.dataset_name = ""
#             cls.dataset_version = ""

#         cls.code_dir = os.getenv("code_dir")
#         cls.resource_type = os.getenv("resourcetype")
#         cls.resource_num = os.getenv("resourcenum")

#         cls.task_name = ""  # os.getenv("task_name")

#         pretrained = os.getenv('pretrain')
#         cls.pretrain_path = None
#         if pretrained == "true":
#             cls.pretrain_path = os.getenv('restore_model_path')
#         cls._init_config_json()

#     @classmethod
#     def _init_model_package(cls):
#         """
#         初始化模型包的格式
#         """
#         '''
#         模型包包含`log`, `model`，和`config`三部分，其中,
#         `log`中包含用于可视化模型结构及结果的`tensorboard`文件，
#         `model`包含训练输出的模型文件，
#         `config`包含该模型版本的基础信息和在其创建的模型评估、模型压缩、模型转换任务。
#         '''
#         cls.save_model_dir = os.path.join(cls.save_dir, "model")
#         cls.save_log_dir = os.path.join(cls.save_dir, "log")
#         cls.save_cfg_dir = os.path.join(cls.save_dir, "config")
#         # 由于创建训练时会初始化旧版本的模型包，但是在该代码编写时模型包已经改了，
#         # 所以需要将旧版本的删除，后续可以删除下面的代码
#         for path in [cls.save_model_dir, cls.save_cfg_dir, cls.save_log_dir]:
#             # if os.path.exists(path):
#             #     shutil.rmtree(path)
#             os.makedirs(path, exist_ok=True)

#     @classmethod
#     def _init_config_json(cls):
#         """
#         初始化配置文件夹里的文件，由于是json文件，
#         因此先用一个变量记住，后续一次性保存
#         """
#         cls.config = {
#             "user": "",
#             "preset": "",
#             "name": "",
#             "usage": "",
#             "engine": "",
#             "scene": "",
#             "model_type": "",
#             "description": "",
#             "version_info":
#                 {
#                     "version": "",
#                     "tag": "",
#                     "model_path": "",
#                     "algorithm_name": os.path.basename(cls.code_dir),
#                     "algorithm_path": cls.code_dir,
#                     "framework": "",
#                     "image": {},
#                     "dataset_type": cls.dataset_type,
#                     "dataset_usage": cls.dataset_usage,
#                     "dataset_name": '-'.join([cls.dataset_name, cls.dataset_version]),
#                     "dataset_path": cls.dataset_dir,
#                     "create_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())),
#                     "resource_type": cls.resource_type,
#                     "resource_num": cls.resource_num,
#                     "hyperparameter": {},
#                     "log_path": cls.save_log_dir,
#                     "model_size": "",
#                     "isdeploy": "",
#                     "train_metrics": {},  # 训练集评估信息
#                     "val_metrics": {},  # 验证集评估信息
#                     "model_graph": ""
#                 }
#         }
#         # print('=============config')
#         # print(cls.config)
#         # print(' ')

#     @classmethod
#     def download_dataset(cls, path):
#         """
#         下载数据到指定路径
#         """
#         print("dataset starts to download...")
#         if os.path.exists(path):
#             # raise Exception("%s 已经存在！"%path)
#             shutil.rmtree(path)
#         shutil.copytree(cls.dataset_dir, path)
#         print("dataset downloads done.")

#     @classmethod
#     def get_dataset_dir(cls):
#         return cls.dataset_dir

#     @classmethod
#     def get_pretrained_model(cls):
#         return cls.pretrain_path

#     @classmethod
#     def visual_summary(cls, data, step, name="scalars"):
#         """
#         将训练过程中的数据写入log文件，方便tensorboard可视化
#         Args:
#             data: 字典格式，每个step的保存数据，例如{'loss': 0.2, 'avg loss': 0.1}
#             step: 整型，训练步数
#         """
#         global tbx
#         if not tbx:
#             print(
#                 'ERROR: no tensorboardX or tensorboard installed, can not save tensorboard file.')
#             return
#         event_path = os.path.join(cls.save_log_dir, name)
#         for k, v in data.items():
#             path = os.path.join(event_path, k, "events.bin")
#             value = [step, v, float(time.time())]
#             if os.path.exists(path):
#                 save_data = np.fromfile(path, dtype=np.float)
#             else:
#                 os.makedirs(os.path.dirname(path))
#                 save_data = np.array([])
#             save_data = np.insert(save_data, len(save_data), value)
#             save_data.tofile(path)

#         cls.writer.add_scalars(name, data, step)

#     @classmethod
#     def write_train_metrics(cls, info_dict):
#         '''
#         写训练集评估信息
#         :param dict: 训练集评估信息字典，例如 {"acc": 0.90, "loss": 0.02}
#         :return:
#         '''
#         cls.config['version_info']['train_metrics'] = info_dict
#         # 保存该模型版本的基础信息
#         with open(os.path.join(cls.save_cfg_dir, 'modelmgt.json'), 'w+') as config_file:
#             json.dump(cls.config, config_file)

#     @classmethod
#     def write_val_metrics(cls, info_dict):
#         '''
#         写验证集评估信息
#         :param dict: 验证集评估信息字典，例如 {"acc": 0.90, "loss": 0.02}
#         :return:
#         '''
#         cls.config['version_info']['val_metrics'] = info_dict
#         # 保存该模型版本的基础信息
#         with open(os.path.join(cls.save_cfg_dir, 'modelmgt.json'), 'w+') as config_file:
#             json.dump(cls.config, config_file)

#     @classmethod
#     def save_from_file(cls, file):
#         '''
#         将模型和配置文件保存到对应目录下
#         :param file: 模型文件路径
#         :return:
#         '''
#         # 保存该模型版本的基础信息
#         with open(os.path.join(cls.save_cfg_dir, 'modelmgt.json'), 'w+') as config_file:
#             json.dump(cls.config, config_file)
#         # 保存模型
#         try:
#             shutil.copy(file, cls.save_model_dir)
#         except Exception as e:
#             print(e)
#             pass

#     @classmethod
#     def save_model_graph(cls, img_path):
#         '''
#         将配置参数文件保存到对应目录下
#         :param file: 配置文件
#         :return:
#         '''
#         try:
#             shutil.copy(img_path, cls.save_model_dir)
#         except Exception as e:
#             print(e)
#             pass

#         save_img_path = os.path.join(
#             cls.save_model_dir, os.path.basename(img_path))
#         cls.config['version_info']['model_graph'] = save_img_path
#         with open(os.path.join(cls.save_cfg_dir, 'modelmgt.json'), 'w+') as config_file:
#             json.dump(cls.config, config_file)

#     @classmethod
#     def save_config_file(cls, files):
#         '''
#         将配置参数文件保存到对应目录下
#         :param file: 配置文件
#         :return:
#         '''
#         for f in files:
#             try:
#                 shutil.copy(f, cls.save_cfg_dir)
#             except Exception as e:
#                 print(e)
#                 pass

#     @classmethod
#     def save_classes_info_from_dict(cls, info_dict):
#         '''
#         写 模型输出标签映射表到classes.csv
#         :param dict: 映射信息字典，例如 {"car": 100, "dog": 2}
#         :return:
#         '''
#         with open(os.path.join(cls.save_cfg_dir, 'classes.csv'), 'w+') as csv_file:
#             for k, v in info_dict.items():
#                 csv_file.write("{},{}\n".format(k, v))

#     @classmethod
#     def save_classes_info_from_file(cls, csv_file):
#         '''
#         保存 模型输出标签映射表到指定路径，并重命名成classes.csv
#         '''
#         shutil.copy(csv_file, cls.save_cfg_dir)
#         base_name = os.path.basename(csv_file)
#         os.rename(os.path.join(cls.save_cfg_dir, base_name),
#                   os.path.join(cls.save_cfg_dir, 'classes.csv'))

#     @classmethod
#     def save_infer_json(cls, info_dict):
#         '''
#         将字典信息转换成推理所需的配置文件按
#         :param dict: 映射信息字典，例如 {"anchor": 100, "label": 2}
#         :return:
#         '''
#         if "anchor" in info_dict and "label" in info_dict and "type" in info_dict and "inputSize" in info_dict:
#             with open(os.path.join(cls.save_model_dir, 'obj_det_cfg.json'), 'w+') as json_file:
#                 data = json.dumps(info_dict)
#                 json_file.write(data)
#         else:
#             print("格式不正确！请检查是否有anchor, label, type, inputSize等字段")

#     @classmethod
#     def init_metric(cls, save_dir=None):
#         '''
#         将字典信息转换成推理所需的配置文件
#         '''
#         if not save_dir:
#             cls.eval_result_dir = os.getenv("save_dir")
#         else:
#             cls.eval_result_dir = save_dir
#         cls.eval_metrics_dir = os.path.join(cls.eval_result_dir, "metrics")
#         cls.eval_detail_dir = os.path.join(cls.eval_result_dir, "results")
#         for path in [cls.eval_metrics_dir, cls.eval_detail_dir]:
#             # if os.path.exists(path):
#             #     shutil.rmtree(path)
#             os.makedirs(path, exist_ok=True)

#     @classmethod
#     def save_metric_index(cls, brief_index, detail_index, pie_charts):
#         '''
#         # brief_index, dict_format
#          {
#             "Macro-Precision": "90.13%",
#             "Macro-Recall": "86.15%",
#             "Macro-F1-Score": "87.05%",
#             "Accuracy": "94.31%"
#         }

#         # detail_index, dict_format
#         {
#             "50": {
#                 "Precision": "79.27%",
#                 "Recall": "98.08%",
#                 "F1-Score": "87.68%",
#                 "pr_img_path": "/hikmars4/users/zyl/hikframe/PR/50.png"
#             },
#         }

#         # pie_chart_list, list of dict
#         {
#             "误检性分析": {
#                 "正确检出": 2966,
#                 "错误检测": 179
#             },
#         }

#         '''
#         if not cls.eval_metrics_dir:
#             print('please init_metric first.')
#             return

#         metric_file = os.path.join(cls.eval_metrics_dir, 'metrics.json')
#         shutil.rmtree(metric_file, ignore_errors=True)
#         metrics_dict = {
#             "index": {"brief": {}, "detail": []}, "chart": {}
#         }
#         metrics_dict["index"]["brief"] = brief_index
#         detail_index_list = [{k: v} for k, v in detail_index.items()]
#         metrics_dict["index"]["detail"] = detail_index_list
#         metrics_dict["chart"] = pie_charts
#         with open(os.path.join(metric_file), "w") as f:
#             json.dump(metrics_dict, f)

#     @classmethod
#     def save_metric_detail(cls, right_rets=None, wrong_rets=None):
#         """
#         right_rets/wrong_rets, list of dict
#         [
#             {
#                 "sample_name": {
#                     "img_file": "/hikmars4/users/zyl/hikframe/dl_demo/signal_cls/data/test/51/1010.png",
#                     "img_size": {
#                         "height": "461",
#                         "width": "100",
#                         "depth": "4"
#                     },
#                     "gt": {
#                         "label": "51"
#                     },
#                     "predicted": {
#                         "predicted_label": "50",
#                         "scores": {
#                             "50": "0.824"
#                         }
#                     },
#                     "info": ""
#                 }
#             }
#         ]
#         """
#         if not cls.eval_detail_dir:
#             print('please init_metric first.')
#             return

#         wrong_dir, right_dir = os.path.join(
#             cls.eval_detail_dir, "wrong"), os.path.join(cls.eval_detail_dir, "right")
#         for path in [wrong_dir, right_dir]:
#             os.makedirs(path, exist_ok=True)

#         def save_json_info(info_list, save_dir):
#             for info in info_list:
#                 sample_name, details = list(info.items())[0]
#                 json_file = os.path.join(
#                     save_dir, '{}.json'.format(sample_name))
#                 detail_json = {
#                     "img_file": "",
#                     "img_size": {
#                         "height": "",
#                         "width": "",
#                         "depth": ""
#                     },
#                     "gt": {
#                     },
#                     "predicted": {
#                     },
#                     "info": ""
#                 }
#                 detail_json["img_file"] = details["img_file"]
#                 detail_json["img_size"] = details["img_size"]
#                 detail_json["gt"] = details["gt"]
#                 detail_json["predicted"] = details["predicted"]
#                 detail_json["info"] = details["info"]
#                 with open(os.path.join(json_file), "w") as f:
#                     json.dump(detail_json, f)

#         def multi_process(data, process_num, func, save_dir):
#             # multiprocess
#             process_num = process_num
#             length = len(data)
#             step = int(length / process_num) + 1

#             process_list = []
#             for i in range(0, length, step):  # 开启5个子进程执行fun1函数
#                 p = Process(target=func, args=(
#                     data[i:i+step], save_dir,))  # 实例化进程对象
#                 p.start()
#                 process_list.append(p)
#             for p in process_list:
#                 p.join()

#         process_num = 10
#         if right_rets:
#             multi_process(right_rets, process_num, save_json_info, right_dir)
#         if wrong_rets:
#             multi_process(wrong_rets, process_num, save_json_info, wrong_dir)
