fix: 公式报告进度数据驱动 — 按实际 CSV/专题图数量计算总步数

旧: total_steps=7 硬编码, 看不到实际数据处理进度
新: 启动时扫描 10_WaterIndex_CSV 和 11_Thematic_Map,
  总步数 = 4(固定章节) + N_csv + N_maps,
  每处理 10% CSV 和每张专题图均更新进度,
  终端显示 统计 7/63 / 专题图 3/20 等实时信息
This commit is contained in:
duxin
2026-07-09 13:21:32 +08:00
parent b88bab57ee
commit 836c322b10

View File

@ -951,9 +951,26 @@ class WaterQualityReportGenerator:
else:
output_path = Path(output_path)
# 进度: 封面+背景+预处理+公式表+统计+分布图+总结 = 7 步
total_steps = 7
# 扫描实际数据量
csv_files = sorted(csv_dir.glob("*.csv")) if csv_dir.is_dir() else []
tif_files = (sorted(thematic_dir.glob("*.tif")) + sorted(thematic_dir.glob("*.png"))
) if thematic_dir.is_dir() else []
n_csv = len(csv_files)
n_maps = min(len(tif_files), 20) # 最多展示 20 张
n_fixed = 4 # 封面 + 背景 + 预处理 + 总结
total_steps = n_fixed + n_csv + n_maps
print(f"[公式报告] 数据: {n_csv} CSV, {len(tif_files)} 专题图 → 总步数 {total_steps}")
progress = self._create_progress(total=total_steps, desc="生成公式报告", on_step=on_progress)
_step = 0
def _next(text=""):
nonlocal _step
_step += 1
try: progress.update(1)
except Exception: pass
if on_progress:
try: on_progress(int(_step / total_steps * 100), text or f"步骤 {_step}/{total_steps}")
except Exception: pass
doc = Document()
section = doc.sections[0]
@ -966,13 +983,10 @@ class WaterQualityReportGenerator:
# ── 封面 ──
self._add_cover_page(doc)
try: progress.update(1)
except Exception: pass
# ── 通用章节:单位介绍 / 数据采集 / 工作流程 ──
self._add_company_description_page(doc)
self._add_data_acquisition_section(doc)
self._add_data_processing_section(doc)
_next("封面与通用章节")
# ── 1. 项目背景 ──
h1 = doc.add_heading("1 项目背景", level=1)
@ -981,36 +995,36 @@ class WaterQualityReportGenerator:
"涵盖叶绿素、蓝绿藻、浊度、CDOM 等多种水色指标的定量化空间制图。")
doc.add_paragraph("数据来源:机载 / 星载高光谱成像仪,经过辐射定标、大气校正、耀斑去除等预处理。")
doc.add_page_break()
_next("项目背景")
# ── 2. 影像预处理 ──
h1 = doc.add_heading("2 影像预处理", level=1)
self._style_heading(h1, 1)
self._add_hyperspectral_images_section(doc)
doc.add_page_break()
_next("影像预处理")
# ── 3. 水色指数公式列表 ──
h1 = doc.add_heading("3 水色指数计算方法", level=1)
self._style_heading(h1, 1)
if csv_dir.is_dir():
csv_files = sorted(csv_dir.glob("*.csv"))
doc.add_paragraph(f"本次反演共应用 {len(csv_files)} 个水色指数公式,"
if csv_files:
doc.add_paragraph(f"本次反演共应用 {n_csv} 个水色指数公式,"
f"各公式基于特征波段比值或差分原理计算:")
for i, cf in enumerate(csv_files[:30], 1): # 最多列出30个
for i, cf in enumerate(csv_files[:30], 1):
doc.add_paragraph(f" {i}. {cf.stem}", style='List Number')
if len(csv_files) > 30:
doc.add_paragraph(f" ... 共 {len(csv_files)} 个公式,详情见统计章节。")
if n_csv > 30:
doc.add_paragraph(f" ... 共 {n_csv} 个公式,详情见统计章节。")
else:
doc.add_paragraph(f"(未找到水色指数目录: {csv_dir}")
doc.add_page_break()
# ── 4. 指数统计结果 ──
# ── 4. 指数统计结果(每个 CSV 更新一次进度)──
h1 = doc.add_heading("4 水色指数统计结果", level=1)
self._style_heading(h1, 1)
figure_num = 10
if csv_dir.is_dir():
csv_files = sorted(csv_dir.glob("*.csv"))
if csv_files:
stats_rows = []
for cp in csv_files:
for i_c, cp in enumerate(csv_files):
try:
df_one = pd.read_csv(cp, sep=',')
val_col = df_one.columns[-1]
@ -1025,6 +1039,9 @@ class WaterQualityReportGenerator:
})
except Exception:
pass
# 每处理 10 个 CSV 更新进度
if (i_c + 1) % max(1, n_csv // 10) == 0 or i_c == n_csv - 1:
_next(f"统计 {i_c+1}/{n_csv}")
if stats_rows:
# 统计表
@ -1056,17 +1073,14 @@ class WaterQualityReportGenerator:
else:
doc.add_paragraph(f"(未找到水色指数目录: {csv_dir}")
doc.add_page_break()
try: progress.update(1)
except Exception: pass
# ── 5. 指数空间分布专题图 ──
# ── 5. 指数空间分布专题图(每张更新进度)──
h1 = doc.add_heading("5 水色指数空间分布专题图", level=1)
self._style_heading(h1, 1)
figure_num += 1
maps_found = 0
if thematic_dir.is_dir():
tifs = sorted(thematic_dir.glob("*.tif")) + sorted(thematic_dir.glob("*.png"))
for tf in tifs[:20]: # 最多展示 20 张
if tif_files:
for i_t, tf in enumerate(tif_files[:20]):
try:
param_name = tf.stem.split('_')[0] if '_' in tf.stem else tf.stem
caption = f"{figure_num} {param_name} 空间分布图"
@ -1075,15 +1089,14 @@ class WaterQualityReportGenerator:
maps_found += 1
except Exception as e:
doc.add_paragraph(f"[专题图插入失败: {tf.name}{e}]")
if len(tifs) > 20:
doc.add_paragraph(f"... 共 {len(tifs)} 张专题图,此处仅展示前 20 张。")
_next(f"专题图 {i_t+1}/{min(len(tif_files), 20)}")
if len(tif_files) > 20:
doc.add_paragraph(f"... 共 {len(tif_files)} 张专题图,此处仅展示前 20 张。")
else:
doc.add_paragraph(f"(未找到专题图目录: {thematic_dir}")
if maps_found == 0:
doc.add_paragraph("(未找到专题图文件,请确认 Step 11 已完成。)")
doc.add_page_break()
try: progress.update(1)
except Exception: pass
# ── 6. 综合总结 ──
h1 = doc.add_heading("6 综合总结", level=1)
@ -1092,8 +1105,7 @@ class WaterQualityReportGenerator:
"进行了定量化空间制图。各指数的统计结果和空间分布专题图如上所示。")
doc.add_paragraph("注意事项:水色指数反演结果为半定量指标,其绝对值可能受大气校正精度、"
"水体光学特性复杂性等因素影响。建议结合实测水质数据进行校验。")
try: progress.update(1)
except Exception: pass
_next("综合总结")
doc.save(str(output_path))
print(f"[公式报告] 生成完成: {output_path}")