from __future__ import annotations from pathlib import Path from typing import Any from .catalog import TASK_DEFAULTS, TASK_TYPES from .config import settings from .modules import build_module_task from .paths import rel SCRIPT_TASK_MAP: dict[str, str] = { "Back_Up.sh": "system.backup", "Check_Graph_Card.sh": "system.check_graph_card", "DataSet_Own/1. 图片预处理(内含使用手册)/1_rename_pics.sh": "dataset.rename", "DataSet_Own/1. 图片预处理(内含使用手册)/2_1_Trans_to_png.py": "dataset.to_png", "DataSet_Own/1. 图片预处理(内含使用手册)/2_2_Resize.py": "dataset.resize_single", "DataSet_Own/1. 图片预处理(内含使用手册)/2_reformate_pics.sh": "dataset.resize", "DataSet_Own/1. 图片预处理(内含使用手册)/3_pair_ori_label.sh": "dataset.pair", "DataSet_Own/1. 图片预处理(内含使用手册)/4_deal_labels.py": "dataset.deal_labels", "DataSet_Own/1. 图片预处理(内含使用手册)/4_deal_labels_old(老版程序).py": "dataset.deal_labels_old", "DataSet_Own/1. 图片预处理(内含使用手册)/4_rebuild_labels.sh": "dataset.rebuild_labels", "DataSet_Own/1. 图片预处理(内含使用手册)/5_TOOL_stack_pics.sh": "dataset.stack", "DataSet_Own/1. 图片预处理(内含使用手册)/5_stack_picture.py": "dataset.stack_single", "DataSet_Own/1. 图片预处理(内含使用手册)/6_TOOL_stitch_pics.sh": "dataset.stitch", "DataSet_Own/1. 图片预处理(内含使用手册)/6_stitch_picture.py": "dataset.stitch_single", "DataSet_Own/1. 图片预处理(内含使用手册)/Seg_data_run.sh": "dataset.run_wizard", "Seg_All_In_One_Analysis/1_Analysis_All.py": "analysis.all", "Seg_All_In_One_MMSeg/My_All_In_One/0_Initial_Save_All_Model_locally.py": "mmseg.init_weights", "Seg_All_In_One_MMSeg/My_All_In_One/1_Initial_Data_All-ori.py": "mmseg.generate_data_legacy", "Seg_All_In_One_MMSeg/My_All_In_One/1_Initial_Data_All_data_from_1_Data_Parameter-V1.py": "mmseg.generate_data_v1", "Seg_All_In_One_MMSeg/My_All_In_One/1_Initial_Data_All_data_from_1_Data_Parameter-V2.py": "mmseg.generate_data", "Seg_All_In_One_MMSeg/My_All_In_One/2_Initial_Alg_All-ori-old.py": "mmseg.generate_alg_legacy", "Seg_All_In_One_MMSeg/My_All_In_One/2_Initial_Alg_All_data_from_2_Alg_Program-V1.py": "mmseg.generate_alg_v1", "Seg_All_In_One_MMSeg/My_All_In_One/2_Initial_Alg_All_data_from_2_Alg_Program-V2.py": "mmseg.generate_alg", "Seg_All_In_One_MMSeg/My_All_In_One/3_Find_And_Delete_Special_Epoch.py": "mmseg.delete_epoch", "Seg_All_In_One_MMSeg/My_All_In_One/3_Tool_Copy_Result_To_Hardisk.sh": "mmseg.copy_result", "Seg_All_In_One_MMSeg/My_All_In_One/4_1_predict_params_FLOPs_FPS_V2.py": "mmseg.flops_fps", "Seg_All_In_One_MMSeg/My_All_In_One/4_1_predict_params_and_FLOPs_V1.py": "mmseg.flops_fps_v1", "Seg_All_In_One_MMSeg/My_All_In_One/4_2_predict_matrics_from_log_V1.py": "mmseg.metrics_v1", "Seg_All_In_One_MMSeg/My_All_In_One/4_2_predict_matrics_from_log_V2.py": "mmseg.metrics", "Seg_All_In_One_MMSeg/My_All_In_One/4_3_predict_draw_pictures_and_tabels.py": "mmseg.draw", "Seg_All_In_One_MMSeg/My_All_In_One/4_4_extract_loss_and_best_miou.py": "mmseg.extract_loss_miou", "Seg_All_In_One_MMSeg/My_All_In_One/x4_Predict_V1-.py": "mmseg.predict_v1", "Seg_All_In_One_MMSeg/My_All_In_One/x4_Predict_V2-.py": "mmseg.predict_v2", "Seg_All_In_One_MMSeg/tools/train.py": "mmseg.train", "Seg_All_In_One_SegModel/1_predict.py": "segmodel.predict", "Seg_All_In_One_SegModel/1_predict_raw_masks_check.py": "segmodel.raw_mask_check", "Seg_All_In_One_SegModel/2_predict_params_and_FLOPs_V1.py": "segmodel.flops", "Seg_All_In_One_SegModel/2_predict_params_and_FLOPs_V2.py": "segmodel.flops", "Seg_All_In_One_SegModel/3_predict_matrics_from_log.py": "segmodel.metrics", "Seg_All_In_One_SegModel/Tool_Copy_Best_Model.sh": "segmodel.copy_best", "Seg_All_In_One_SegModel/Tool_benchmark_smp.py": "segmodel.benchmark", "Seg_All_In_One_SegModel/Tool_get_params_and_FLOPs.py": "segmodel.params_flops", "Seg_All_In_One_SegModel/predict.sh": "segmodel.batch_predict", "Seg_All_In_One_SegModel/train.py": "segmodel.train", "Seg_All_In_One_SegModel/train.sh": "segmodel.batch_train", "Seg_All_In_One_YoloModel/Tool_Yolo_Copy_Best_Model.sh": "yolo.copy_best", "Seg_All_In_One_YoloModel/Yolo可视化测试/yolo_layer_tester.py": "yolo.layer_tester", "Seg_All_In_One_YoloModel/Yolo数据集构建/0_1_check_picture_pair.py": "dataset.yolo_check_pairs", "Seg_All_In_One_YoloModel/Yolo数据集构建/0_2_TOOL_stack_pics.sh": "dataset.yolo_stack", "Seg_All_In_One_YoloModel/Yolo数据集构建/0_2_stack_picture.py": "dataset.yolo_stack_single", "Seg_All_In_One_YoloModel/Yolo数据集构建/1_deal_labels.py": "dataset.yolo_rebuild_labels", "Seg_All_In_One_YoloModel/Yolo数据集构建/2_Check_and_Gen_Txt_Label_ori_label.py": "dataset.yolo_txt_ori", "Seg_All_In_One_YoloModel/Yolo数据集构建/2_Check_and_Gen_Txt_Label_sort_label.py": "dataset.yolo_txt_sort", "Seg_All_In_One_YoloModel/Yolo数据集构建/Tool_convert_bmp_jpg_to_png.py": "dataset.yolo_convert_png", "Seg_All_In_One_YoloModel/Yolo数据集构建/Tool_resize_pics.py": "dataset.yolo_resize", "Seg_All_In_One_YoloModel/yolo_predict.sh": "yolo.batch_predict", "Seg_All_In_One_YoloModel/yolo_predict_V1.py": "yolo.predict_v1", "Seg_All_In_One_YoloModel/yolo_predict_V2.py": "yolo.predict", "Seg_All_In_One_YoloModel/yolo_predict_V2_compare_all.py": "yolo.compare", "Seg_All_In_One_YoloModel/yolo_predict_raw_masks_check.py": "yolo.raw_mask_check", "Seg_All_In_One_YoloModel/yolo_predict_visualize_nn.py": "yolo.heatmap", "Seg_All_In_One_YoloModel/yolo_train.py": "yolo.train", "Seg_All_In_One_YoloModel/yolo_train.sh": "yolo.batch_train", "Seg_Predict_Own_Video_V2/1_Save_Frame_V1.py": "dataset.video_frames", "Seg_Predict_Own_Video_V2/1_Save_Frame_V2.py": "dataset.video_frames", "Seg_Predict_YoloModel/yolo_Seg_Video-V1-Visible.py": "yolo.video_visible", "Seg_Predict_YoloModel/yolo_Seg_Video-V2-UnVisible.py": "yolo.video_unvisible", "Tool-可视化/0_图片Labels生成/4_deal_labels.py": "visual.deal_labels", "Tool-可视化/0_图片Labels生成/Tool_deal_labels.py": "visual.tool_deal_labels_demo", "Tool-可视化/Tool_Check_and_Gen_Txt_Label_ori_label.py": "visual.label_ori", "Tool-可视化/Tool_Check_and_Gen_Txt_Label_sort_label.py": "visual.label_sort", "Tool-可视化/Tool_Gen_8_Bit_PNG[没用,不认].py": "visual.gen_8bit_png", "Tool-可视化/get_FPS.py": "visual.fps", "Tool-可视化/inference.py": "visual.inference", "Tool-可视化/train.py": "visual.train", "Tool-可视化/yolov11_heatmap_V1.py": "visual.yolo11_heatmap_v1", "Tool-可视化/yolov11_heatmap_V2.py": "visual.yolo11_heatmap_v2", "Tool-图片堆叠/1_check_picture_pair.py": "dataset.stack_pair_check", "Tool-图片堆叠/2_TOOL_stack_pics.sh": "dataset.stack_tool_batch", "Tool-图片堆叠/2_stack_picture.py": "dataset.stack_tool_single", } SUPPORTING_SCRIPT_PATTERNS = ( "Seg_All_In_One_MMSeg/demo/", "Seg_All_In_One_MMSeg/build/", "Seg_All_In_One_MMSeg/configs/", "Seg_All_In_One_MMSeg/docker/", "Seg_All_In_One_MMSeg/docs/", "Seg_All_In_One_MMSeg/projects/", "Seg_All_In_One_MMSeg/mmseg/", "Seg_All_In_One_MMSeg/tests/", "Seg_All_In_One_MMSeg/setup.py", "Seg_All_In_One_MMSeg/My_All_In_One/2_Alg_Program/", "Seg_All_In_One_MMSeg/My_All_In_One/Initial_Alg_Program/", "Seg_All_In_One_MMSeg/My_All_In_One/Initial_Data_Program/", "Seg_All_In_One_MMSeg/My_All_In_One/Initial_Schedule_Program/", "Seg_All_In_One_MMSeg/tools/dist_", "Seg_All_In_One_MMSeg/tools/slurm_", "Seg_All_In_One_MMSeg/tools/test.py", "Seg_All_In_One_MMSeg/tools/analysis_tools/", "Seg_All_In_One_MMSeg/tools/dataset_converters/", "Seg_All_In_One_MMSeg/tools/deployment/", "Seg_All_In_One_MMSeg/tools/misc/", "Seg_All_In_One_MMSeg/tools/model_converters/", "Seg_All_In_One_MMSeg/tools/torchserve/", "Seg_All_In_One_SegModel/config.py", "Seg_All_In_One_SegModel/dataset.py", "Seg_All_In_One_SegModel/loss.py", "Seg_All_In_One_SegModel/utils.py", "Seg_All_In_One_YoloModel/yolo_config.py", "Seg_All_In_One_YoloModel/Yolo数据集构建/Tool_Classes_And_Palette.py", "Seg_All_In_One_YoloModel/Yolo数据集构建/Tool_deal_labels.py", "Seg_Predict_YoloModel/yolo_config.py", "Seg_Predict_YoloModel/yolo_train.py", "DataSet_Own/2. 图片分割程序(mmseg)/", ) def _script_inventory() -> list[str]: scripts = [] for path in settings.source_root.rglob("*"): if path.is_file() and path.suffix in {".py", ".sh"}: scripts.append(rel(path, settings.source_root)) return sorted(scripts) def _is_supporting_script(relative_path: str) -> bool: return any(relative_path.startswith(pattern) or relative_path == pattern for pattern in SUPPORTING_SCRIPT_PATTERNS) def _command_script_path(command: list[str]) -> Path | None: if not command: return None if command[0] == "bash" and len(command) > 1: return Path(command[1]) if command[0] == "python" and len(command) > 1 and command[1] != "-c": return Path(command[1]) if len(command) > 5 and command[:3] == ["conda", "run", "-n"] and command[4] == "python": return Path(command[5]) return None def build_task_checks() -> list[dict[str, Any]]: checks = [] for task in TASK_TYPES: params = TASK_DEFAULTS.get(task, {}) try: spec = build_module_task(task, dict(params), settings.task_conda_env) script_path = _command_script_path(spec.command) if spec else None checks.append( { "task": task, "passed": spec is not None and (script_path is None or script_path.exists()), "command": spec.command if spec else None, "cwd": str(spec.cwd) if spec else None, "script_exists": None if script_path is None else script_path.exists(), "script": None if script_path is None else str(script_path), } ) except Exception as exc: checks.append({"task": task, "passed": False, "error": str(exc)}) return checks def get_coverage_report() -> dict[str, Any]: scripts = _script_inventory() mapped_scripts = [script for script in scripts if script in SCRIPT_TASK_MAP] user_scripts = [script for script in scripts if not _is_supporting_script(script)] unmapped_user_scripts = [script for script in user_scripts if script not in SCRIPT_TASK_MAP] task_checks = build_task_checks() return { "scripts_total": len(scripts), "user_scripts_total": len(user_scripts), "mapped_user_scripts": len(mapped_scripts), "task_build_passed": all(item["passed"] for item in task_checks), "unmapped_user_scripts": unmapped_user_scripts, "script_task_map": SCRIPT_TASK_MAP, "task_build_checks": task_checks, }