init 后首次落盘,累计工作: - 数据侧:simulate_breeding_data real-scale 3.5万树重建 + 分层观测 - 引擎侧:ABLUP 稀疏生产档 EM-REML(blup 1.6.0/1.7.0);性能倒挂修复—— 系谱闭包收口为 BFS 可达祖先 + N_EXACT 3000 对齐 N_SUBSAMPLE(选中 200~3000 树 不再顶进数小时精确迹尾),A/B 数值等价实证 + 守卫探针 - 前端:观测过滤 + 表单/HTTP 工具链完善 - 文档:业务链/观测梳理 + 引擎实施记录 + 规划对照总表 - gitignore:排除 Temp/调试脚本/一次性验证输出
2098 lines
270 KiB
Markdown
2098 lines
270 KiB
Markdown
# 桃育种系统 · 统计引擎实施记录
|
||
|
||
> **版本**:v1.4(2026-08-04 追加统计严谨·预测完整性与 MLOps 复现性:PA 落库 / 溯源 / germplasm_id 填充 / 砧木扩列 / Calo 相关校正 / 空间竞争协变量 + 组合得失漏斗)
|
||
> **定位**:记录统计引擎多轮 P0/P1 落地 + 田间刚需(花粉档案)+ 决策正确性(无性系级指数)+ 统计严谨(配合力交配设计 / 相关校正 / 空间竞争)+ MLOps 复现性 + 组合得失漏斗的实现、验证与文件清单——**G×E 交互引擎**(2026-08-03)、**性状方向标注**(2026-08-04)、**花粉档案**(2026-08-04)、**无性系级指数**(2026-08-04)、**配合力交配设计**(2026-08-04)、**统计严谨·MLOps 复现性**(2026-08-04,①Calo②PA③溯源④germplasm_id⑤砧木⑥空间竞争)与**组合得失漏斗**(2026-08-04,⑧ v_combination_funnel)。本文档为持续追加的落地台账,与规格文档 `桃育种系统模块扩展需求规格.md`(v2.10)配套;规格管"应该长什么样",本文管"实际落地了什么、怎么验证的"。 配套《桃育种系统业务链路与数据模型说明书》v1.1(2026-08-06 重生成,已同步 O1 花期数据消费补强 / N4 plan→trial→target 血缘 / 亲本校验 / 世代闭环落库 / 新增 §九 QA 与 CI 章节)与代码保持一致,三者(规格 + 实施记录 + 说明书)互为索引。
|
||
> **相关探针**:`Temp/claude/e2e_gxe_20260803.py`(G×E,5 场景)· `Temp/claude/e2e_direction_20260804.py`(方向标注,7 组)· `Temp/claude/e2e_pollen_20260804.py`(花粉档案)· `Temp/claude/e2e_clone_index_20260804.py`(无性系级指数,6 组)· `Temp/claude/e2e_combining_design_20260804.py`(配合力交配设计,5 组)· `Temp/claude/e2e_prediction_rigor_20260804.py`(②③④,4 组)· `Temp/claude/e2e_rootstock_20260804.py`(⑤)· `Temp/claude/e2e_corr_spatial_20260804.py`(①⑥,3 组)· `Temp/claude/e2e_combination_funnel_20260804.py`(组合得失漏斗,3 组)。 · `Temp/claude/e2e_o1_bloom_20260805.py`(O1 花期数据消费补强:四态软警示 + 窗口覆盖三态 + 库存五态 + 反向门禁,4 组)
|
||
|
||
---
|
||
|
||
## 一、G×E 交互引擎 P0(2026-08-03)
|
||
|
||
### 1.1 背景与目标
|
||
|
||
复审清单第 2 条要求**基因型×环境(G×E)交互随机效应**显式建模。桃为多年生多年多点(MET)试验作物,同一克隆/家系在跨点、跨年表现往往相反(如 c1 在 A 站高、B 站低,c2 反之),若只估主效应会系统性误排 EBV。本轮在 `run_ablup` 上扩展 G×E 模式(`method=GXEBLUP`),并补齐可辨识性门禁与异步任务记录。
|
||
|
||
### 1.2 引擎能力(`statistics/service.py::run_ablup`)
|
||
|
||
| 参数 | 取值 | 行为 |
|
||
|---|---|---|
|
||
| `gxe` | `True` / `False` | `True` 走 GXEBLUP(含 G×E 随机互作);`False` 回归纯 ABLUP(G×E 项关闭) |
|
||
| `gxe_env` | `site` / `year` | 环境维度。`site` 自动入固定效应 `trial_study`;`year` 自动入固定效应 `year` |
|
||
| `method` | `GXEBLUP` / `ABLUP` | 按 gxe 开关自动落库;model_name 形如 `GXEBLUP_{trait}_{env}_{ts}` |
|
||
| `fixed_effects` | 列表 | 调用方显式指定时与自动效应合并 |
|
||
|
||
**G×E 落库输出(`breeding_prediction.note` JSON)**:
|
||
- `sigma_gxe`:G×E 方差分量 σ²gxe(>0 表示存在交互)
|
||
- `gxe_ratio`:σ²gxe 占比
|
||
- `n_cross_env`:跨环境基因型数(有多少基因型至少在 2 个环境中观测)
|
||
- `skipped`:跳过明细(如缺站点株数)
|
||
|
||
**记录级 vs 基因型级**:
|
||
- 家系分组(无 clone)时基因型=组合,G×E 记录逐树;`year` 模式记录级 = (树,年) 逐条(train_n 为记录数,EBV 行按树写)。
|
||
- 克隆坍缩(见 1.5)时基因型=clone,多株坍缩为基因型节点。
|
||
|
||
### 1.3 自动固定效应
|
||
|
||
| gxe_env | 自动固定效应 | 说明 |
|
||
|---|---|---|
|
||
| `site` | `trial_study` | 站点由 `trial_study_id` 解析(缺站点的株记录跳过并写 `skipped`) |
|
||
| `year` | `year` | 年份由观测 `evaluate_year` 解析 |
|
||
|
||
调用方仍可用 `fixed_effects` 显式追加(如 `["trial_study"]`),引擎合并去重。
|
||
|
||
### 1.4 可辨识性门禁(`G×E 不可辨识` → 409,拒绝运行)
|
||
|
||
| 门禁 | 触发 | 处置 |
|
||
|---|---|---|
|
||
| 无跨环境重复 | 没有任何基因型在 ≥2 个环境出现(`n_cross_env == 0`) | `G×E 不可辨识:无任何基因型跨环境重复。拒绝运行。` |
|
||
| 单元内无重复 | 每个(基因型×环境)单元仅 1 条观测,σ²gxe 与残差混杂 | `无任何基因型×环境单元内重复(每格仅 1 条观测…)` |
|
||
| 无可分环境记录 | 所有记录缺站点/年份 | `G×E 分析无可分环境的记录` |
|
||
|
||
门禁拒绝时在 `StatisticsJobModel` 落一条 `status=FAILED` + `error_msg`(同步 409 抛出,异步失败可查)。
|
||
|
||
### 1.5 克隆坍缩
|
||
|
||
同 clone 经扩繁的多株 tree 在 G×E 模式下**坍缩为基因型节点 `c{clone}`**:G×E 专用系谱 `gxe_pedigree` 以 `c{clone}` 为个体,父母指向组合亲本(或树亲本);`record_map` 全部映射到 `c{clone}`。同 clone 各株 EBV 一致(重复测量聚合,杜绝自由度虚高)。
|
||
|
||
### 1.6 异步任务记录(`StatisticsJobModel`)
|
||
|
||
| 字段 | 值 | 说明 |
|
||
|---|---|---|
|
||
| `job_type` | `GXE` / `ABLUP`(/ `COMBINING` 等) | 任务类型 |
|
||
| `status` | `SUCCESS` / `FAILED` | 任务状态 |
|
||
| `result_ref` | prediction id | 关联结果 |
|
||
| `error_msg` | 文本 | 失败原因(可辨识性门禁消息亦落此) |
|
||
|
||
### 1.7 验证(`Temp/claude/e2e_gxe_20260803.py`,5 场景全过)
|
||
|
||
| 场景 | 数据 | 断言要点 |
|
||
|---|---|---|
|
||
| [1] site-G×E 家系分组 | 2 组合×2 站×3 株,无 clone | 自动 `fixed={trial_study}`、`method=GXEBLUP`、σ²gxe>0、n_cross_env=2、train_n=12、EBV 行=12、job_type=GXE SUCCESS |
|
||
| [2] 不可辨识门禁 | 各组合仅单站 | 409 `G×E 不可辨识:无任何基因型跨环境重复`、job FAILED + error_msg |
|
||
| [2b] 单元内无重复 | 2 基因型×2 站每格 1 株 | 409 含 `单元内重复`、job FAILED |
|
||
| [3] year-G×E | 2 clone×2 年交叉互作 | 自动 `fixed={year}`、train_n=16(记录级)、EBV 行=8(树级)、σ²gxe>0、n_cross_env=2 |
|
||
| [5] 克隆坍缩(site) | 2 clone×2 站×每格 2 株 | `record_map` 全为 `c{clone}`、同 clone EBV 相同、train_n=8、EBV 行=8 |
|
||
| [4] 回归 gxe=False | 同 [1] 数据 | `method=ABLUP`、显式 `fixed_effects=["trial_study"]`、EBV 行=12、job_type=ABLUP SUCCESS |
|
||
|
||
测试基座用 `_spy_solve` 包一层真引擎(monkeypatch `blup.solve`),捕获 `fixed`/`record_map` kwargs 后仍跑真解,验证引擎传参;`GATE_RELAX=dict(min_clone_n=1, min_pedigree_rate=0.0, max_missing_rate=1.0)` 放开数量门槛专注验证 G×E 逻辑。
|
||
|
||
---
|
||
|
||
## 二、性状方向标注 direction / into_ebv / default_h2(2026-08-04)
|
||
|
||
### 2.1 缺陷背景(科学正确性硬伤)
|
||
|
||
`bre_trait` 原仅 `stage`/`is_core`,**无方向标注**。选择指数与决策默认"高 EBV = 优",对**低优性状**(裂果率、病害级别、酸度——若目标是低酸)会**选反**:Smith-Hazel 的 b 与加权 Z 隐含"越大越好"。用户确认缺陷属实,拍板修复范围:
|
||
- **翻转范围**:指数+决策+排行**全翻转**;
|
||
- **into_ebv 范围**:'0' 仅从**选种相关候选**剔除(指数/EBV 排行/决策预览/ABLUP 下拉),describe/correlation/trait_values 不受影响;
|
||
- **default_h2 兜底**:zsum + smith_hazel 都兜底(无实测 h² 用先验,两者皆无才报错)。
|
||
|
||
### 2.2 数据模型变更
|
||
|
||
`bre_trait` 新增三列(幂等 ALTER,`backend/sql/weld_trait_direction.sql`;create_all 只建新表,新列须手写 SQL):
|
||
|
||
| 列 | 类型 | 默认 | 说明 |
|
||
|---|---|---|---|
|
||
| `direction` | varchar(16) | `'desc'` | 性状方向:`desc`=越大越好 / `asc`=越小越好 |
|
||
| `into_ebv` | varchar(1) | `'1'` | 是否选种目标:`1`=进 EBV/指数/决策候选 / `0`=仅记录 |
|
||
| `default_h2` | double precision | NULL | 先验遗传力 h²(指数无实测 h² 时兜底;桃经典先验,可在性状字典改) |
|
||
|
||
**种子数据(`backend/sql/bre_trait_seed.sql`,INSERT 0 43,ON CONFLICT DO UPDATE 含三新列)**:
|
||
- 7 个数值 core 性状(max/avg_fruit_weight、longitudinal/transverse/lateral_dia、flesh_thickness、ssc):`direction='desc'`、`into_ebv='1'`、`default_h2` 取桃经典先验(果重/糖度 0.5、果径/肉厚 0.4/0.3);
|
||
- 其余 categorical/date 性状:`into_ebv='0'`、`default_h2=NULL`。
|
||
|
||
**ORM/API 透传**:`TraitModel`/`TraitBaseSchema`/`TraitUpdateSchema`/`TraitOutSchema`/`TraitQueryParam` 补齐三字段;`batch_export` mapping_dict、`batch_import` header_dict/fields(direction/into_ebv 缺省 `'desc'/'1'`、default_h2 `_to_float`;**required_headers 仍只校验原 14 键,兼容旧模板**)、`import_template_download` 选项同步。
|
||
|
||
### 2.3 后端翻转逻辑(`statistics/service.py`)
|
||
|
||
**辅助** `_trait_meta_map(codes=None)`:`{trait_code: {direction, into_ebv, default_h2}}`,供指数/决策/排行共享方向语义。
|
||
|
||
| 模块 | 变更 |
|
||
|---|---|
|
||
| `list_traits(core_only, selection_only)` | select 新增三字段;`selection_only=True` → `where(into_ebv == "1")`(controller 加 `selection_only` query 参数) |
|
||
| `selection_index` | `cols` 剔除 `into_ebv='0'` 写入 `extra["dropped"]`(用户可见提示) |
|
||
| `_weighted_z_index`(zsum) | **z 标准化后对 asc 性状取负**(`z = -z`),统一"越大越优";use_h2 兜底 `h = herit.get(c) or default_h2` |
|
||
| `_smith_hazel_index` | h² 取 `h_eff[c] = 实测 h² or default_h2`;**`h_eff[c] is None` 才 409**(`缺实测且无先验 default_h2: …`);a 归一化后对 asc 元素取负 |
|
||
| `run_ablup` | 写时 rank 排序 `reverse=(direction != "asc")`(EBV 排行即优度序) |
|
||
| `ebv_ranking` | **读时重排**(见 §三) |
|
||
| `clone_ranking` | 按当前方向重排 `ebv_mean`(`reverse=(direction != "asc")`) |
|
||
| `decision_preview` | `_top_n`:`into_ebv='0'` 直接返回空集;`ranked` 按方向取最优前 N(asc 取 EBV 最小);op 缺省 `<=`(asc)/ `>=`(desc),pheno 与 ebv 共用 |
|
||
| `compare_predictions` | 轮次对比 rank 排序方向感知(见 §三) |
|
||
|
||
### 2.4 前端
|
||
|
||
| 文件 | 变更 |
|
||
|---|---|
|
||
| `api/module_bre/statistics.ts` | `listTraits(coreOnly, selectionOnly)` 带 `selection_only` 参数 |
|
||
| `views/module_bre/statistics/index.vue` | **`selTraits`(`listTraits(true, true)`)仅用于指数权重/EBV 批次/ABLUP-G×E 性状下拉**,与 describe/correlation 共享的 `traitSel` 解耦(后者保留全量);asc 性状标签加 '↓越小越优' 角标 |
|
||
| `views/module_bre/trait/index.vue` | 表单/表格/详情/搜索四处加 direction el-select(desc/asc+文案)、into_ebv 开关、default_h2 输入 |
|
||
| `views/module_bre/selection_rule/index.vue` | conditions_json 文本框说明:"op 缺省按性状方向(desc≥ / asc≤),rank_top_n 按方向取最优前 N" |
|
||
|
||
### 2.5 验证(`Temp/claude/e2e_direction_20260804.py`,7 组全过)
|
||
|
||
基座 4 性状 dA(desc,1,0.5)/bB(asc,1,0.25)/cC(desc,0,None)/dD(desc,1,None) + 4 批次 pA(h²=0.5)/pB/pC/pD(h²=None) + 12 株 EBV=[10.0..32.0] 升序。
|
||
|
||
| 组 | 验证点 | 断言要点 |
|
||
|---|---|---|
|
||
| [1] | list_traits 三字段 + selection_only | 返回 direction/into_ebv/default_h2;`selection_only=True` 过滤 `into_ebv='0'` |
|
||
| [2] | zsum 方向翻转 | 同数据 desc→asc 排名**精确互反**(top2 从最高 EBV 2 株翻为最低 2 株) |
|
||
| [3] | into_ebv='0' 剔除 | 权重含 cC → 结果 traits 不含 cC、`result_json.dropped` 有提示 |
|
||
| [4a] | smith_hazel default_h2 兜底 | 批次 pD h²=None 但性状 dD 带 default_h2=0.25 → 成功 |
|
||
| [4b] | smith_hazel 无实测无先验 | 批次无 h² 且性状无 default_h2 → 409 `缺实测且无先验` |
|
||
| [5] | decision rank_top_n 方向 | asc 命中 EBV 最低 2 株、desc 命中最高 2 株;无 op 时 asc 走 `<=` |
|
||
| [6] | ebv_ranking 读时重排 | 性状事后改方向后按当前方向重排(rank 按优度重编号) |
|
||
| [7] | compare_predictions 方向感知 | asc 反序两批 rank1=最低 EBV 株(cur_ebv=10.0);desc 反序两批 rank1=最高 EBV 株(32.0) |
|
||
|
||
---
|
||
|
||
## 三、本轮修复的结构性 bug(方向盲区家族)
|
||
|
||
同一缺陷模式——**"高 EBV = 优"硬编码**——在排行/对比链路还有两处遗留,本轮一并修复:
|
||
|
||
### 3.1 `ebv_ranking` 方向盲区(读时重排)
|
||
|
||
原实现只在 `direction=="asc"` 时重排,`desc` 信任**写时持久化 rank**。当性状事后改方向(如 bB 由 asc 改 desc),已落库批次 rank 仍是 asc 序 → 读回倒序、最低 EBV 排第一。修复:**读时始终按 `predicted_value` + 当前 direction 重排并重编号 rank**,且 `self.db.expunge(r)`——因为 GET 会话走 `session.begin()`(退出自动提交),不 expunge 会把重排后的 rank 写回库,破坏"GET 纯读"。
|
||
|
||
### 3.2 `compare_predictions` 硬编码降序
|
||
|
||
原实现两处排序 `reverse=True`(写死高 EBV=rank 1)。对 asc 性状展示的 rank 列会把**最差株显示为第 1**(Spearman 相关/位移量对反转不变量,但暴露的 rank 列是错的)。修复:读 trait direction,`reverse = (direction != "asc")` 同时用于 rank_cur 与 rank_prev;corr/flip 判定对反转不变量保持不变。
|
||
|
||
---
|
||
|
||
## 四、花粉档案 breeding_pollen(2026-08-04)
|
||
|
||
### 4.1 缺陷背景(田间刚需)
|
||
|
||
用户反馈:桃花期仅 3–7 天,**父本花粉是杂交季命脉**,但代码里没有 `bre_pollen` 表(仅在测试文件提及),`bre_pollination` 有花朵数/坐果数/去雄/套袋,却**无花粉采集日期、贮藏方式(-20℃/液氮)、活力检测(TTC 染色率/离体萌发率%)、授粉窗口计划**。后果:明年复盘"这批坐果为什么低"毫无抓手。核验属实(比描述更严重:一期文档规划的 `pollination_method`/`pollen_source`/`pollen_viability` 三字段也全未实现)。
|
||
|
||
### 4.2 架构决策(用户确认)
|
||
|
||
| 决策点 | 拍板 | 理由 |
|
||
|---|---|---|
|
||
| 父本锚点 | **树级 `male_tree_id`** FK→bre_tree(与 pollination.male_tree_id 一致) | 单父本溯源;混合/外地采集时为空 + `source_type` 区分 |
|
||
| 活力建模 | **单值+方法**(`viability_method`[ttc/germination]+`viability_pct`+`viability_test_date`) | 不建子表,够用且简单 |
|
||
| 窗口计划 | **派生有效期+校验**(`collect_date`+`expiry_date`;窗口=[采集日,失效日] 由 pollination 校验) | 不建独立计划表;`/bre/pollen/available_lots` 提供"当前花期可用批次" |
|
||
|
||
### 4.3 数据模型(`backend/sql/weld_pollen.sql`,幂等 DDL + create_all 注册)
|
||
|
||
新表 `bre_pollen`(lot_code UNIQUE / male_tree_id FK SET NULL / source_type tree|mixed|external / collect_date / collect_method / quantity / storage_method fridge|minus20|minus80|liquid_n2 / viability_method ttc|germination / viability_pct / viability_test_date / expiry_date / remark)+ `ALTER bre_pollination ADD pollen_lot_id integer REFERENCES bre_pollen(id) ON DELETE SET NULL` + `ADD pollination_method varchar(32)`(补一期文档规划但遗漏的授粉方式)。
|
||
|
||
ORM:`module_bre/pollen/` 五件套(model/schema/crud/service/controller),路由前缀 `/bre/pollen`;`module_bre/__init__.py` 注册 `PollenRouter`(create_all 经 import 链自动拾取新模型)。
|
||
|
||
### 4.4 服务层关键逻辑(`pollen/service.py` + `pollination/service.py`)
|
||
|
||
| 逻辑 | 实现 |
|
||
|---|---|
|
||
| 去重 | `_check_code`:批次号存在 → 409「已存在」(create/update/batch_import 均走) |
|
||
| FK 校验 | `assert_parents_exist`(父本树不存在→409;**自动跳过 None**,可空 male_tree_id 安全) |
|
||
| 标签填充 | `_attach_fk_labels`:male_tree_id→tree_no;授粉侧 pollen_lot_id→lot_code |
|
||
| 授粉窗口校验 | `_validate_pollen_window`:授粉日期须在批次 [collect_date,expiry_date] 内,否则 409「授粉日期 X 不在花粉批次 Y 的授粉窗口 [A ~ B] 内」;update 时字段未变沿用库内现值 |
|
||
| 可用批次 | `available_lots(date_on)`:返回窗口内批次(label 含窗口区间+活力%),缺省今天 |
|
||
|
||
### 4.5 菜单/权限(`backend/sql/bre_menu.sql`)
|
||
|
||
| 项 | 值 |
|
||
|---|---|
|
||
| 菜单 | 900056 花粉档案(parent 900030 杂交配组,hidden,route `/bre/pollen`,component `module_bre/pollen/index`) |
|
||
| 按钮 E 段 | 900601-900608(`module_bre:pollen:detail/query/create/update/delete/export/import/download`) |
|
||
| 角色关联 | SUPER_ADMIN/ADMIN 范围扩至 900600-900699 |
|
||
|
||
### 4.6 前端
|
||
|
||
| 文件 | 变更 |
|
||
|---|---|
|
||
| `api/module_bre/pollen.ts` | PollenAPI 全套 + `getAvailableLots`(授粉窗口下拉) |
|
||
| `views/module_bre/pollen/index.vue` | 花粉 CRUD 页(贮藏/活力/采集方式下拉、采集/测定/有效期日期、活力% 数字) |
|
||
| `views/module_bre/pollination/index.vue` | 表单/表格/搜索加 `pollen_lot_id`(批次下拉)+ `pollination_method`(授粉方式下拉) |
|
||
| `views/module_bre/_shared/StageView.vue` + `stage_cross/index.vue` | 杂交配组第三标签「花粉档案」 |
|
||
|
||
### 4.7 验证(`Temp/claude/e2e_pollen_20260804.py` 全过 + `vue-tsc`)
|
||
|
||
| 组 | 断言 |
|
||
|---|---|
|
||
| [pollen.create] | male_tree_no 标签=T015108、活力 85.5% 回填、窗口落库 |
|
||
| [dup] | 409「花粉批次号 … 已存在」 |
|
||
| [fk] | 409「采集父本树不存在或已被删除」 |
|
||
| [list/detail/options/available_lots] | 均含新批次;available_lots 返回窗口内批次 |
|
||
| [pollination 窗口内] | create 成功、pollen_lot_no 标签、授粉方式回填 |
|
||
| [window 窗口外] | 409 含「授粉窗口 [2026-07-01 ~ 2026-09-30]」 |
|
||
| [update/delete] | 授粉日期改窗口内仍通过;pollen update 活力/有效期生效;软删生效 |
|
||
|
||
---
|
||
|
||
## 五、选择指数·无性系级聚合(2026-08-04)
|
||
|
||
### 5.1 决策正确性背景
|
||
|
||
用户提出决策正确性缺陷:`selection_index` 对每个 `tree_id` 算指数并排名、`apply_selection` 写每株,但**桃是无性繁殖**——一个 clone 经扩繁的多株遗传同质,应聚合为一个遗传实体再排名。后果:同一个优系 3 株可能被拆成 3 个独立指数条目,可能只选中其中 1 株而漏掉该系其他株,也不利"系级决选"。用户拍板:指数前先按 clone 聚合 EBV(mean/max 由**可靠性加权**),在 clone 级算 Smith-Hazel,再决定入选 clone。
|
||
|
||
**自株退化(工程补充)**:`tree.clone_id` 在实生苗阶段可空(v2.2/A1 决策),若把无 clone 的株全部剔除,实生苗阶段选择会塌缩。故未晋升 clone 的实生株**退化为自株单元**(key=`-tree_id`,每株独立参与指数与决选),入选命中规则 stage 时晋升建 clone。
|
||
|
||
### 5.2 数据模型变更
|
||
|
||
**无表结构变更**(复用 `tree.clone_id` + `breeding_prediction_value` 既有字段)。仅接口与计算层变更:
|
||
|
||
| 接口 | 变更 |
|
||
|---|---|
|
||
| `SelectionIndexIn.aggregate` | 新增:`clone`(默认,无性系级)/ `tree`(旧单株级行为保留) |
|
||
| `selection_index` 响应 | 每条 top 项含 `clone_id`/`clone_code`/`n_trees`/`tree_ids`(clone 级);tree 模式含 `tree_id`;整体 `"aggregate"` 回显 |
|
||
|
||
### 5.3 聚合与排名逻辑(`statistics/service.py`)
|
||
|
||
**`_clone_units(cols, tree_ids, ebv_by_trait, pheno_by_trait, rel_by_tree)`**——聚合单元构造:
|
||
- 查 `tree.id/clone_id/tree_no`(限定 tree_ids)→ 按 `clone_id` 分桶,空桶自株 key=`-tree_id`;
|
||
- 单元 `ebv_src[c][key]` = 可靠性加权 `Σ(ebv×rel)/Σ(rel)`(桶内每 trait 各算一份),全 rel=0 回退简单均值;
|
||
- 单元 `pheno_src[c][key]` = 简单均值(smith_hazel 表型均值用);
|
||
- 返回 `[{key, clone_id, label, n_trees, tree_ids}]`。
|
||
|
||
**排名单位切换**:zsum / Smith-Hazel 改为在单元 key 集上计算(`ebv_src`/`pheno_src` 取数),方向感知沿用 v2.3(统一越大越优);Smith-Hazel 的 G 矩阵 pair 相关仍由树级 `ebv_by_trait` 抽样估计,b = P⁻¹Ga 在 clone 单元上评分。响应组装把单元字段映射回每条 top(tree 模式还原 `tree_id`)。
|
||
|
||
**`apply_selection` 按遗传实体写**:
|
||
- top 项可能是 clone 级(`tree_ids`)或旧树级(`tree_id`),统一构建 `units`;
|
||
- 每单元 `rel = min(rel_by_tree.get(t, 1.0) for t in u_tids)`(保守:最弱证据株门控全系);
|
||
- 写一条 `selection_result`:`clone_id` 指向全系(self 为 NULL)+ `tree_id` 溯源一株(优先已有记录株)+ reason 含「系内N株」;
|
||
- 入选单元命中规则 stage → `_promote_tree_to_clone(首株, stage)` 幂等晋升建 clone(复用既有 clone、推进 stage),self 株由此回填 `clone_id`。
|
||
|
||
### 5.4 前端
|
||
|
||
| 文件 | 变更 |
|
||
|---|---|
|
||
| `api/module_bre/statistics.ts` | `selectionIndex` data 类型加 `aggregate?: 'clone' | 'tree'` |
|
||
| `views/module_bre/statistics/index.vue` | 工具栏「聚合:无性系级/单株级」radio(默认无性系级)+ 说明文案(桃无性繁殖默认;未晋升实生株按单株参与);clone 模式结果表显示 clone_code/clone_id/n_trees/涉及单株 |
|
||
|
||
### 5.5 验证(`Temp/claude/e2e_clone_index_20260804.py`,6 组全过)
|
||
|
||
基座:目标/组合/2 clone(X=2株 T1T2、Y=2株 T3T4)+ 2 自株(T5T6)+ 2 性状 A(desc) B(asc) + 2 批次。A 系 EBV:T1=10(rel.1)/T2=30(rel.9) 加权 28;T3=20(rel.9)/T4=40(rel.1) 加权 22——**可靠加权 X 排 Y 前,简单均值则 X20<Y30 反序**,验证加权是有效差异而非巧合。
|
||
|
||
| 组 | 验证点 | 断言要点 |
|
||
|---|---|---|
|
||
| [1] | clone 聚合单元 + 可靠加权排名 | 6 株 → 4 单元;clone 单元 n_trees=2/tree_ids 正确;自株 key 独立;X(加权28) 排 Y(加权22) 前 |
|
||
| [2] | tree 模式兼容 | `aggregate="tree"` 返回 6 条含 `tree_id`,desc 首=EBV 最高株 T4 |
|
||
| [3] | 方向翻转 clone 级 | A 改 asc → top 精确互反,首=最低聚合 EBV 的 T5 自株 |
|
||
| [4] | smith_hazel clone 级 | b 含 A/B;top 含 clone 单元(n_trees/tree_ids 正确) |
|
||
| [5] | apply_selection clone 级写入 | top_n=2 → 写 2 条决选:cloneX 一条(clone_id + 溯源 T1/T2 之一 + reason「系内2株」)+ self T6 一条 |
|
||
| [6] | apply 晋升建 clone | top_n=4 含自株 → T5/T6 命中 sp 规则晋升建 clone(clone_id 回填);clone X 株 stage 推进 sp |
|
||
|
||
> **科学正确性收口**:指数排名单位与决选写入单位统一为**遗传实体**——同一优系多株不会再被拆散、单株误选漏选;自株退化保住实生苗阶段选择能力,且入选即晋升、天然补上 clone 归属。
|
||
|
||
---
|
||
|
||
## 六、配合力交配设计 design_type(2026-08-04)
|
||
|
||
### 6.1 缺陷背景(统计严谨)
|
||
|
||
用户指出统计严谨缺陷:`combining.solve` 只实现 **Griffing 对称全双列**(model A),但 `run_combining` 与 `bre_combining_ability` 都**没有 `design_type` 字段**区分完全双列 / 部分双列 / line×tester(NCII) / NCIII。后果:用 line×tester 设计时,GCA/SCA 算法与 ANOVA 自由度都与全双列不同,当前一律按全双列算**会算错**(自由度错、GCA 含互反/自交效应)。用户拍板修复:`bre_cross_combination` / `bre_combining_ability` 加 `design_type`,`combining.solve` 按设计分支(line×tester 用 NCII 双因素模型)。
|
||
|
||
### 6.2 数据模型变更
|
||
|
||
`bre_cross_combination` 加 `design_type` varchar(16) NULL(缺省按 `full_diallel` 计);`bre_combining_ability` 同步落 `design_type`。取值**硬编码校验**(同 `selection_index.method`,非 sys_dict):`full_diallel`(完全双列,默认)/ `partial_diallel`(部分双列)/ `line_tester`(line×tester NCII)/ `nciii`(NCIII 测交)。DDL 见 `backend/sql/weld_combining_design.sql`(幂等 ALTER + COMMENT)。create/update 接受 code 或中文标签并归一化,非法值 409(`交配设计取值不合法`)。
|
||
|
||
### 6.3 求解器分支(`scripts/breeding_stats/combining.py`)
|
||
|
||
| 设计 | 模型 |
|
||
|---|---|
|
||
| `full_diallel` / `partial_diallel` | **Griffing 对称全双列** model A:`y_ij = μ + g_i + g_j + s_ij`,Σg=0 约束,最小二乘 BLUE |
|
||
| `line_tester`(NCII) | **双因素模型** model B:`y_ij = μ + l_i + t_j + (lt)_ij`;parent1=line(母本)、parent2=tester(父本),**分别 Σl=0 / Σt=0**;SCA = line×tester 互作 = 残差 |
|
||
| `nciii` | 同一 model B,门槛 **tester 恰好 2 个** |
|
||
|
||
工程要点:
|
||
- **可辨识性**:tester 列从索引 `1+n_l` 起 → **显式列选择**(非连续切片);基线列切出后吸收剩余列。
|
||
- **顺序 ANOVA(SS 型)**:SS_line(intercept→line)→ SS_tester(→tester after line)→ SS_sca(残差);df_line=n_l-1、df_tester=n_t-1、df_sca=n-1-df_line-df_tester。输出 `design`/`roles`/`df_line`/`df_tester`/`df_sca`。
|
||
- **门禁**:同亲本既作 line 又作 tester(角色重叠)→ `ValueError` → 任务 FAILED + CustomException「角色重叠」;NCIII tester≠2 → 拒绝。
|
||
- **gca_se 持久化**:GCA 标准误**内嵌 `anova_json["gca_se"]`**(避免 DB 迁移,gca_json/sca_json 形状稳定);前端 GCA 表加 SE 列。
|
||
|
||
### 6.4 运行过滤与持久化(`statistics/service.py::run_combining`)
|
||
|
||
`run_combining` 加 `design_type` 参数透传 `combining.solve`;**按设计过滤组合**——只纳入 `cc.design_type or 'full_diallel' == dt` 的组合,杜绝全双列标注组合混入 line×tester 运行(混算根因)。`bre_combining_ability.design_type` 随结果落库,`anova_json` 带 `design` 供前端分显示。
|
||
|
||
### 6.5 前端
|
||
|
||
| 文件 | 变更 |
|
||
|---|---|
|
||
| `api/module_bre/statistics.ts` | `RunStatsPayload.design_type?: string`(配合力运行时下发) |
|
||
| `api/module_bre/cross_combination.ts` | 查询/表格/表单类型加 `design_type` |
|
||
| `views/module_bre/statistics/index.vue` | 运行对话框「交配设计」radio(DESIGN_LABELS 四选项 + 说明);配合力批次表「设计」列;详情 ANOVA 按 `a.design` 分支——NCII/NCIII → line/tester/互作 F 与 p + roles 计数,双列 → GCA F;GCA 表 SE 列;SCA 表展示 |
|
||
| `views/module_bre/cross_combination/index.vue` | 表单/表格/详情/搜索四处 `design_type`(radio + DESIGN_LABELS 中英映射,createInitialFormData 默认 full_diallel) |
|
||
|
||
### 6.6 验证(`Temp/claude/e2e_combining_design_20260804.py`,5 组全过 + `vue-tsc`)
|
||
|
||
基座:数值性状 + 目标 + 6 亲本;NCII 2×2(line_tester 4 组合)+ NCIII 2×2(nciii 4 组合)+ 1 条 full_diallel(应被 line_tester 运行排除)。
|
||
|
||
| 组 | 验证点 | 断言要点 |
|
||
|---|---|---|
|
||
| [1] | NCII line_tester 运行 | design_type 落库;anova.design=line_tester;**df 1/1/1**;roles.lines/testers 正确;平衡 2×2 精确解 gca{l1:-2,l2:+2,t1:-1,t2:+1};SCA 恰 4 条;`E2EDTMIX`(full_diallel)被排除;`anova.gca_se` 内嵌 |
|
||
| [2] | NCIII 分支 | 只纳入 nciii 标注组合;同一双因素模型;df_line/df_tester=1;SCA 4 条;gca{n1:-2,n2:+2} |
|
||
| [3] | 角色重叠 gate | 同亲本作 line 又作 tester → 任务 FAILED + CustomException 含「角色重叠」 |
|
||
| [4] | create/update 校验 | `line_tester`→原样、中文「完全双列」→归一化 `full_diallel`、`bogus_design`→409、update→`nciii` |
|
||
| [5] | 持久化复查 | commit 后新会话 design_type / anova.design / gca_se 均真实落库 |
|
||
|
||
> **科学正确性收口**:配合力计算不再默认"一律全双列"——line×tester(NCII)/NCIII 走双因素模型,GCA/SCA 与 ANOVA 自由度按设计正确计算;运行层按 `design_type` 过滤组合,杜绝混算;角色重叠直接拒绝,消除亲本角色语义错误。**待办**:`partial_diallel`(Griffing model 4,无互反)与 model 3(含互反、需单株表型)本轮未单独实现,随使用按需补。
|
||
|
||
---
|
||
|
||
## 七、统计严谨·预测完整性与 MLOps 复现性(v1.4,2026-08-04)
|
||
|
||
### 7.1 缺陷背景(七条复审逐条核实)
|
||
|
||
用户抛出七条统计严谨/完整性复核主张,**逐条对照代码核实均为真缺陷**后按优先级落地(便宜且值得马上补 ②④ → 中期 ③⑤ → 需新能力 ①⑥):
|
||
|
||
| # | 主张(核实) | 落地 |
|
||
|---|---|---|
|
||
| ② | `bre_prediction_value` 只存 reliability,未存预测准确度 **PA** | 加 `pa = √reliability`;批次 `bre_prediction.accuracy` 改填真 PA |
|
||
| ④ | `PredictionValueModel.germplasm_id` **永未填充**(run_ablup 只写 tree_id) | 写 EBV 行时回填 `tree.germplasm_id`,亲本级 EBV 查询可用 |
|
||
| ③ | `bre_prediction` 无 data_version / 输入哈希 / 引擎版本,**MLOps 溯源不全** | 加三字段 + 确定性输入哈希,同数据重跑一致、改观测必变 |
|
||
| ⑤ | `bre_rootstock` 仅 code/name/remark,无矮化类、砧穗亲和性 | 扩 `dwarf_class` + `compatibility`,全链路透传 |
|
||
| ① | Smith-Hazel 的 G 矩阵用"EBV 皮尔逊相关"近似(**无真 MT-BLUP**) | 改 **Calo 可靠性校正** `r_g = r_EBV/√(rel_i·rel_j)`(真 MT-BLUP 记遗留) |
|
||
| ⑥ | 果园**株间竞争 / 边缘效应**未建模 | `run_ablup` 新增 `covariate="competition"`(Chebyshev 邻域株数) |
|
||
| ⑦ | 前端 D 层 `_coming_soon` 占位页 | **保持占位属预期**(P2 远景,本轮不动) |
|
||
|
||
### 7.2 数据模型变更(`backend/sql/weld_prediction_rigor.sql` + `weld_rootstock.sql`)
|
||
|
||
| 表 | 列 | 类型 | 说明 |
|
||
|---|---|---|---|
|
||
| `bre_prediction_value` | `pa` | double precision | 预测准确度 PA = √reliability(每株每性状) |
|
||
| `bre_prediction` | `data_version` | varchar(32) | 数据版本(`_DATA_VERSION="v2.7"`,service.py) |
|
||
| `bre_prediction` | `input_hash` | varchar(64) | SHA256:`{tree_id}:{均值表型}` + `{个体}\|dam\|sire` 确定性序列化(数据漂移可检测) |
|
||
| `bre_prediction` | `engine_version` | varchar(32) | 引擎版本(`blup.ENGINE_VERSION="1.0.0"`) |
|
||
| `bre_rootstock` | `dwarf_class` | varchar(32) | 矮化类:矮化/半矮化/乔化/柱状/其他 |
|
||
| `bre_rootstock` | `compatibility` | varchar(16) | 砧穗亲和性:强/中/弱 |
|
||
|
||
> `accuracy` 语义正名:原误填"均值 EBV 的平方根"(量纲不符),现改填**真 PA = √(批次内可靠性均值)**(`numeric(5,3)`,3 位小数),与 `bre_prediction_value.pa`(每株)口径一致。
|
||
|
||
### 7.3 引擎逻辑(`statistics/service.py` + `blup.py`)
|
||
|
||
| 规格点 | 实现 |
|
||
|---|---|
|
||
| ② PA | `run_ablup` 写 EBV 行 `pa = √reliability`;批次 `accuracy = √(均值 rel)`。`ebv_ranking` 单株响应透出 `pa` |
|
||
| ④ germplasm_id | `run_ablup` 写 EBV 行 `germplasm_id = tree.germplasm_id`(晋升回填的种质;无种质株保持 NULL 合规) |
|
||
| ③ 溯源 | 批次级落 `data_version` / `input_hash` / `engine_version`;`input_hash` 覆盖全部参与树 × 全部观测(含 NULL 表型拼接),**改 1 条观测哈希必变** |
|
||
| ① Calo | `_smith_hazel_index` G 非对角改 `r_g = r_EBV/√(rel_i·rel_j)`(rel 取配对树该性状均值),钳制 [−1,1];可靠性缺失/近零 → 0(保守);`extra["g_corr"]`(性状对)+ `extra["g_note"]` 落 `bre_selection_index.result_json` 可审计;rel 数据即 ② 落库的 reliability |
|
||
| ⑥ 空间竞争 | `run_ablup(covariate="competition")`:同 **(plot_id, block_no)** 网格内 Chebyshev 距离 1(8 邻域,不含自身)株数作协变量;相邻越多竞争越强、边缘株相邻少隐式捕捉边缘效应;G×E 分支同步支持(三处 `covariate == "crop_load"` 泛化为 covariate 真值);**全无 row/col → CustomException**(显式数据需求);`bre_tree.row_no/col_no` 数据能力已全链路就位(模型/前端录入/表格/详情/导入导出) |
|
||
|
||
### 7.4 前端
|
||
|
||
| 文件 | 变更 |
|
||
|---|---|
|
||
| `api/module_bre/statistics.ts` | 指数批次表/EBV 行类型加 `germplasm_id`/`pa` |
|
||
| `views/module_bre/statistics/index.vue` | 指数批次表加 `germplasm_id`/`pa` 列;ABLUP 运行对话框协变量 el-checkbox 改 **radio**(无 / crop_load / competition)+ 说明文案 |
|
||
| `api/module_bre/rootstock.ts` + `views/module_bre/rootstock/index.vue` | `dwarf_class`/`compatibility` 全量:常量、搜索、表格、详情、表单、handleSearch/onResetSearch |
|
||
|
||
### 7.5 验证(三探针全过 + `vue-tsc`)
|
||
|
||
**`e2e_prediction_rigor_20260804.py`(②③④,4 组)**
|
||
| 组 | 断言 |
|
||
|---|---|
|
||
| [1] | 每株 `pa = √rel` 逐条一致;批次 `accuracy` = √(均值 rel);溯源三字段(data_version=v2.7 / engine=1.0.0 / acc=0.439);germplasm 级查询(按 gA 查得 2 条);ebv_ranking 透出 pa |
|
||
| [2] | 复现性:同数据重跑 input_hash 完全一致 |
|
||
| [3] | 数据漂移:改 1 条观测值后重跑哈希必变 |
|
||
| [4] | 跨会话持久化:commit 后新会话读取值/哈希仍在(全行扫描断言) |
|
||
|
||
**`e2e_rootstock_20260804.py`(⑤)**:create/detail/update/list(搜索 dwarf_class)/options/export(含新列)/template(下拉选项)/DB 直查全过。
|
||
|
||
**`e2e_corr_spatial_20260804.py`(①⑥,3 组)**
|
||
| 组 | 断言 |
|
||
|---|---|
|
||
| [1] | Calo 校正值:`g_corr` 含性状对、`g_note` 含"可靠性校正";`got_rg` 与独立重算 `clamp(r/√(rel_i·rel_j))` 一致(容差 1e-4),例 r=0.9966/rel 0.1925·0.1345 → r_g=1.0 |
|
||
| [2] | competition 消费验证:有坐标运行成功,EBV 与无协变量最大差异 0.5465(差分消费,非仅字段) |
|
||
| [3] | 数据需求判定:全无 row/col → CustomException 含 row_no/col_no |
|
||
|
||
### 7.6 遗留(已记账,不动引擎)
|
||
|
||
- **真 MT-BLUP**:多性状 G 需全新多变量 REML 求解器(Kronecker 积 G/R + 方差分量迭代,数值收敛风险大)。本轮用 Calo 可靠性校正顶上(业界对"EBV 相关替代 G"的标准修正),`g_corr`/`g_note` 落库可审计。后续要做即按此接口替换。
|
||
**2026-08-04 追加加固**:逐对独立估计的 r_g 在 ≥3 性状时可能违反三角不等式使 G 非正定 → `_smith_hazel_index` 构造 G 后做**最近半正定投影**(Higham 特征值截断,`np.linalg.eigh`),b=P⁻¹Ga 才良性;新增稳定性警示 `extra["warnings"]`(完整观测树 <30 / P 条件数 >1000 / G 非正定已投影 / r_g 钳到 [−1,1] 边界)随 `result_json` 落库可审计,不阻断。数值验证:0.9/0.9/−0.9 相关阵 det<0 → 投影触发;2 性状正定场景无警示。
|
||
- **⑦ 前端 D 层占位**:分子育种/品种保护/AI 增强 `_coming_soon` 保持占位,属 P2 远景预期。
|
||
|
||
### 7.7 组合得失漏斗 v_combination_funnel(v2.8,2026-08-04)
|
||
|
||
**缺陷背景(逐条复审第 8 条,最贴业务)**:数据本已齐全——`bre_pollination.flower_count/effective_count`(花→果)、`bre_seed_lot.seed_count/germination_rate`(种→苗)、`bre_seedling.seedling_count`(出苗)——但**无任何按 `bre_cross_combination` 汇总的派生指标**:结实率/出苗率/选择强度未滚到组合层,配合力第一手证据(组合得失链路)字段在但没合成进配合力上下文。核实属实:全库无 结实率/出苗率/选择强度/funnel 实现;唯一"选择强度链"是 `seed_lot.used_count` 机械累加(账本非派生指标);`run_combining` 只取 `func.avg(value_numeric)` 组合均值、`combining.solve` 只认 `combo/parent1/parent2/value`。用户拍板:补视图/派生表即可,数据已齐、风险极低。
|
||
|
||
**六级链路与派生指标**:
|
||
|
||
| 环节 | 数据源(均按 combination_id 聚合) | 派生 |
|
||
|---|---|---|
|
||
| 花→果 | `bre_pollination` Σflower_count / Σeffective_count | **结实率** fruit_set_rate = Σeff/Σflower×100 |
|
||
| 果→种 | `bre_seed_lot` Σseed_count / AVG germination_rate | 出苗基数 |
|
||
| 种→苗 | `bre_seedling` Σseedling_count / Σstrong_seedling_count | **出苗率** emergence_rate = Σseedling/Σseed×100 |
|
||
| 苗→定植 | `bre_planting` Σtree_count | 定植数 |
|
||
| 定植→树 | `bre_tree` 非软删 COUNT | 树数(评价群体基数) |
|
||
| 树→入选 | `bre_selection_result` 非软删 COUNT | **选择强度** selection_rate = 入选数/树数×100 |
|
||
|
||
缺环节的组合比率列留 NULL(`bre_cross_combination` 主表 LEFT JOIN 六源,按组合一行)。
|
||
|
||
**实现**:
|
||
- `backend/sql/weld_combination_funnel.sql`:`v_combination_funnel` 普通 VIEW(DROP IF EXISTS + CREATE OR REPLACE 幂等,F2 决策保 fresh 不用 MV),psql 应用(create_all 只建 ORM 表,视图须手写 SQL)。
|
||
- `statistics/service.py::combination_funnel()`:查视图返回 `{rows, n}`(Numeric→int/float 归一),视图未就绪 CustomException 提示。
|
||
- `statistics/controller.py`:`GET /statistics/combination-funnel`(`module_bre:statistics:query` 权限)。
|
||
|
||
**验证(`Temp/claude/e2e_combination_funnel_20260804.py`,3 组全过)**:
|
||
|
||
| 组 | 断言 |
|
||
|---|---|
|
||
| [1] | 全六级组合:150 花/50 果→结实率 33.33%、100 种(发芽率均值90%)/80 苗→出苗率 80%、55 定植/3 树/2 入选→选择强度 66.67%,逐计数精确断言 |
|
||
| [2] | 仅授粉组合:fruit_set=50.0% 算得出,种/苗/定植/树/入选 全 NULL(LEFT JOIN 正确性) |
|
||
| [3] | 跨会话持久化:commit 后新会话读同值 |
|
||
|
||
> **工程教训**:首跑清理阶段 FK 崩——helper 里 `db.add()` 后**未 flush 就取 `.id`** 拿到 None,删除 `WHERE id IN (None,…)` 不命中留下孤儿行。修复:add 后先 `await db.flush()` 再取 id。此为探针自身 bug,非视图/端点缺陷。
|
||
|
||
---
|
||
|
||
## 八、分子育种「建数据能力」(2026-08-04)
|
||
|
||
> 分子层四表 DDL 早已在 `backend/sql/bre_tables.sql`(§3.7),但 module_bre 无 ORM/服务 → DNA 指纹/QTL/GWAS/GS 全 inert。用户拍板先建「数据能力」:四模块 CRUD + Excel 导入导出 + VCF 导入 + 指纹防错(无性系混杂检测)。GS/GWAS/GBLUP 引擎仍占位。菜单 900210-900213 由占位页切真实页面,900214 GWAS 保持 `_coming_soon`。
|
||
|
||
### 8.1 DDL 缺口与补列
|
||
|
||
`bre_genotype_sample` 原 DDL 无样本名字段(只有 dataset_id/source_type/source_id/sample_type/sample_date/method/lab/remark)。VCF 表头映射、UI 展示、指纹报告都靠样本名 → 按 weld 惯例补列(create_all 只建新表、不改既有表):
|
||
|
||
```sql
|
||
ALTER TABLE bre_genotype_sample ADD COLUMN IF NOT EXISTS sample_name varchar(128);
|
||
COMMENT ON COLUMN bre_genotype_sample.sample_name IS '样本名称(VCF 表头/UI 展示,可空)';
|
||
CREATE INDEX IF NOT EXISTS ix_bre_genotype_sample_dataset_name ON bre_genotype_sample (dataset_id, sample_name);
|
||
```
|
||
|
||
### 8.2 四模块五件套
|
||
|
||
| 模块 | 表 | 关键列 / 约束 | 导入必填 |
|
||
|---|---|---|---|
|
||
| marker | bre_marker | marker_name UNIQUE;chromosome/position/marker_type/panel/assembly_version | marker_name |
|
||
| genotype_dataset | bre_genotyping_dataset | dataset_name/platform/panel/purpose/run_date/lab | dataset_name |
|
||
| genotype_sample | bre_genotype_sample | **sample_name(weld 补)**;dataset_id FK→dataset | sample_name(dataset 名解析成 ID) |
|
||
| genotype_call | bre_genotype_call | sample_id/marker_id 双 FK + **UNIQUE(sample_id,marker_id)**;allele 按 VCF/GP 编码 | sample_name/marker_name(解析成 ID)/allele |
|
||
|
||
- **五件套**:model/schema/crud/service/controller,`module_bre/__init__.py` 注册。ORM 严格对齐 bre_tables.sql——分子表无 `status` 列,模型覆盖 `__table_args__`(`Index("ix_bre_<表>_created_deleted", "created_time", "is_deleted")`)跳基类默认 status 索引。
|
||
- **FK 存在性**:sample/call create/update 前 `assert_parents_exist`(父级软删也拦截→409「XX不存在或已被删除」)。
|
||
- **名称透出**:get_list/detail 后查 ref_map 填 dataset_name / sample_name / marker_name(seed_lot combination_name 同款 `_attach_fk_labels`)。
|
||
- **Excel 导入导出**:header_dict 中文头→列,名称解析成 ID;导入模板/导出 mapping_dict 含 created_by 名解析。
|
||
|
||
### 8.3 VCF 导入(POST /bre/genotype_call/import/vcf)
|
||
|
||
1. 跳过 `##` 行,定位 `#CHROM` 表头 → FORMAT 后为样本列,GT 在 FORMAT 子字段索引。
|
||
2. marker:ID 非 `.` 用 ID、否则 `CHROM:POS`,按 UNIQUE 查重 → 缺失建号(marker_type=snp、panel=dataset.panel)。
|
||
3. 样本:按 `(dataset_id, sample_name)` 查重 → 缺失建号(sample_type=vcf、method=genotyping,source 留空)。
|
||
4. GT:`|`→`/` 规范化;`.`/`./.`/`./` 跳过;allele 存 GT 编码(0/0、0/1、1/1)。
|
||
5. 内存 dict 以 `(sample_id, marker_id)` 去重(文件内重复 last-wins);已存在分型跳过 → **重跑幂等**;500/批批量 insert。
|
||
6. 返回 `{dataset_id, dataset_name, variants, samples, samples_created, markers_created, calls_inserted, skipped_missing}`。
|
||
|
||
### 8.4 DNA 指纹防错(GET /bre/genotype_call/fingerprint/check)
|
||
|
||
纯数据层比对,无外部依赖:
|
||
1. 取 dataset 内样本 + 分型结果,构建 `{sample_id: {marker_id: allele}}`,allele 规范化。
|
||
2. 两两比对:共同 marker `< min_markers` 跳过(信息量不足);否则 `identity = 匹配数/共同数`。
|
||
3. 判定:同源对(source_type+source_id 相同且非空)`identity < threshold` →「同源指纹不一致(疑似样品污染/取错)」;异源对 `identity ≥ threshold` →「异源指纹一致(疑似无性系混杂/标签互换)」。
|
||
4. 返回按 identity 降序的 pair 行(样本名含来源、共同数、匹配数、identity、标记)。
|
||
|
||
### 8.5 菜单 / 权限 / 前端
|
||
|
||
- `bre_menu.sql`:900210-900213 component_path 由 `_coming_soon/index` 切 `module_bre/{marker,genotype_dataset,genotype_sample,genotype_call}/index`;F 段按钮 `id=900700+seq*10+border`(八按钮:查看/查询/新增/编辑/删除/导出/导入/下载模板),`ON CONFLICT (id) DO NOTHING` 幂等;SUPER_ADMIN/ADMIN 角色关联 64 行。
|
||
- 前端:4 api .ts + 4 index.vue。genotype_sample 搜索/表单带 dataset 下拉;genotype_call 带 sample/marker 双下拉 +「导入 VCF」(dataset 下拉+文件上传,报计数)与「指纹检测」(dataset 下拉+min_markers+阈值,结果表两色标签:danger=同源不一致、warning=异源一致)两个自定义按钮/对话框。
|
||
|
||
### 8.6 e2e 验证(e2e_molecular_20260804.py)
|
||
|
||
| 组 | 断言 |
|
||
|---|---|
|
||
| [1] | 四模块 CRUD 闭环:dataset→marker→sample→call create/detail/update/list/options,FK 名称透出(sample.dataset_name、call.sample_name/marker_name) |
|
||
| [2] | 唯一键/父级:重复 (sample,marker)→409「已存在」;sample 引用不存在 dataset→409;重复 marker_name→409 |
|
||
| [1b] | 删除闭环:call→sample→marker→dataset 软删后 detail 不可见 |
|
||
| [3] | 指纹:6 样本 3 标记——同源对 1 处不一致→命中「同源指纹不一致」(identity 2/3);异源对全一致→2 对「异源指纹一致」(identity 1.0);同源全一致对不误报;共同 marker 不足(S-Y 仅 1 标记)对不出现 |
|
||
| [3b] | 空数据集指纹 samples=0/flagged=0 |
|
||
| [4] | VCF:6 variant × 3 样本——markers_created=5/samples_created=3/calls_inserted=13/skipped_missing=2;文件内重复标记 last-wins((P01,V100)=1/1);自动建号元数据(V500 chrom=2/pos=500/type=snp/panel=dataset.panel);**重跑幂等**(samples/markers/calls 均 0 新增) |
|
||
|
||
清理按 FK 逆序物理删(call→sample→marker→dataset,前缀 E2EM-),重跑幂等。
|
||
|
||
---
|
||
|
||
## 九、精修项落地:DUS 数据能力 + stage 感知 + k-fold CV + 公平性报告(2026-08-04)
|
||
|
||
### 9.1 缺陷背景(用户核实四条缺口,全部拍板落地)
|
||
|
||
用户核对后确认四条精修缺口属实并拍板「全部落地,更新文档,保留版本」:
|
||
1. **DUS/品种保护**:无 DUS 模块、无 UPOV TG/53 描述符观测模板(菜单 900230 预留仍占位);档位=**数据能力(三表)**。
|
||
2. **stage 感知**:`bre_trait.stage`(v2.0 定义)存在但 BLUP/选择指数/决策无视,童期/成株性状混用无警示。
|
||
3. **模型外部验证**:可靠性仅 PEV 法(内部);档位=**ABLUP + GXEBLUP 双支持** k-fold CV(外部预测准确度)。
|
||
4. **AI 伦理·分组偏差**:G×E 引擎已覆盖互作,缺按 site 的系统性 EBV 偏差/公平性报告。
|
||
|
||
### 9.2 DUS 数据能力(三表)
|
||
|
||
| 表 | 业务列 | 约束 |
|
||
|---|---|---|
|
||
| `bre_dus_descriptor` | descriptor_no(UPOV TG/53 特性号)、trait_id→bre_trait(可空=自由描述符)、trait_code 快照、descriptor_name、expression_type(QN/PQ/QL)、method、example_varieties(标准品种)、test_stage、required | uq_descriptor_no |
|
||
| `bre_dus_test` | test_name、germplasm_id→bre_germplasm、trial_study_id→bre_trial_study、tester、test_date、status(planning/testing/completed/report)、conclusion(pending/distinct/not_distinct)、report_path | uq_test_name |
|
||
| `bre_dus_observation` | dus_test_id→bre_dus_test、dus_descriptor_id→bre_dus_descriptor、value_numeric、value_text、expression_note | uq(test,descriptor) |
|
||
|
||
- 表新建走 **create_all**(不在既有 DDL,无需 weld);五件套 `module_bre/dus/` 注册 `/bre/dus_test/*`(descriptor 9 端点含导入导出+模板,test 9,observation 6)。
|
||
- 种子 `sql/bre_dus_seed.sql`:UPOV TG/53 桃描述符 **15 条**,`trait_code → bre_trait LEFT JOIN` 解析 trait_id(**8 条关联**),`ON CONFLICT(descriptor_no) DO NOTHING` 幂等。
|
||
- 菜单 `sql/bre_menu_refine.sql`:900230 component 切真实页 `module_bre/dus/index`;**G 段按钮 900800-900808**(perm `module_bre:dus_test:*`,八按钮含导入/下载模板)+ SUPER_ADMIN/ADMIN 角色关联。
|
||
- FK 名称透出:trait_name / germplasm_name / trial_study_name / descriptor_no+descriptor_name;描述符导入按中文头「关联性状编码」→trait_id。
|
||
|
||
### 9.3 stage 感知
|
||
|
||
- `_trait_meta_map` 读入 `trait.stage`(缺省 evaluation);`PredictionModel.stage` 落库(`sql/weld_refine.sql` 补列)+ 预测批次表展示(童期 warning / 成株 primary 标签)。
|
||
- `selection_index` 加 `stage` 入参:传 juvenile/evaluation 只纳入该阶段性状(异阶段写入 `skipped_stage`,同阶段无性状→409 带剔除清单);不传且横跨两阶段 → `stage_warning`(童期/成株性状清单 + 「证据来自不同发育阶段,需人工复核」)。
|
||
- `decision_preview` 同理:传 stage 时异阶段规则条件跳过(matched=None、reasons 不出现);不传且规则引用性状横跨两阶段 → `stage_warning`。
|
||
|
||
### 9.4 k-fold CV(外部验证)
|
||
|
||
- 求解器 `scripts/breeding_stats/blup.py::kfold_cv`:**sire 家系分层留出**(同家系不进训练/测试双折避免乐观,无父本个体自成一系)、固定种子;每折训练子集重估方差组分 → 留出个体 EBV 由系谱预测(个体保留在 A 矩阵、仅掩蔽表型)→ pearson+RMSE;单折失败(train<2 / G×E 结构不可辨识)记 None+warning 不中断。
|
||
- 落库 `bre_cv_result`(method=KFCV/ABLUP|KFCV/GXE、k/n_total/n_individuals/mean/pooled pearson/RMSE/cv_accuracy/h2)+ `bre_cv_fold` 明细;MLOps 溯源 data_version/input_hash/engine_version 复用。
|
||
- 端点:`POST /bre/statistics/cv/run`(trait_id/code/year/fixed/covariate/**gxe/gxe_env**/k 2~10,ABLUP 与 GXEBLUP 同入口)、`GET /bre/statistics/cv`(批次)、`GET /bre/statistics/cv/{id}`(含折明细)。
|
||
|
||
### 9.5 公平性报告(只读,不建表)
|
||
|
||
`GET /bre/statistics/fairness?prediction_id=&group_by=site&threshold_sd=1.0`:
|
||
- `site_summary`:每 site n_trees/n_groups/n_individuals/EBV 分布(mean/sd/min/max)/mean_reliability/**deviation=site_mean−grand_mean**、`flagged=|deviation|>threshold_sd×grand_sd`。
|
||
- `rank_consistency`:site 内组合均值 EBV 排名 vs 全体组合排名,共享组合 ≥2 时手写 Spearman。
|
||
- `gxe_pattern`:组合×site 单元均值(单元 n≥2),暴露跨 site 排名翻转。
|
||
|
||
### 9.6 验证(e2e_refine_20260804.py 全过 + vue-tsc)
|
||
|
||
| 组 | 断言 |
|
||
|---|---|
|
||
| [1] | DUS:三表 CRUD + 种子命中(15 条、TG/53/5=果形、≥1 条关联 trait_id)+ FK/唯一键/子表阻断删除/软删全 409 路径 |
|
||
| [2] | stage:selection_index 无 stage→警示含两性状;juvenile→traits 只含童期 + skipped_stage=[成株];decision_preview juvenile→成株规则条件跳过(matched=None)、童期规则命中部分株;ABLUP 批次 stage 落库(juvenile/evaluation 各对) |
|
||
| [3] | CV:ABLUP k=3 折 pearson 全非 None(sire 家系留出→留出株 EBV 收缩到均值、pearson=0 为设计预期)+ GXE k=2 跨 site 跑通 + 幂等重跑新批次 + data_version=“v2.7”/engine/input_hash + job SUCCESS |
|
||
| [4] | fairness:2 site 9 株 site_summary 2 行(deviation 异号、flagged 布尔)+ rank_consistency 2 行(shared≥2、spearman 非 None)+ gxe_pattern n≥2 单元 |
|
||
|
||
清理按 FK 逆序物理删(前缀 E2ER-),TG/53 种子描述符与既有数据不动。
|
||
|
||
---
|
||
|
||
## 十一、六项能力完善:MT-BLUP + GBLUP/ssGBLUP + DUS 特异性检验 + AMMI/FW 稳定性 + MLOps 重训回滚 + BLUP stage 拆分(2026-08-04)
|
||
|
||
### 11.1 缺陷背景(用户两轮复核核实六条缺口、逐项拍板「全部落地」)
|
||
|
||
1. **MT-BLUP**:Smith-Hazel 的 G 非对角仍用 Calo 校正 EBV 相关近似(`service.py` 已诚实文档化为回退),缺真遗传相关估计 → 拍板**成对双性状 BLUP**(非全多变量 REML)。
|
||
2. **GBLUP/ssGBLUP**:分子层只有数据能力(四模块 CRUD + VCF + 指纹),无 VanRaden G / 基因组选择引擎 → item 明确两者都做。
|
||
3. **DUS 特异性统计检验**:`conclusion` 纯人工(无判定端点)→ 拍板**参照=同 trial_study 自动 + 可显式指定**。
|
||
4. **AMMI/Finlay-Wilkinson 稳定性**:G×E 随机效应已估 σ²gxe,无跨环境稳定性排名。
|
||
5. **MLOps 自动重训 + 版本回滚**:APScheduler 在但统计无重训接线、无 is_active → 拍板**漂移检测端点 + 手动触发**,不注册 cron。
|
||
6. **BLUP stage 拆分**:run_ablup 只打标签(model_name 后缀)不按 stage 取数。
|
||
|
||
### 11.2 MT-BLUP(`scripts/breeding_stats/mtblup.py` + `statistics/service.py`)
|
||
|
||
- `mtblup.solve_bivariate(pedigree, phenos, code1, code2)`(ENGINE_VERSION=1.0.0):共享系谱复用 `blup._order_pedigree/_build_ainv` 建 A/A⁻¹;模型 y=[y1;y2] 堆叠、X/Z 块对角;Var(u)=G0⊗A(G0=[[Va1,ρ√(Va1Va2)],[·,Va2]])、Var(e)=diag(Ve1,Ve2)⊗I。**降维**:Va1/Ve1、Va2/Ve2 取自各性状单性状 REML(=既有 herit 来源),仅对 ρ∈[−0.99,0.99] 1-D golden-max 最大化精确 REML ll(复用 `_golden_max` + `_solve_gxe` 的 V=Z(G0⊗A)Z'+R、slogdet+yPy 模板)。返回 r_g/σa 矩阵/n_common/n_iter/converged/warning;单性状观测 <2 → 该性状 NAN。
|
||
- `run_genetic_corr(trait_ids, year)`:`_gather_shared_phenos` union 树集 + 树级均值 + 共享系谱;两两 bivariate,对角=单性状 h²·P_ii、非对角=r_g·√(G_ii·G_jj) 组装 G0,Higham 特征值截断投影半正定;落 `bre_genetic_corr_result`(trait_codes/matrix/sigma_a/heritability/pairs_json/n_common + data_version/input_hash/engine_version)+ `StatisticsJobModel(job_type="GENCORR")`;`list_genetic_corr` / `genetic_corr_detail`。
|
||
- `_smith_hazel_index` 加 `g_method="calo"|"mtblup"`(`selection_index` 透传):mtblup 时逐对 `solve_bivariate` 填 G 非对角,单对不收敛回退 Calo + warning 清单(不阻断指数);≥3 性状 r_g 三角不等式违反 → 特征值截断投影半正定;`extra["g_source"]="mtblup|calo"` 落库可审计。
|
||
- 端点:`POST /statistics/genetic-corr/run`(trait_ids 多选 + year)、`GET /statistics/genetic-corr`、`GET /statistics/genetic-corr/{cid}`。
|
||
|
||
### 11.3 GBLUP / ssGBLUP(`scripts/breeding_stats/genomic.py` + `statistics/service.py`)
|
||
|
||
- `build_g_matrix(genotypes, markers, *, maf_min, method=2, blend=0.02)`:dosage 0/1/2 样本×标记,缺格按列均值 2p 填充;MAF 过滤(`maf>=maf_min`,全滤 → ValueError);VanRaden **method1** G=ZZ'/2Σp(1-p)(diag≈1)/ **method2** G=ZDZ'(D=1/[2p(1-p)]);blend 岭 `G=(1−ω)G+ω·mean(diag)·I` 保证可逆。
|
||
- `solve_gblup(pedigree, phenos, G, *, tol)`:仅基因型个体入模型,MME 用 G⁻¹ 替代 A⁻¹;σ²a 用 `_golden_max` profile(仿 `blup.solve`);返回 ebv/reliability(=1−PEV/σ²a)/h2/σa/σe/converged/warning。
|
||
- `solve_ssgblup(pedigree, phenos, G, genotyped, *, tol)`:**H⁻¹ = A⁻¹ + [[0,0],[0, G⁻¹ − A22⁻¹]]**(Aguilar et al. 2010);A22=A[genotyped,genotyped] 稠密子阵 `np.linalg.inv`(病态加 `_RIDGE=1e-6`);**V 块必须用 H 协方差**——按 Aguilar 块公式构造完整 H(D=G−A22:H=A+[[A12A22⁻¹DA22⁻¹A21, A12A22⁻¹D],[D·A22⁻¹A21, D]];非基因型块 += L·D·L'、交叉块 += L·D、基因型块 = G),REML 似然 V=ZH[z,z]Z'+R,H⁻¹ 仅进 MME 系数矩阵。**修复前 V 块误用 `Hinv[z,z]` 致似然失构**。基因型+非基因型个体都出 EBV。
|
||
- `run_gblup(dataset_id, trait_id, trait_code, year=None, method="gblup"|"ssgblup", maf_min=0.05)`:取数 `bre_genotype_call` join `bre_marker` pivot sample×marker 剂量(`"0/0"→0/"0/1"→1/"1/1"→2`,多等位跳过);样本→个体映射 source_type='tree' 直连 + sample_name↔tree.tree_no/germplasm.cultivar_name 名称兜底,未映射→跳过 + note warning 清单;`genotyped = sorted(dosage)` 对齐 `build_g_matrix` 内部 `sorted(genotypes)` 行序(**修复前用全部映射树,零有效调用树会错位 G 索引静默污染 EBV**);input_hash 覆盖(基因型矩阵哈希 + phenos + ped);落 PredictionModel(method=GBLUP/ssGBLUP,engine_version 落库)+ PredictionValueModel(每树 EBV/rel/pa/rank)+ job_type="GBLUP";`list_genotyping_datasets`(genotyping_dataset 列表 + n_samples)。
|
||
- 端点:`POST /statistics/gblup/run`、`GET /statistics/gblup/datasets`;批次/EBV 复用 `list_predictions`(按 method 过滤)+ `ebv_ranking`。
|
||
|
||
### 11.4 DUS 特异性统计检验(`dus/service.py` + `fdist.py`)
|
||
|
||
- `fdist.f_icdf(p, d1, d2)`:F-CDF 二分反解;`t_crit(alpha, df)=√f_icdf(alpha, 1, df)`(t²=F(1,df))。
|
||
- `dus.distinctness(candidate_rows, reference_rows, descriptor_meta, alpha=0.01)`:
|
||
- **QN**:候选 vs 参照单因素 ANOVA → MSE,df → `LSD = t_crit(α,df)·√(MSE·(1/n_cand+1/n_ref))`;`|cand_mean − ref_mean| > LSD` → 该描述符 distinct(逐参照比较,任一超 LSD 即 distinct)。
|
||
- **PQ/QL**:表达状态众数——候选众数 ∉ 参照众数集 → distinct。
|
||
- 汇总逐描述符 {descriptor_no, name, expression_type, candidate_value, ref_values, statistic, critical, distinct};总体建议=≥1 个 **required** 描述符 distinct → distinct,否则 not_distinct,数据不足→pending(不判)。
|
||
- `test_distinctness(test_id, reference_test_ids=None, alpha=0.01)`:默认参照=同 `trial_study_id` 其他非软删 test(候选自身分组:同 germplasm_id 的测试合并为重复),可显式覆盖;取候选+参照观测+描述符 → 判定 → **落 `analysis_json`**(逐描述符表+建议+参照集+alpha+运行时间);`conclusion` 当前 pending 时自动填建议(人工可改)。`distinctness_report(test_id)` 读已存分析;DusTestOutSchema 加 analysis_json。
|
||
- 端点:`POST /bre/dus_test/distinctness/{test_id}`、`GET /bre/dus_test/distinctness/{test_id}`。
|
||
|
||
### 11.5 AMMI / Finlay-Wilkinson 稳定性(`scripts/breeding_stats/stability.py` + `statistics/service.py`)
|
||
|
||
- `finlay_wilkinson(table)`:每基因型对**环境指数**(该环境全基因型均值 `np.nanmean(Y, axis=0)`)回归 y_gj=b·I_j+a(lstsq)→ b/截距/R²/se_b/dev_ms;`flag_stable = |b−1| ≤ 2·se_b`,且**完美拟合(dev_ms≤1e-12·max(1,ptp(y)²))时 se_b 无信息量 → b≈1(|b−1|≤1e-6)才判稳**(修复前浮点 b 永不精确=1 且 se_b=0 → 误判不稳)。
|
||
- `ammi(table, n_components=2)`:μ+g+e 两因素分解 → 残差 SVD(np.linalg.svd,首引)→ λ1/λ2、每基因型 IPC1/IPC2 得分、`ASV=√((IPC1·SS_ipc2/SS_ipc1)²+IPC2²)`(Purchase 2000,IPC1 按 SS 比例缩放)、Wricke ecovalence=Σ(y_ij−y_i.−y_.j+y..)²、`ipc_variance`(各 IPC 解释比例);rows 按 ASV 升序 + rank。
|
||
- `run_stability(trait_id, trait_code, gxe_env="site"|"year", year=None, methods=("ammi","finlay"))`:两向表 genotype=clone(缺则 combination,再退 tree)× env=site(trial_study_id)/year(evaluate_year),每格多株均值(仿 `trait_values` 取数);有效格子 <2×2 → 409;落 `bre_stability_result`(detail_json + data_version/input_hash/engine_version)+ job_type="STABILITY";`list_stability` / `stability_detail`。
|
||
- 端点:`POST /statistics/stability/run`、`GET /statistics/stability`、`GET /statistics/stability/{sid}`。
|
||
|
||
### 11.6 MLOps 自动重训 + 版本回滚(`statistics/service.py` + `sql/weld_advanced.sql`)
|
||
|
||
- weld:`bre_prediction.is_active boolean default false`。`run_ablup`/GXE/GBLUP 落库:同 trait 无 active 批次 → 本批 active=true,否则 false(**版本链语义**)。
|
||
- `_gather_digest_inputs(trait_id, year)`:轻量抽取——仅组装进 `_input_digest` 的 phenos+pedigree(复用 run_ablup 的取数 SQL,不含 fixed/cov/门禁),供 drift 重算当前哈希(规避全量抽取风险)。
|
||
- `GET /statistics/model/drift?prediction_id=`:从该批次 job params_json 取 (trait_id,year,gxe,gxe_env) → `_gather_digest_inputs` 重算 → {prediction_id, changed, current_hash, stored_hash, data_version}。
|
||
- `POST /statistics/model/retrain?prediction_id=`:**漂移才重训**——`run_ablup`(同 params) 建新批次并 `await model_activate(new_id)` 转移 active(**修复前新批次默认 inactive**——旧批次仍 active,重训后新批次卡在非生效态,破坏版本链语义)→ {retrained, old_id, new_id, new_hash};无漂移 → {retrained:false, reason}。
|
||
- `POST /statistics/model/activate/{id}`:trait 内标 active(回滚原语);`list_predictions`/PredictionOut 加 is_active。
|
||
|
||
### 11.7 BLUP stage 拆分(`statistics/service.py` + `sql/weld_advanced.sql`)
|
||
|
||
- weld:`bre_trait_observation.stage varchar(16)`(观测级发育阶段,缺省继承 trait.stage)。TraitObservationModel + schema(create/update/out)+ 前端观测表单 stage 下拉(juvenile/evaluation)。
|
||
- `run_ablup(stage=None)` + RunStatsIn.stage:stage 给定 → 取数 `where(coalesce(obs.stage, trait.stage) == stage)`;过滤时 model_name 加 `_{stage}` 后缀 + PredictionModel.stage=生效 stage;未给定但数据 obs.stage 与 trait.stage 出现分歧 → note 警示("有 N 条观测标注了观测级 stage,但本次未按阶段拆分…",不阻断);GXE 分支同步应用;非法 stage → 409。
|
||
|
||
### 11.8 前端
|
||
|
||
- `statistics.ts`:runGeneticCorr/listGeneticCorr/geneticCorrDetail + runStability/listStability/stabilityDetail + runGblup/getGblupDatasets + modelDrift/modelRetrain/modelActivate + 类型。
|
||
- `statistics/index.vue`:新「遗传相关 MT-BLUP」(性状多选→相关矩阵表格)、「稳定性 AMMI/FW」(性状+env+methods→FW b/R²/flag 表 + AMMI IPC/ASV/rank 表)、「基因组选择 GBLUP」(dataset+性状+method radio+maf→批次/EBV 表)三 tab;ABLUP 运行对话框加 stage 三态(全部/童期/成株);Smith-Hazel 对话框加 g 矩阵来源 radio(Calo/MT-BLUP);预测批次表加「当前版本」标签 + 漂移检测/自动重训/设为当前版本按钮。
|
||
- `dus/index.vue`:DUS 测试行加「特异性判定」按钮→对话框(alpha + 参照默认同点 + 逐描述符结果表 + 建议)→「应用判定」写 conclusion。
|
||
- `vue-tsc --noEmit` 通过(EXIT=0)。
|
||
|
||
### 11.9 验证(`Temp/claude/e2e_advanced_*.py` 6 组全过)
|
||
|
||
- **stability**:3 组合×3 站点 FW b=2.0/1.0/−0.0、flag=F/T/F(C1 稳定)、r²=1/C2 None(常量响应 R² 无定义)、AMMI 9 格 IPC1≥IPC2 rank 升序、year 维度、非法 methods 409、list/detail。
|
||
- **stage**:juvenile/evaluation 各只含对应观测树 + model_name `_{stage}`、不传含全部 4 株 + note 警示、非法 stage 409。
|
||
- **mtblup**:r_g=0.99(y2=2·y1 强正相关)对称、σa12>0、h²∈(0,1)、n_common=4、Smith-Hazel g_method=mtblup `g_source` 落库;**顺带修 `_smith_hazel_index` 未定义变量 `tid` 真 bug**。
|
||
- **gblup**:GBLUP 5 EBV 非基因型株=0 + ssGBLUP 非零 + solve_ssgblup(V 块用 H、g 亲本 EBV 有限、G method1 diag_mean≈1)+ 样本 4 直连+1 名称兜底+1 全多等位(回归 genotyped 对齐修复)+1 未映射 warning + list_genotyping_datasets n_samples=6。
|
||
- **dus**:自动参照同点 5 测试、D1 LSD=1.239 df=3 t_crit=5.8409 distinct、D2 PQ distinct、D3 非必测 not distinct、analysis_json+conclusion 自动建议、显式参照覆盖、无重复 pending+warning。
|
||
- **mlops**:首批 active → 改观测 drift changed → retrain 新批次 active 旧 inactive → 无新漂移幂等 {retrained:false} → activate 旧批次回滚(直接断言 `model_retrain` 修复)。
|
||
- 后端重启 + openapi 确认 6 组新端点 + 2 新表(bre_genetic_corr_result / bre_stability_result)create_all;`weld_advanced.sql` psql `-w` 幂等。
|
||
|
||
### 11.10 本轮修的三处引擎级 bug(e2e 探针暴露)
|
||
|
||
1. **ssGBLUP V 块**(genomic.py):REML 似然 V=ZH[z,z]Z'+R 必须用 **H 协方差**,`Hinv[z,z]` 是把逆矩阵喂给协方差位置 → 似然失构、h² 失真。H 按 Aguilar 块公式构造。
|
||
2. **genotyped 与 G 行序错位**(service.py):`genotyped` 必须 `sorted(dosage)` 对齐 `build_g_matrix` 内部 `sorted(genotypes)`;用全部映射树时,零有效调用树(全多等位)会静默错位 G 索引污染 EBV。
|
||
3. **`_smith_hazel_index` 未定义 `tid`**(service.py):mtblup 分支取系谱树集的集合推导式引用未定义变量 → 首次走 g_method=mtblup 即 NameError。改 `{tid for tid, d in pheno_all.items() if any(c in d for c in cols)}`。
|
||
4. **`model_retrain` 不激活新批次**(service.py):重训后补 `await model_activate(new_id)`,否则新批次默认 inactive 卡在旧批次下,版本链断裂。
|
||
5. **`flag_stable` 完美拟合误判**(stability.py):残差≈0 → se_b=0 → `|b−1|≤2·se_b` 恒假(浮点 b≠1 精确)。改 dev_ms 阈值判定:完美拟合 → `|b−1|≤1e-6` 判稳。
|
||
|
||
### 11.11 收尾修复:统计二级菜单深链(前端,用户反馈"4 个二级菜单页面都一样")
|
||
|
||
统计分析下 4 个二级菜单(统计计算/育种值/选择指数与决策/图形分析)的 `component_path` 均指向 `module_bre/statistics/index`,而该页是单页多 tab(`activeTab` 默认 `batches`)且不读路由 → 点谁都落在"模型批次"页。修复:`statistics/index.vue` 增 `useRoute()` + `ROUTE_TAB_MAP`,`activeTab` 初始值按路由取。**关键坑**:数据库 `sys_menu.route_path` 实为**相对路径**(`statistics`/`prediction_value`/`selection_decision`/`statistics_chart`),经父级 `/breeding` 拼接后实际 URL 是 `/breeding/statistics/...`,与 seed SQL 写的 `/bre/...` 绝对路径**不一致**——故**必须按 `route.name` 匹配**(StatisticsCalc→batches、PredictionValue→ebv、SelectionDecision→index、StatisticsChart→correlation),而非 `route.path`(首次按 path 匹配 `/bre/...` 全部落空,用户刷新仍默认页)。四个菜单路由 `name` 各异,RouterView 缓存键 `name+params` 不同 → 每次点击组件重挂载,深链可靠。图形分析无专属 tab,暂归"相关性"。`pnpm type-check` EXIT=0,vite(base=/web,端口 5666)HMR 生效。
|
||
|
||
## 十二、田间试验精度补强·砧木×接穗随机互作 G×R(2026-08-04)
|
||
|
||
### 12.1 缺陷背景(用户核实两条精度缺口,拍板先做 G×R)
|
||
|
||
用户核实田间试验设计精度两条缺口:① **无 R 侧空间协方差**(行-列 AR1×AR1,当前 `np.eye(m)*Ve` 纯对角)——该项需先补 `tree.row_no/col_no` 数据与设计图,留待后续;② **无 scion×rootstock(G×R)随机互作**——`rootstock` 当前仅作固定哑变量(v2.0 ⑤ 砧木建模铁律「BLUP 固定效应扣除」),无第三个随机效应槽。用户拍板**先做 G×R 随机互作**(探索到跑通真实数据档位成本可控)。
|
||
|
||
### 12.2 架构决策
|
||
|
||
- **结构同构、求解器零改动**:G×E 分支 `_solve_gxe`(blup.py)的 Z₂ 已按 `(基因型,因子水平)` 分组配 `I·σ²` 交互,**因子无关**(pair-grouping 机制),G×R 只是把分组键换成 `(基因型, 砧木水平)`,MME/REML/输出键全部复用。
|
||
- **Z₂ 单槽位 → G×E/G×R 必须互斥**:`if gxe and gxr` 显式 409(文案「共用同一随机效应槽(Z₂)」),前端再加双向互斥 watcher 兜底。
|
||
- **克隆坍缩系谱共享**:`gxe_pedigree`(clone 树坍缩为 `c{clone}` 节点,父母本=组合/种质亲本)构建块从 `if gxe:` 内**上移**为 G×E/G×R 共享(纯构建、ABLUP 路径不执行)。
|
||
- **rootstock 移出固定效应**:`gxr=True` 时强制 `fixed_effects` 剥离 `rootstock`,p_est 不再计入砧木水平,防与 Z₂ 共线。
|
||
|
||
### 12.3 求解器(`backend/scripts/breeding_stats/blup.py`)
|
||
|
||
`_solve_gxe` 加两个可选参数(默认值保现有 G×E 行为逐字节不变):
|
||
- `factor_label="G×E"`——未收敛警告「{factor_label} 似然面可能极平/边界最优」;
|
||
- `factor_name="环境"`——方差归零警告「{factor_label} 方差分量收敛到 0(数据不支持基因型×{factor_name}互作)」。
|
||
- 公开 `solve()` 加参并透传 `_solve_gxe`(**服务端走的是 `solve()`,首次探针即暴露漏传**)。
|
||
- `ENGINE_VERSION` "1.1.0"→"1.2.0"。
|
||
|
||
### 12.4 服务端(`statistics/schema.py` + `controller.py` + `service.py`)
|
||
|
||
- `RunStatsIn` + `run_ablup` 加 `gxr: bool`;controller 透传。
|
||
- 互斥门禁(job 创建前):`gxe and gxr` → 409。
|
||
- job_type=`"GXR" if gxr else ("GXE" if gxe else "ABLUP")`;params_json 落 `gxr`。
|
||
- `elif gxr:` 分支镜像 G×E site 分支:
|
||
- 遍历 `phenotypes.items()`(int tid),`rid = f"t{tid}"`(**字符串键**)查 `rootstock_map[rid]`(`rs{rootstock}`),缺砧木 → `skipped++` 跳过并 note 警示;无任何可分砧木记录 → 409。
|
||
- `rec_gxr[rid] = (grp, rs)`:grp 优先 `c{clone_of[tid]}`(克隆坍缩)、退 `f{combo_of[tid]}`;`rec_map[rid]` 同理。
|
||
- 门禁三件套镜像:`n_cross_rootstock`=同基因型跨砧木数==0、max cell_counts<2、`residual_df = m - q - p_est`<1(p_est 含 intercept + trial_study 水平-1(若固定)+ covariate,**rootstock 不计入**)→「G×R 不可辨识」409。
|
||
- `rec_fixed`(仅 trial_study,经 `fixed_map`)+ `rec_cov`(cov_map);rootstock 从 `fixed_effects` 剥离。
|
||
- 求解:`blup.solve(gxe_pedigree, rec_phenos, gxe=rec_gxr, record_map=rec_map, fixed=..., covariate=..., factor_label="G×R", factor_name="砧木")`。
|
||
- `method="GXRBLUP"`;model_name `GXRBLUP_{trait}` + `_{stage}?` + `_{ts}`。
|
||
- note:`stage/sigma_a/sigma_gxr(=sigma_gxe)/sigma_e/gxr_ratio(=gxe_ratio)/n_cross_rootstock(=n_cross_env)/n_genotypes/warning/skipped/stage_note`。
|
||
- EBV 写入共用段 accuracy 个体集按 gxr 选 `gxr_tree_ids`。
|
||
- `_DATA_VERSION` "v2.9"→"v2.10"。
|
||
|
||
### 12.5 前端(`statistics.ts` + `statistics/index.vue`)
|
||
|
||
- `RunStatsPayload.gxr`。
|
||
- G×E tab `gxeEnabled` 后加 `<el-checkbox v-model="gxrEnabled">启用砧木×接穗互作(G×R)随机效应</el-checkbox>`;双向互斥 watcher;运行按钮文案「运行 MET / GxE / GxR」、辅助文案三分支。
|
||
- 批次表互作方差列 v-if 扩为 `GXEBLUP || GXRBLUP`;`fmtGxeNote` 按 `n.sigma_gxr != null` 分支(σ²gxr/σ²gxe、gxr_ratio/gxe_ratio、跨砧木/跨环境基因型)。
|
||
- `runGxe` payload 加 `gxr: gxrEnabled.value`;`vue-tsc` 通过(EXIT=0)。
|
||
|
||
### 12.6 验证(`Temp/claude/e2e_gxr_20260804.py`,4 组全过)
|
||
|
||
1. **正例**:2 基因型(clone)× 2 砧木 × 2 株 = 8 株,强交叉互作观测(clone1×R1 高/R2 低、clone2 相反)→ GXRBLUP、job_type=GXR、σ²gxr=74.8>0、n_cross_rootstock=2、n_genotypes=2、8 EBV 行。
|
||
2. **门禁负例**:同基因型仅跨 1 砧木 → CustomException「G×R 不可辨识」。
|
||
3. **互斥负例**:`gxe=True, gxr=True` → CustomException「Z₂」。
|
||
4. **rootstock 剥离**:`gxr=True` 同时 `fixed_effects=["rootstock"]` → 剥离后不共线、正常出 σ²gxr。
|
||
- 后端重启(含孤儿 reloader worker 清理)后 openapi 确认 `gxr: True` 入参;`vue-tsc` EXIT=0。
|
||
|
||
## 十三、基因组选择(GS)实证严谨性·GBLUP/ssGBLUP 专用 k-fold 交叉验证(2026-08-04)
|
||
|
||
### 13.1 缺陷背景(用户核实两条 GS 实证缺口,拍板先做 k-fold)
|
||
|
||
用户核实 GS 实证严谨性两条缺口:
|
||
① **GS 缺自身交叉验证**——`run_cv`/`kfold_cv`(blup.py)是 A 矩阵系谱预测(ABLUP/GXE),GBLUP 落库的 `accuracy=√mean(reliability)` 是**理论准确度**(PEV 推导),**对模型误设不敏感**:G 算错/标记编码错/遗传力先验偏时 PEV 可靠性依然漂亮,真实预测能力却崩了,只有掩蔽留出「GEBV vs 表型 pearson」能测出实证预测能力。
|
||
② **SSR panel 难构 VanRaden G**——`_dosage_from_gt` 只吃 `0/1` 两段整数且 `max≤1`;SSR 片段编码(`168/174`)、多等位(`0/1/2`)、phasing(`0|1`)全部被丢弃 → SSR calls 静默变缺失 → `m_after_maf→0` 时 `build_g_matrix` 直接 ValueError「MAF≥0.05 的标记为 0」→ 409。这是"有引擎但数据接不进"的现实坑。
|
||
|
||
用户拍板**先做 GS k-fold(①)**;SSR dummy 编码(②)留待后续。
|
||
|
||
### 13.2 架构决策
|
||
|
||
- **核心洞察——掩蔽留出已原生支持**:`_profile_solve`(genomic.py)已实现「仅观测子集进模型、**全部个体**出 EBV」——非观测个体 Z 行全 0、经 G⁻¹/H⁻¹ 的 cross-relationship 预测(e2e_advanced_gblup 已验证非基因型株 tree4 出非零 EBV)。所以 GS CV 掩蔽留出 = 传训练子集 phenos → 全个体 GEBV → 取留出个体与观测表型相关。**G/H/Hinv 只建一次,逐折只换 z_train 子阵**(折划分不改变关系矩阵)。
|
||
- **折划分差异(与 ABLUP 的本质区别)**:ABLUP 的 `kfold_cv` 按 **sire 家系分层留出**(同一家系不跨训练/测试,防同家系信息泄漏)。GS 的候选是 genotyped∩phenos 的**同世代样本、无系谱家系树**,用**固定种子随机分层**(round-robin 到 k 折)即标准做法——文档明示该差异,将来要防近亲泄漏可加「按 G 关系分层」。
|
||
- **方法互通**:`method="gblup"` → 关系矩阵 G(individuals=genotyped);`method="ssgblup"` → `_build_h` 合并关系阵 H(individuals=order,含非基因型亲属)。两者共用一个输出 dict 形状(与 blup.kfold_cv 逐键对齐)。
|
||
|
||
### 13.3 求解器(`backend/scripts/breeding_stats/genomic.py`)
|
||
|
||
1. **抽取 `_build_h(pedigree, genotyped, G, *, ridge, extra_base)`**:solve_ssgblup 的 base/non_base→`_order_pedigree`→A/Ainv→Hinv→H 构建提成 helper,返回 `(order, idx, H, Hinv)`。solve_ssgblup 改调(行为不变)。
|
||
- **缺失基因型个体按 base 补入系谱**(原 `if missing_gen: raise ValueError` 改 `for g in missing_gen: base.append(g)`)——无表型基因型树不再触发 ValueError,CV/ssGBLUP 更稳(与 phenos 兜底一致)。
|
||
2. **新增 `kfold_cv_genomic(phenos, G, genotyped, *, k=5, seed=20260804, method="gblup", pedigree=None, ridge)`**:
|
||
- `method="gblup"`:individuals = sorted(genotyped)(G 行序);`relmat_inv = np.linalg.inv(G)`(奇异回退 pinv);zmat_full = G。
|
||
- `method="ssgblup"`:`_build_h(pedigree, genotyped, G, extra_base=list(phenos))` → individuals = order;relmat_inv = Hinv;zmat_full = H。
|
||
- `cand = sorted(genotyped ∩ phenos)`;`n_total = len(cand)`;`<2` → 空 folds + warning(对齐 blup.kfold_cv)。
|
||
- 折划分:`rng = random.Random(seed)`,shuffle cand → `bin_of = {c: i % k}`。
|
||
- 逐折:`test_set = {c: b == fold}`;`train_phenos = phenos − test_set`;`z_train = 观测个体索引`;`_profile_solve(zmat_full[ix_(z,z)], X, y, relmat_inv, n, z_train)` → 全 EBV → 留出个体 GEBV vs 表型 `blup._pearson` + RMSE;单折失败(训练<2/测试空/求解异常/未收敛/测试有效<2)→ error 记 warning **不中断**。
|
||
- 输出 dict 与 blup.kfold_cv **逐键对齐**(`k/n_total/n_individuals/folds/mean_pearson/mean_rmse/pooled_pearson/pooled_rmse/cv_accuracy/h2/warning`)。
|
||
3. `ENGINE_VERSION` "1.0.0"→"1.1.0"。
|
||
|
||
### 13.4 服务端(`statistics/schema.py` + `controller.py` + `service.py`)
|
||
|
||
- **`_gather_gblup_inputs(dataset_id, maf_min)` 提取**:run_gblup 的 dataset→samples→call_rows→markers→sample→tree 映射→dosage→`build_g_matrix`→genotyped 装配(约 60 行)提成 helper,返回 `(dosage, marker_order, genotyped, G, g_meta, unmapped)`。run_gblup 改调(行为逐字节不变),GS CV 复用。**e2e_advanced_gblup.py 复跑兜底回归**。
|
||
- **`run_cv` 签名扩展**:加 `dataset_id: int | None = None, method: str | None = None, maf_min: float = 0.05`;params_json 落三键。
|
||
- **GS 分支**(公共表型/系谱装配后、`elif gxe:` 前,与 G×E/ABLUP **互斥**——双开时 GS 优先):
|
||
- `_gather_gblup_inputs(dataset_id, maf_min)` → `gs_phenos = {f"t{tid}": v}`(键对齐 run_gblup "t{tid}" 约定)→ `kfold_cv_genomic(gs_phenos, G, genotyped, k=k, method=method, pedigree=pedigree)`。
|
||
- method 名 `"KFCV/GBLUP"` / `"KFCV/ssGBLUP"`(method varchar(16) 放得下)。
|
||
- input_hash = sha256(`_input_digest(pedigree, gs_phenos)` + `\n` + geno_str),geno_str 镜像 run_gblup(`f"{s}|{mk}|{dosage[s].get(mk, '.')}"` 全排序)。
|
||
- engine_version 按分支:GS 用 `genomic.ENGINE_VERSION`,ABLUP/GXE 用 `blup.ENGINE_VERSION`(`cv_engine_version`/`method_name` 先默认后覆盖)。
|
||
- **schema `CvRunIn`** + controller run_cv 透传 `dataset_id/method/maf_min`。
|
||
- `_DATA_VERSION` "v2.10"→"v2.11"。
|
||
|
||
### 13.5 前端(`statistics.ts` + `statistics/index.vue`)
|
||
|
||
- `CvRunPayload` 加 `dataset_id?/method?/maf_min?`。
|
||
- CV tab 加 **mode radio(ABLUP / GS)**:GS 模式显示基因型数据集下拉(复用已加载 `gbDatasets`)+ method radio(GBLUP/ssGBLUP)+ MAF≥ 输入;**隐藏 G×E 控件**;辅助文案分支「掩蔽留出 GEBV vs 表型 pearson(实证预测能力,固定种子随机分层)」。
|
||
- `submitCv` 按 mode 组装 payload(GS 传 dataset_id/method/maf_min);`vue-tsc` EXIT=0。
|
||
|
||
### 13.6 验证(`Temp/claude/e2e_gblup_cv_20260804.py`,3 组全过 + 回归)
|
||
|
||
构造:5 家系 × 3 全同胞 = 15 株(每系独立组合+亲本种质),10 标记(MK0/MK1 为 QTL 效应 2.0,家系 QTL 剂量 `[(2,2),(2,1),(1,2),(1,0),(0,0)]`→遗传值 8/6/6/2/0,非 QTL 标记 `(f*3+j)%3` 家系特征化),表型 = 12 + 2·dose(MK0) + 2·dose(MK1) + 低噪(±0.3),家系内基因型一致 → 留出预测靠 G/H 同家系交叉关系,强信号。
|
||
|
||
1. **GBLUP 正例**:`run_cv(trait, dataset_id, method="gblup", k=5)` → job SUCCESS;`CvResultModel.method=="KFCV/GBLUP"`、`cv_accuracy=0.794 > 0.3`、`==mean_pearson`、n_total/n_individuals=15/15、input_hash 64hex、engine_version=1.1.0、5 折 n_train/n_test≥1、`CvFoldModel` 5 行。
|
||
2. **ssGBLUP 正例**:`method="ssgblup"` → `"KFCV/ssGBLUP"`、cv_accuracy=0.794 > 0.3(H 合并系谱+标记,家系内同基因型仍强预测)。
|
||
3. **门禁负例**:dataset 仅 1 个无映射样本(sample_name=NO_MATCH)→ `CustomException`「基因型样本均无法映射到单株」,FAILED job 落库。
|
||
4. **回归**:`e2e_advanced_gblup.py` 复跑全过(`_gather_gblup_inputs` 提取后 run_gblup 行为不变:h²/5 条 EBV/非基因型株 EBV=0、note 未映射警示)。
|
||
- 后端重启(含孤儿 reloader worker 清理)后 openapi 确认 `CvRunIn` 出现 `dataset_id/method/maf_min`;`vue-tsc` EXIT=0。
|
||
|
||
## 十四、现代桃育种领域覆盖·S-等位基因交配兼容性 + 抗病/需冷量性状字典(2026-08-04)
|
||
|
||
### 14.1 背景(用户核实四方向覆盖,拍板按建议次序做)
|
||
|
||
| 方向 | 核实结论 | 处置 |
|
||
|---|---|---|
|
||
| ① S-等位基因(自交不亲和)交配兼容性 | **完全未建模**:`bre_pollen`/`bre_pollination` 无 S-allele 字段、`bre_cross_combination` 无兼容性校验、"配了不结"硬需求空白 | 落地(本批) |
|
||
| ② 需冷量/需热量 | 环境侧已建(`bre_germplasm.chilling_requirement` 属性 + `bre_environment_condition.chilling_hours/GDD`),**选种性状侧 bre_trait 缺失**(66 行字典无一条) | 落地(本批) |
|
||
| ③ 抗病性状(细菌性穿孔病/褐腐病/白粉病) | `bre_germplasm.disease_resistance` 仅自由文本,**bre_trait 一条都没有** | 落地(本批) |
|
||
| ④ MAS/QTL/GWAS 闭环 | 900214 仍 `_coming_soon`,发现层(GWAS/QTL 定位→MAS)完全缺失 | 留待单独立项 |
|
||
|
||
关键事实:**统计引擎 `_trait_meta_map` 仅消费 `data_type='numeric'` 的性状**(EBV/选择指数/决策候选),故抗病/需冷量必须建 numeric 而非 categorical 分级;桃属配子体自交不亲和(S-RNase),`Sf` 等位为自交亲和型(SI 功能缺失),多数商业化品种携带。
|
||
|
||
### 14.2 ②③ 性状字典种子(`backend/sql/bre_disease_chilling_traits.sql`)
|
||
|
||
幂等 `ON CONFLICT (trait_code) DO UPDATE`,新增 **5 条** numeric trait,全部 `into_ebv='1'`(选种目标)+ `direction='asc'`(低值优):
|
||
|
||
| trait_code | 名称 | category | unit | 说明 |
|
||
|---|---|---|---|---|
|
||
| `disease_shot_hole` | 细菌性穿孔病 | 抗病性 | 级 | 0-5 级病情指数(0=免疫…5=高感),`valid_min=0/valid_max=5`,h²=0.3 |
|
||
| `disease_brown_rot` | 褐腐病 | 抗病性 | 级 | 同上 |
|
||
| `disease_powdery_mildew` | 白粉病 | 抗病性 | 级 | 同上 |
|
||
| `chilling_requirement` | 需冷量 | 生态适应性 | h | 打破休眠 0~7.2℃ 低温累计小时(0-3000),h²=0.5 |
|
||
| `heat_requirement` | 需热量 | 生态适应性 | GDD | 发芽前 >7.2℃ 有效积温(0-10000),h²=0.4 |
|
||
|
||
`stage='evaluation'` + `method` 测定说明;前端 trait 页 category 自由文本自动显示、0 改动。
|
||
|
||
### 14.3 ① S-等位基因建模(`germplasm` + `cross_combination`)
|
||
|
||
- **`bre_germplasm.s_alleles`**(`String(32)`,如 `S1/S3`;`Sf`=自交亲和型):model + schema(Create/Update/Out)+ `ALTER TABLE` + `COMMENT`。
|
||
- **兼容校验**(`cross_combination/service.py`):
|
||
- `_parse_s_alleles(raw)`:分隔符 `/ , ;` → 归一化小写等位集合;空白返回 None。
|
||
- `_s_compat_check(female_s, male_s)`:**任一亲本含 `sf`→full 放行**(Sf 不排斥);否则共享 2 个→`none`、1 个→`half`、0 个→`full`;缺 S 数据→`unknown` 跳过。
|
||
- `_check_s_compat(female_id, male_id)`:读亲本 s_alleles → `none` 抛 `CustomException` 409「S-等位基因完全不相容(共享 …),该组合无法坐果」(**"配了不结"硬门禁**);`half` 返回警示文案。
|
||
- `create`/`update` 在亲本存在性断言后调用;`CrossCombinationOutSchema.s_compat`(可选派生字段)落半兼容警示;**同亲本自交共享 2 等位自然被 409 拦截**(除非含 Sf)。
|
||
|
||
### 14.4 前端
|
||
|
||
- germplasm 表单加 **S-等位基因** 输入(type input,placeholder「如 S1/S3;Sf=自交亲和型」)+ 导出列;`germplasm.ts` `GermplasmForm/GermplasmTable` 加 `s_alleles?`。
|
||
- cross_combination 组合提交**包装 createApi/updateApi**:响应含 `s_compat` 则 `msg.warning` 展示(统一消息入口);409 由统一错误处理自动提示。
|
||
|
||
### 14.5 验证(`Temp/claude/e2e_s_allele_20260804.py`,6 组全过)
|
||
|
||
1. **纯函数 8 例**:S1/S3×S1/S3→none、×S2/S4→full、×S1/S2→half、S1/Sf×S1/S1→full、大小写/混合分隔→none、缺数据→unknown、`_parse_s_alleles` 归一化断言。
|
||
2. **service 层 create**:共享 S1/S3→409「不相容」;共享 S1→`s_compat` 半兼容文案;0 共享→无警示;Sf 放行;缺 S 跳过。
|
||
3. **②③ 落库核验**:bre_trait 5 条 numeric+asc+into_ebv=1 已落库。
|
||
4. **openapi 核验**:`BreedingGermplasm{Create/Update/Out}.s_alleles` + `CrossCombinationOut.s_compat`。
|
||
5. `vue-tsc` EXIT=0;后端重启后核验。
|
||
|
||
## 十五、GWAS/QTL/MAS 标记辅助选择闭环(2026-08-04)
|
||
|
||
> v2.13 §十四 标记「④ GWAS/QTL/MAS 闭环留待后续单独立项」——本轮单独立项落地,补齐**发现层**:GWAS/QTL 定位 → 显著标记 → MAS 面板,900214 占位页翻真实页。桃在成熟期/果重等位点已有已知 QTL,MAS 让童期幼苗在无表型/无 EBV 时也能被标记辅助选择。
|
||
|
||
### 15.1 求解器 `backend/scripts/breeding_stats/gwas.py`(`ENGINE_VERSION=1.0.0`,纯 numpy 零 scipy)
|
||
|
||
- **模型**:逐标记单标记回归 `y ~ μ + PC1..PCn_pc + marker`;加性效应=标记回归系数。
|
||
- **群体结构**:标记剂量矩阵(缺失按列均值填)中心化 → `np.linalg.svd` 前 n_pc 个主成分得分(`pc_scores = U[:,:n_pc]·s[:n_pc]`)作协变量。
|
||
- **p 值**:`t = coef/SE`,`p = fdist.f_pvalue(t², 1, df)`(df = n − n_pc − 2)——**复用 DUS LSD 已验证的正则不完全 beta,零 scipy 新依赖**。
|
||
- **多重检验**:`threshold_bonf = sig_level/m_after_maf`;BH-FDR q(numpy argsort 自底向上保单调)。
|
||
- **QTL 定位**:sig_bonf 标记按 chromosome 排序,相邻间距 < qtl_window 合并簇,簇内最小 p 为峰标记(单显著标记也落 QTL 兜底)。
|
||
- **共线兜底(本轮关键修复)**:非 QTL 标记与 PC 共线时 XtX 奇异,`np.linalg.inv` 返回病态(负对角元 → `sqrt` 域错)。改**微小岭回归** `reg=1e-8·max(diag(XtX))` 兜底——共线方向 SE 大而有限 → t 小 → p≈1(效应被 PC 吸收,正确非显著);与群轴正交的 QTL 标记不受影响(1e-8 相对岭可忽略)。
|
||
- MLM 预留:method 参数(gwas/ssgwas),本轮仅实现 gwas。
|
||
|
||
### 15.2 数据装配与 5 张新表
|
||
|
||
- **`_gather_gwas_inputs(dataset_id, maf_min)`**(service.py 新 helper,仿 `_gather_gblup_inputs` 但 marker 查询补 chromosome/position)→ `(dosage, marker_order, markers_meta, genotyped, unmapped)`。**独立 helper,run_gblup/run_cv 零回归**。
|
||
- **`bre_gwas_result`**(批次:n_individuals/n_markers/m_after_maf/maf_min/n_pc/sig_level/threshold_bonf/n_sig_bonf/n_sig_fdr/n_qtl/data_version/input_hash/engine_version/remark)
|
||
- **`bre_gwas_snp`**(逐标记:marker_id/marker_name/chromosome/position/maf/effect/se/t_value/p_value/neg_log10p/q_value/sig_bonf/sig_fdr,FK CASCADE)
|
||
- **`bre_qtl`**(trait_id/chromosome/start_bp/end_bp/peak_marker_id/peak_marker_name/peak_p/n_markers/effect/source=known|gwas/gwas_result_id)
|
||
- **`bre_mas_panel`** + **`bre_mas_panel_marker`**(favorable_dose/direction=high|low/effect,UNIQUE(panel,marker))
|
||
- ORM 于 `statistics/model.py`(ModelMixin 全套),`create_all` 建表 + `backend/sql/weld_gwas.sql` 幂等 `CREATE TABLE IF NOT EXISTS` 双保险。
|
||
|
||
### 15.3 服务端端点与 MAS 决策 hook
|
||
|
||
- `POST /bre/statistics/gwas/run`(GwasRunIn: dataset_id/trait_id/trait_code/year/method/maf_min/n_pc/sig_level/qtl_window)→ job_type=GWAS,`_gather_gwas_inputs` + `asyncio.to_thread(gwas.run_gwas)` + input_hash(系谱+表型+基因型确定性序列化)+ engine_version;成功落 bre_gwas_result + bre_gwas_snp 批量 + bre_qtl(source=gwas)。
|
||
- `GET /bre/statistics/gwas/list` + `GET /bre/statistics/gwas/{id}`(result + snps + qtls)。
|
||
- `bre_qtl` CRUD(已知 QTL 录入 source=known)+ `bre_mas_panel` CRUD + `POST /bre/statistics/mas-panel/{id}/markers`(全量替换)。
|
||
- **decision_preview MAS hook**:条件循环 `("pheno","ebv")` → `("pheno","ebv","marker")`;`_mas_hit_map` 按候选树批量查 call → `_dosage_from_gt` → 有利剂量命中计数(direction=high: dose≥favorable_dose / low: ≤),`conds["marker"]={panel_id:{min_hits}}` —— **童期幼苗无表型/无 EBV 也能被标记辅助选中**。
|
||
- `_DATA_VERSION` v2.12;端点权限复用 `module_bre:statistics:*`(900071 已授 ADMIN,900214 翻转无需新增按钮)。
|
||
|
||
### 15.4 前端(`gwas.ts` + `gwas/index.vue`,900214 翻转)
|
||
|
||
- **GWAS 结果 tab**:批次表 + **Manhattan 图**(裸 `echarts.init`:x=染色体累加位置、逐染色体分组着色、显著点红色、Bonf 阈值 markLine、dataZoom)+ **QQ 图**(期望 −log10((i+.5)/m) vs 观测)+ SNP 表 + QTL 区间表。
|
||
- **QTL 定位 tab**:已知 QTL 录入 CRUD(trait/chromosome/区间/peak/effect/remark)。
|
||
- **MAS 面板 tab**:面板 CRUD + 标记选择对话框(marker/favorable_dose/direction/effect)。
|
||
- 运行对话框参数:dataset_id/trait_id/year/maf_min=0.05/n_pc=3/sig_level=0.05/qtl_window=1000000。
|
||
- `sys_menu 900214` → `component_path='module_bre/gwas/index'`(`bre_menu.sql` §6d);`vue-tsc` EXIT=0。
|
||
|
||
### 15.5 验证(`Temp/claude/e2e_gwas_20260804.py`,7 段全过 + 回归)
|
||
|
||
1. **run_gwas**:job GWAS/SUCCESS;bre_gwas_result n=32/m=200→200/bonf=2/fdr=2/qtl=2/input_hash 64 位/engine_version=1.0.0/threshold_bonf=sig/m_after_maf。
|
||
2. **bre_gwas_snp**:全字段(chromosome/position/neg_log10p/q_value);MK0/MK1 均 Bonf 显著且为所在染色体(chr1/chr3)最小 p(MK0 p=2.3e-05、MK1 p=5.4e-05)。
|
||
3. **QTL 定位**:2 区间峰标记=MK0/MK1,source=gwas 落库且挂批次。
|
||
4. **已知 QTL CRUD**:create/update/list(source=known)全过。
|
||
5. **MAS**:面板 2 标记(favorable_dose=2/high)→ decision_preview marker 条件(min_hits=1)命中 16 株 + **无表型童期幼苗 1 株**,低剂量株不命中。
|
||
6. **门禁**:dataset 无映射样本 → CustomException「无法映射」。
|
||
7. **清理**:finally FK 逆序自动清理。
|
||
- **回归**:`e2e_advanced_gblup.py` + `e2e_gblup_cv_20260804.py` 复跑**零回归**(GBLUP/ssGBLUP CV accuracy 0.794);openapi 核验 10 条 gwas/qtl/mas-panel 路径。
|
||
|
||
### 15.6 数据设计要点(避免 PC 吞噬 QTL 的实证教训)
|
||
|
||
- **标记数太少(如 20)且非 QTL 标记全为群轴共线**时,标记矩阵秩塌缩,SVD 前 n_pc 个 PC 本身跨越因果标记 → 效应被 PC 吸收、SE 膨胀、无显著标记(实测 MK0 p=0.77)。
|
||
- **正确设计**:2 群体结构(各 16 株)+ 200 标记,非 QTL 标记携带「群轴 + 组内独立伪随机变异」(PC1=群轴、PC2/3 与 QTL 标记低相关),QTL 标记剂量在群体内多重集一致(与群轴正交)→ PC 校正后效应保留、双 QTL Bonf 显著。
|
||
- **功效**:n=32、m=200、QTL 效应 2.0 时 p~1e-5(Bonf 阈值 2.5e-4 余量 10×);n=24 则功效不足(p~2.5e-4 擦线)。
|
||
|
||
## 十六、九缺口补齐:经典侧计算端点 + 分子侧严谨性 + 求解器核心(2026-08-04)
|
||
|
||
> 用户自 GWAS/QTL/MAS 闭环后重扫 12 项缺口,A1(S-等位)与 A4(G×R)已同日落地剔除,余 9 项拍板「全部补齐」,分三批独立 e2e + 回归。三批均 e2e 通过、回归零回归,后端重启 + openapi 核验 + HTTP smoke + 前端 vue-tsc EXIT=0。
|
||
|
||
### 16.1 批1 经典侧计算端点(纯计算不建表,`statistics/controller.py` + `service.py` + 前端 statistics/index.vue)
|
||
|
||
| 缺口 | 落地 |
|
||
|---|---|
|
||
| A5 数据质量 | `POST /statistics/data-quality`——`data_quality_report(trait_id, site_id?, tree_ids?)`:tree 级观测装配(同 run_ablup)+ 缺失率 + CV + **IQR** 与 **MAD 稳健 z-score** 双法异常标记,输出 `{trait, n_trees, missing_rate, cv, outliers, summary}`;前端「数据质量」对话框 |
|
||
| A3 遗传增益 | `POST /statistics/genetic-gain`——**ΔG=k·r_g·σ_A**:k 由 top_p 经 **Acklam 有理近似 Φ⁻¹**(纯 numpy 零 scipy)、r_g=批次 PA(√mean reliability)、σ_A=√h²·σ_P,逐轮 `{round, current_mean, ΔG_units, ΔG_pct_mean, next_mean, cumulative}` |
|
||
| A6 主动选配 | `POST /statistics/mating-recommend`——S-等位硬过滤(复用 `cross_combination._s_compat_check`:none 剔除/half flag)+ 亲缘 A 惩罚 `score=w_ebv·mid_parent_EBV−w_kin·max(0,r−threshold)`,`{pairs:[{female, male, ebv_mean, r, s_compat, score, flags}]}`;**计算端点不落库**(用户拍板) |
|
||
|
||
### 16.2 批2 分子侧严谨性(`gwas.py` / `genomic.py` / VCF 装配 / MAS 语义)
|
||
|
||
| 缺口 | 落地 |
|
||
|---|---|
|
||
| B1 EMMAX | `gwas._emmax`:零模型 y=Xβ+u+e(u~N(0,σ²g·K)),方差分量复用 `genomic._profile_solve`;**eigh 对角化** K=QΛQ' → V⁻¹=Q(σ²Λ+σ²eI)⁻¹Q';逐标记 GLS t²→`fdist.f_pvalue`;run_gwas 后处理抽共享函数,GLM 逐字节不变;`method="emmax"`(gwas 1.1.0) |
|
||
| B2 SSR 多等位 | VCF 按 ALT 数定 marker_type;`_allelic_from_gt` 每等位 0/1/2;3 处装配按 marker_type 分支 SSR 展开每等位一列;`build_g_matrix` 多等位 VanRaden 推广(genomic 1.2.0) |
|
||
| B3 QTL×E | `POST /statistics/gwas-qtl-x-e`:分环境 run_gwas 合并 QTL → stable(≥2 环境同号)/ env-specific / 异号 G×QTL 警示,计算端点不建表 |
|
||
| B4 MAS 语义 | `weld_mas_semantics.sql` 幂等 ADD COLUMN:mode/favorable_allele/haplotype_group;`_mas_hit_map` additive/dominance/recessive/allele/haplotype 五语义 |
|
||
|
||
### 16.3 批3 求解器核心(`blup.py`,ENGINE_VERSION 1.3.0)
|
||
|
||
- **A2 AR1×AR1 空间协方差** `solve_spatial`:e~N(0,σ²e·R)、R=AR1(ρ)⊗AR1(ρ)、R⁻¹ 纯 numpy eigh、REML 对 (h²,ρ) 坐标上升黄金搜索;`run_ablup(spatial=True)` → method=AR1×AR1/model_name=SPATIAL_*,ρ/σ²a/σ²e/h² 落 note;与 G×E/G×R 互斥、缺 row/col 坐标 409;`spatial=False` 逐字节不变。
|
||
- **A7 稀疏 A⁻¹+共轭梯度**:`_build_ainv_sparse`(COO)+ `_cg_solve`(max_iter=800/tol=1e-9);`use_sparse = n_with_parents>0 and n>N_SPARSE(1000)` 阈值分派 → `"solver":"sparse-cg"` + `cg_iter`;**Hutchinson k=100**(固定种子 20260804)估 PEV 对角 → `"reliability_approx":True`;收敛失败回退稠密;稠密路径(n≤1000)逐字节不变。
|
||
|
||
### 16.4 版本与验证
|
||
|
||
- `_DATA_VERSION` v2.13;ENGINE_VERSION:blup 1.3.0 / genomic 1.2.0 / gwas 1.1.0。
|
||
- **批1** `Temp/claude/e2e_data_mating_gain_20260804.py`:data-quality 命中离群株 / ΔG 自洽 / mating-recommend 剔除不相容对 + 亲缘惩罚生效 / 无观测 409 门禁。
|
||
- **批2** `Temp/claude/e2e_molrigor_20260804.py` 五段:EMMAX 复现双 QTL + SSR 混合 GBLUP 全标记进入 + QTL×E stable/env-specific + dominance/haplotype 语义命中 + 门禁。
|
||
- **批3** `Temp/claude/e2e_spatial_sparse_20260804.py` 三段:AR1×AR1 ρ=0.9796/h²=0.0013/method 标签 + 稀疏路径 EBV 3.49e-12 / h² 0.00 / CG 7 折 / Hutchinson mean-rel Δ0.054(n=20 最坏,文档标注近似)+ 默认稠密路径引擎级 0 差(落库 4.92e-05 为 numeric(12,4)/numeric(6,4) Postgres 量化,非回归)。
|
||
- **回归**:e2e_gwas(7 段)/e2e_advanced_gblup/e2e_gblup_cv/e2e_gxr/e2e_refine/e2e_corr_spatial 全绿;openapi 核验 4 新端点 + RunStatsIn.spatial/gxe/gxr + GwasRunIn/GwasQtlXEIn.method=emmax + MasPanelMarkerIn 三字段;HTTP smoke(data-quality trait 28、genetic-gain top_p=0.2 得 k=1.3998、409 门禁);vue-tsc EXIT=0。
|
||
|
||
## 十七、十二项真缺口补齐:引擎三件 + 模块四件 + 底座五件(2026-08-05)
|
||
|
||
> 用户「全部补齐」后做全量现状盘点(2 个 Explore 代理 + 关键文件精读),发现总表大量「待建」标记过时——35 个 module_bre 后端模块 CRUD 全部齐全、数据字典四类已灌、描述统计/ANOVA 引擎已落地。真实缺口收敛为 **12 件**,用户拍板范围=只补这 12 件;移动端(V1.2)/品种登记 PVP(V3.0)/AI 三件套(V4.0)留波次不建。分三批独立 e2e + 回归,每批验收。三批均 e2e 通过、全量回归零回归,后端重启 + openapi 核验(631 路径)+ vue-tsc EXIT=0。完整台账见规格 §8.24–8.26。
|
||
|
||
### 17.1 批1 引擎三件(solver 扩展,独立新路径)
|
||
|
||
- **ssGWAS**(`scripts/breeding_stats/gwas.py`,ENGINE_VERSION **1.2.0**):run_gwas `method="ssgwas"` 分支 → `_ssgwas`——`genomic.build_g_matrix`(blend 岭保正定)构 G → `genomic.solve_gblup` 全样本 GEBV û;**Wang et al. 单步 GWAS MEM 对角近似**:`ê_j=(M_j'Z'G⁻¹û)/(2Σp_j(1−p_j))`、`Var(ê_j)=σ²u/(2Σp_j(1−p_j))`,Wald `t=ê/SE`、df=n−2 → `fdist.f_pvalue`;共享 `_finalize`/`_bh_qvalues`/`_cluster`(GLM/EMMAX 逐字节不变);门禁无基因型样本报错、G⁻¹ 岭兜底;服务端 method 透传 + 前端 gwas 运行对话框下拉加 ssgwas。
|
||
- **全 MT-BLUP 多变量 REML**(`scripts/breeding_stats/mtblup.py`,ENGINE_VERSION **1.1.0**):`solve_multi`——m 性状 y 堆叠、X/Z 块对角、Var(u)=G0⊗A、Var(e)=diag(ve_i·I);**EM-REML 迭代**(单性状 REML 初始、G0 非对角 0 → 迭代更新 G0/ve、特征值截断 + Higham 投影保正定、max_iter 兜底不收敛→`converged=False`+warning);输出 G0 全元素 + r_g 矩阵 + n_iter/converged/warning;`run_genetic_corr` 加 `full_mtblup=True` 一次 m 性状给完整 G0(逐对 bivariate 路径保活)。
|
||
- **AR1×AR1 双参 ρ**(`scripts/breeding_stats/blup.py`,ENGINE_VERSION **1.4.0**):`solve_spatial(aniso=False)`——R_ij=ρ_row^|Δrow|·ρ_col^|Δcol|、内层 `_f_rho` 拆 ρ_row/ρ_col 交替坐标上升;`run_ablup(spatial=True, spatial_aniso=True)` → method=AR1×AR1(aniso)、note 落 rho_row/rho_col;**aniso=False 输出与 v1 逐字节一致**(回归断言);门禁/互斥/缺坐标逻辑不变。
|
||
|
||
### 17.2 批2 模块四件(标准 CRUD 五件套 + 前端 + 菜单翻转)
|
||
|
||
- **field_operation 农事操作 900051**:`bre_field_operation`(tree_id/plot_id/op_type/op_date/op_detail/operator_id);op_type 字典(施肥/喷药/修剪/灌溉/疏果/套袋/采收)bre_dict 灌入。
|
||
- **observation 通用观测 900050**:`bre_observation` EAV 通用录入(可挂 plot 级、不强制 trait);obs_type numeric/text/date。
|
||
- **breeding_report 育种报告 900075**:`bre_report` CRUD + `POST /report/generate`(按 report_type 聚合 bre_prediction/bre_stability_result/bre_cv_result 成结构化报告 + doc_path);前端列表 + 生成对话框。
|
||
- **analysis_dataset 分析数据集 900070**:新表 `bre_analysis_dataset`(trait_codes/sample_ids/config jsonb + status,create_all + 幂等 weld 兜底);CRUD +「查看性状值」跳 statistics trait-values 复用既有视图。
|
||
- **菜单翻转 + 文案清理**:幂等 UPDATE component_path→`module_bre/<name>/index`、E 段按钮 900xxx;900014/900015/900021/900061/900063/900065 菜单 description 残留「待建」→ UPDATE 去除。
|
||
|
||
### 17.3 批3 底座五件
|
||
|
||
- **审计切面**:`bre_audit_log`(16 列已建零实现)→ `module_bre/audit/`;`base_crud.py` 三写方法事务内 flush 后追加 **CREATE 记录级 / UPDATE 字段级 diff(每变更字段一行)/ DELETE 记录级**;`settings.AUDIT_BRE_ENABLED` + 模型 `__bre_audit__` opt-in;批量导入会话标志抑制逐行、仅汇总 IMPORT 一条;`GET /bre/audit/list|detail`。
|
||
- **统一编号服务**:`app/utils/number_gen.py` `NumberGenService`(前缀/日期/序列/回绕规则)+ **`pg_advisory_xact_lock` 原子取号** + `bre_sequence` 表;迁移 4 处(cross_combination YY+3位 / tree 组合-序号 / selection_result clone_code 扩位 / seedling batch_no YP-…),行为格式保持。
|
||
- **超期预警定时任务**:每日 job 按 `selection_rule` 扫描——树 N 年未决策(selection_result 无记录且定植超 N 年)/ pollen 批次过期(采集日+有效期)/ seed_lot 超期 → 写 `bre_alert`(alert_type/entity_type/entity_id/message/status/created_id)+ `GET /bre/alert/list` + 前端「预警中心」页。
|
||
- **备份容灾**:`backend/scripts/pg_backup.sh`(pg_dump 自定义格式到 `Temp/backup/` 按日期 + N 天轮转)+ `pg_restore.sh`;系统 job 每日 02:00(ap_scheduler 3 系统 job:operation 清理 Sun 03:00 / alert 扫描 08:37 / 备份 02:17)。
|
||
- **BrAPI + MIAPPE**:`module_bre/brapi/controller.py`(app 根注册 prefix `/brapi/v2`,只读不建表):germplasm/observationvariables/studies/observations/miappe 五端点,BrAPI 2.x `metadata{pagination,status,datafiles}+result{data}` 包裹、0 基分页;bre_germplasm → germplasmDbId/germplasmName/PUI/accessionNumber/commonCropName=Peach/genus=Prunus/species=persica/subtaxa;bre_trait → observationVariableDbId/trait/method/scale(scale.dataType 映射 + validValues);observations 合并 bre_trait_observation + bre_observation(tree→germplasm join)。
|
||
|
||
### 17.4 版本与验证
|
||
|
||
- `_DATA_VERSION` v2.14;ENGINE_VERSION:gwas 1.2.0(ssGWAS)/ mtblup 1.1.0(solve_multi)/ blup 1.4.0(aniso)/ genomic 1.2.0。
|
||
- **批1** `Temp/claude/e2e_gaps_engines_20260804.py` 3 组 PASS:ssgwas 复现已知 QTL(与 EMMAX 同数据集显著标记一致)+ solve_multi 3 性状 G0 半正定、r_g 与逐对 bivariate 同号量级 + aniso 双参 ρ 合理、aniso=False 与 v1 逐字节一致。
|
||
- **批2** `Temp/claude/e2e_gaps_modules_20260805.py` 15 组断言 PASS:四模块 CRUD + report generate 聚合 + 菜单翻转 + 文案清理。
|
||
- **批3** `Temp/claude/e2e_gaps_base_20260804.py` 19 ok / 0 fail:审计三操作(CREATE 记录级 / UPDATE 字段级 diff / DELETE 记录级)+ 导入抑制仅汇总 + 8-session 并发取号 seq 1-8 唯一 + 三类预警命中(树超期/花粉过期/种子超期)、无负例误报、幂等去重、resolve→不再重复 + 备份脚本执行成功 + pg_restore --list 含 bre_alert/bre_sequence/bre_audit_log/bre_analysis_dataset + BrAPI 分页数学/germplasm/variable/study/observation 映射。
|
||
- **回归**:e2e_spatial_sparse(3 段)/e2e_gwas(7 段)/e2e_molrigor(5 段)/e2e_advanced_gblup(4 段)/e2e_gblup_cv(3 段)/e2e_refine(8 段)/e2e_gxr(4 段)/e2e_corr_spatial(3 段)全复跑零回归;其间修复 1 处回归——`statistics.service._allelic_columns` 的 B2 SSR 兜底对 **SNP 标记**误把多等位调用(如 "1/2")当有效剂量 → 树 4 被误判基因型、破坏「非基因型株 GBLUP EBV=0」语义;修复:仅 `marker_type` 为空时走 SSR 每等位展开,SNP 标记 "1/2" 视为缺失(显式 SSR 分支不受影响,e2e_molrigor 全绿兜底)。
|
||
- **openapi**:重启后端后核验 **631 路径**(5 brapi + `/bre/breeding_report/report/generate` + `/bre/audit/list|detail|options` + `/bre/alert/list|detail|options|resolve` 全在);HTTP smoke(germplasm 37 / variables 71 / studies 3 / observations 107 / miappe 3 模板);前端 vue-tsc --noEmit EXIT=0。
|
||
|
||
## 十八、桃育种业务流全面完善:业务数据链 + 统计算法 + 前端体验(2026-08-05)
|
||
|
||
> 用户要求「对现有功能,结合桃育种实际业务流程与需求,进行全面测试分析,并完善」。三路审计(双代理并行 + 数据层性状字典探测 + 独立 grep/read 验证)收敛真实缺口 **10 项**(业务数据链 1-6 / 统计算法 7 / 前端 8-10),拍板全部实施 + 两裁决:**导入按钮维持隐藏**(23+ 页显式隐藏,导入弹窗/处理器/后端端点完整保留)、**采收入口走农事操作**(op_type=harvest 结构化产量表单 + 同步统计引擎,非独立模块)。批A 业务数据链(A1-A6)/ 批B 统计算法(B1-B4)/ 批C 前端(C1-C4),分三批独立 e2e + 全量回归零回归,后端重启 + openapi 核验 + vue-tsc EXIT=0。完整台账见规格 §8.27。
|
||
|
||
### 18.1 批A 业务数据链(A1-A6)
|
||
|
||
- **A1 果实采收结构化入口**(`field_operation/{model,service,schema}.py`):`bre_field_operation` 加 `yield_kg`/`fruit_count`/`avg_fruit_weight`/`marketable_rate` 4 可空列(`backend/sql/weld_busflow.sql` `ADD COLUMN IF NOT EXISTS` 幂等,create_all 不建已有表新列);service create/update 当 `op_type=="harvest"` 且 tree_id 非空且有产量数据 → 按 trait_code(single_tree_yield/fruit_number/avg_fruit_weight/marketable_rate)查 trait_id 同步写 `bre_trait_observation`(evaluate_year=op_date.year、trial_study_id 由 plot 继承),trait_code 缺失跳过不 409;**plot 级采收只留 field_operation,不进树级统计**。
|
||
- **A2 性状种子**(`backend/sql/bre_yield_phenology_traits.sql`,`ON CONFLICT(trait_code) DO UPDATE` 幂等):产量构成 5(单株产量/果数/均果重/好果率/裂果率 low)+ 物候 3 date 型(盛花期/果实成熟期/落叶期)+ 品质 3(可溶性固形物/可滴定酸 low/固酸比)+ 生长量 3(主干周长/树高/冠幅)+ 描述性 categorical 5(果形/茸毛/离核/果皮底色/着色类型,into_ebv=0)。
|
||
- **A3 种质级观测**:`bre_observation` 加可空 `germplasm_id`(FK→bre_germplasm,weld ALTER + index);observation service `assert_parents_exist` 扩展种质校验;前端表单种质选择器 + 搜索栏 germplasm 过滤。
|
||
- **A4 授粉→收种→种子处理补链**:`bre_seed_lot.pollination_id`(FK→bre_pollination)+ `bre_seed_treatment.seed_lot_id`(FK→bre_seed_lot,weld ALTER);前端 seed_lot 授粉选择器(按 combination 过滤)、seed_treatment 种子批次选择器。
|
||
- **A5 EAV 观测校验**(observation + trait_observation create/update):obs_type=numeric→parse float、obs_type=date→parse 日期,否则 409;trait 有 valid_min/valid_max 且 numeric → 越界 409;**重复校验** 同 (tree_id|plot_id|germplasm_id, trait_id, obs_year, obs_date) 已存在 → 409(精确到日,同日不同 trait / 不同日多次观测放行)。
|
||
- **A6 阶段自动设置 + 成株门禁**:tree.service create 当 stage 为空 → 按 breeding_generation 推断(F 代杂种→`juvenile`、亲本/嫁接成株→`evaluation`);trait_observation create 门禁 trait.stage=evaluation 而 tree.stage=juvenile → **409**「童期树不可录成株性状」;juvenile 性状录童期树仍允许;不影响 decision_preview 的 marker 辅助选入(非观测路径)。
|
||
|
||
### 18.2 批B 统计算法(B1-B4)
|
||
|
||
- **B1 type-B 多环境遗传力**(`statistics/service.py`):`_values_by_tree_env`(按 trait_id + trial_study_id/evaluate_year 分环境聚合树→值)+ `run_type_b_heredity` **复用 `mtblup.solve_bivariate` 把环境当"性状"**(phenos={"E1":{tree:v},"E2":{tree:v}} 同一系谱)精确 REML 估 r_g;`method="calo"` 备选(分环境 EBV 相关/√rel);`env_dim="site"|"year"`;共有树 <2 → 409;落 `bre_type_b_result`(`statistics/model.py` 新表,镜像 GENCORR)+ controller `POST /statistics/type-b-heredity` + `GET /type-b` + `GET /type-b/{id}`;前端 type-B tab。
|
||
- **B2 correlation genetic 模式**:`correlation_matrix` 加 `mode="pheno"|"genetic"`、`g_method`、`year`;**pheno 分支逐字节不动**;genetic 走新私有 `_genetic_corr_matrix` 逐对 `mtblup.solve_bivariate` 组装 G0(对角 1、非对角钳[-1,1]),**不落库**(对齐 data_quality 计算端点模式);schema CorrelationIn 加 mode/g_method/year。
|
||
- **B3 selection_index 自动权重**:`auto_weights: bool=False` → True 时权重=`_trait_meta_map`.default_h2(实测 h² 优先,兜底 0.1)、**强制 use_h2=False**(防双重相乘)、direction 由 `_weighted_z_index` asc 翻转处理;weights_json 记 `"__auto":true`;into_ebv=0 剔除进 dropped。
|
||
- **B4 UPGMA 聚类**:`run_cluster`(trait_ids/entity_type(tree|clone)/mode(pheno|genetic)/distance(1-|r| 或 euclidean 标准化)/k)输入矩阵复用 `_genetic_corr_matrix`/correlation_matrix;**UPGMA 纯 numpy**(距离矩阵迭代合并,无 scipy);输出 `{clusters, merges, order}`;controller `POST /statistics/cluster`(不落库);前端 cluster 树状图 tab。
|
||
|
||
### 18.3 批C 前端(C1-C4,按用户裁决:不恢复导入按钮)
|
||
|
||
- **C1 观测录入增强**:observation 页搜索栏加 plot/trial_study(站点)/germplasm 过滤(ObservationQueryParam 加 tree_id/plot_id/germplasm_id/trial_study_id)+ germplasm 表单(A3);field_operation 页 op_type=harvest 动态显示产量结构化表单 + 表格 4 列。
|
||
- **C2 统计可视化 ECharts**:`echarts.ts` 注册 HeatmapChart + VisualMapComponent;`statistics/index.vue` correlation 热图(mode 切换)+ gblup 可靠性热图/EBV 趋势折线(per-batch 聚合)+ type-B tab(热图+明细)+ cluster 树状图;图表生命周期(activeTab→resize、window resize、onBeforeUnmount dispose)。
|
||
- **C3 combination-funnel 前端入口**:statistics 工具栏「组合得失漏斗」按钮 + 1080px 对话框调 `GET /statistics/combination-funnel`(后端已有、前端此前缺失)。
|
||
- **C4 stage_phenotype 容器同步**:`_shared/StageView.vue` compMap 注册 Observation/FieldOperation,`stage_phenotype/index.vue` tabs 通用观测/农事操作翻真实页。
|
||
|
||
### 18.4 版本与验证
|
||
|
||
- `_DATA_VERSION` **v2.15**(service.py:94);**引擎版本不变**(mtblup/blup/gwas/genomic 本轮未改)。
|
||
- **批A** `Temp/claude/e2e_busflow_20260805.py` **11 组断言 PASS**(A1 采收同步 4 行观测/plot 级不写 + A2 性状种子齐全 + A3 种质观测回查 + A4 授粉→收种→处理全链路 + A5 非法/越界/重复 409 + A6 F1 自动 juvenile、童期录成株 409)。
|
||
- **批B** `Temp/claude/e2e_statsflow_20260805.py` **15 组断言 PASS**(type-B 矩阵对角 1/对称/r_g 范围/site·year 环境集不同/n_common 共有树/GET 回查 + correlation pheno 逐字节回归/genetic 对称对角 1/calo 回退 + index auto==手工 default_h2 权重/asc 翻转/into_ebv=0 剔除 + cluster 3 已知类还原/k 边界/clone 聚合)。
|
||
- **批C** HTTP smoke `Temp/claude/smoke_busflow_c_20260805.py` **10 检查全过**(observation 3 过滤对真实数据 n=1 全命中 + funnel n=21 + correlation pheno/genetic + type-b list + cluster POST + auto_weights);vue-tsc --noEmit EXIT=0。
|
||
- **回归**:**11 套件全复跑零回归**——e2e_spatial_sparse / e2e_gwas / e2e_molrigor / e2e_advanced_gblup / e2e_gblup_cv / e2e_refine / e2e_gxr / e2e_corr_spatial / e2e_gaps_engines / e2e_gaps_modules / e2e_gaps_base(其间同步 e2e_spatial_sparse 两处 `data_version` 断言 v2.14→v2.15,版本语义更新非回归)。
|
||
- **openapi**:后端重启核验 `/statistics/type-b-heredity`、`/type-b`、`/type-b/{id}`、`/statistics/cluster`、`correlation?mode/genetic`、`/selection-index auto_weights` 全在;observation list 四过滤(tree/plot/germplasm/trial_study)经真实 HTTP 命中。
|
||
|
||
### 18.5 世代闭环修复:单株晋级同步落系谱(2026-08-05 跟进)
|
||
|
||
> **用户报告闭环断裂**:`selection_result/service._promote_tree_to_clone` 晋升单株到品系(line/regional_trial/released)时仅 `BreedingGermplasmCRUD.create(cultivar_name=clone_code)` 建种质,**未同步写 `bre_pedigree`** → 新种质在统计引擎 `_build_pedigree`(statistics/service.py:299,按 `bre_pedigree.child_code`→`germplasm.cultivar_name` 匹配祖先)里查不到亲本,被当 **founder**,跨世代系谱链断裂:A-BLUP / 亲缘矩阵 / 选配近交规避跨代失效、遗传增益滚雪球效应归零。
|
||
|
||
**修复**(`selection_result/service.py`):晋级到 `_GERMPLASM_STAGES` 且树未关联种质时,建 `bre_germplasm` **携带 generation/stage**,并自动落一条 `bre_pedigree`:`child_code=clone_code(品种名)`、`dam_id/sire_id=tree.dam_id/sire_id`(为空回退组合 `female_parent_id/male_parent_id`)、`combination_id`、`generation=tree.generation`、remark「单株晋级自动落系谱(世代闭环)」;**child_code 幂等查重**(已存在不重复落)。附 `combo=None` 顶部初始化,消除"树已有 clone(ap/sp 晋级过)再晋级品系"路径的 `UnboundLocalError` 隐患。
|
||
|
||
**引擎级验证**(`Temp/claude/e2e_pedigree_closure_20260805.py`,11 组断言全过):① 晋升 line → 建种质携带 generation/stage + 自动落谱(dam/sire/combination/generation 齐);② `_build_pedigree` 对下一代树输出 `g{晋升种质}` 带 dam/sire(非 founder);③ **A 矩阵跨代恢复**——两棵仅经晋升种质共享祖先的下一代树,亲缘 `A[T2,T3]=0`(修复前,gT1 当 founder)→ `0.125`(修复后,血缘推导 `2·¼·f(gT1,gA)=2·¼·¼`);`A[gT1,gA]=0.5`(亲子)佐证链条接通;④ tree.dam/sire 为空 → 组合亲本回退落谱;⑤ child_code 预置行不重复;⑥ 已有 clone(sp 晋级过)再晋级品系 → else 分支回退组合亲本落谱(`combo=None` 初始化防 UnboundLocalError 的回归用例)。
|
||
|
||
**回归**:e2e_batch_selection(晋级主线,含新建谱行被 combo CASCADE 清理无残留)/ e2e_gaps_base(19 ok)/ e2e_spatial_sparse / e2e_advanced_gblup / e2e_gaps_modules(15 组)全过零回归。
|
||
|
||
### 18.6 近交惩罚「静默关闭」修复:亲缘矩阵多源解析 + 显式告警(2026-08-05 跟进)
|
||
|
||
> **用户报告最隐蔽的坑**:`mating_recommend` 的亲缘矩阵靠 `_germplasm_pedigree`(statistics/service.py)用 `bre_pedigree.child_code` 与种质 `cultivar_name/accession_no` **精确字符串匹配**来建。一旦名称不完全一致(大小写/空格/代号),pedigree 返回空 → `rmat={}` → 所有配对 `r=0` → `kin_pen=max(0,0−thr)=0` → **近交规避整体失效,且无任何告警**——用户以为系统在避近交,实际没避。用户提出三点修复方向:① 匹配失败显式告警;② 优先用种质实体自带 dam/sire 或 clone/tree 聚合,而非名称反查;③ 绝不静默 no-op。核实确认,并额外发现:候选既是 child 又是祖先时 `g{id}` 被重复追加 → `blup.relationship_matrix` 抛『系谱个体重复』→ 端点崩溃。
|
||
|
||
**修复**(`statistics/service.py`)——重写 `_germplasm_pedigree` 为**多源级联**(返回 `(pedigree, coverage)`,`coverage={total,resolved,resolved_ids,founder,matched_rows,orphan_rows,fk_sources}`):
|
||
|
||
1. **① 显式系谱(权威)**:`bre_pedigree.child_code` 规范化(strip+casefold)命中 `cultivar_name/accession_no` 索引——保留手录系谱语义,并直接修复大小写/空格错配;
|
||
2. **② FK 兜底**:`tree.germplasm_id == 该种质` 的树 → 其 `dam_id/sire_id` 全集去重后**唯一一致**才采纳(升种质=升谱树自带种质级亲本,消除名称反查对代号错配的脆弱性);多对歧义(trial 树挂冲突亲本)→ 视为无回退 founder,不武断选取;
|
||
3. **③ founder**。祖先以同级联 **BFS 展开 + 去重**(修复重复抛错崩溃 + 打通跨代系谱链)。
|
||
|
||
`mating_recommend` 新增显式告警:**`kinship_status=ok|partial|none`** + **`kinship_warning`**(none→「候选亲本均未解析到系谱…近交惩罚已禁用:所有配对 r 按 0 计」;partial→列未解析亲本名单;ok 但有孤儿行→「bre_pedigree 有 N 条 child_code 未匹配任何种质名称(孤儿记录),跨代亲缘可能低估」)+ 逐对 `flags` 加「亲缘未解析(r 按 0 计)」;返回体新增 `kinship`(resolved/founder/matched_rows/orphan_rows/fk_sources)。**设计红线**:FK 只做兜底、绝不覆盖显式系谱(A6 回归保真:trial 树 FK 挂 FM/MM 与显式系谱 dam=G0 冲突 → r(G0,G4)=0.5 保持)。
|
||
|
||
**验证**(`Temp/claude/e2e_mating_kinship_20260805.py`,**14 组断言全过**):① FK 兜底恢复(无 ped 行升种质树直连 → r(GX,GA)=0.5,修复前为 0);② 孤儿行告警(全解析 status=ok + orphan 警告);③ 规范化匹配(child_code 大小写变体仍命中显式系谱);④ 三代链不崩 + r(GX,GW)=0.5 / r(GA,GW)=0.25;⑤ 全 founder → status=none + 显式告警 + 逐对旗标;⑥ partial → 未解析亲本名单。**回归**:e2e_data_mating_gain(A6,r=0.5 保真)/ e2e_batch_selection / e2e_gaps_base 全过零回归。**HTTP 核验**:后端重启后 `/bre/statistics/mating-recommend` 真实数据 32/33 → `kinship_status=none` + `kinship_warning` 含「近交惩罚已禁用」+ `kinship={resolved:0,founder:2,orphan_rows:2}` + 逐对旗标(顺带暴露 2 条真实孤儿系谱行——数据质量信号)。
|
||
|
||
### 18.7 选配「亲本 EBV」回退逻辑方法学修复:direct 优先 + 子代测验降权 + 双侧去重(2026-08-05 跟进)
|
||
|
||
> **用户报告方法学错误**:`mating_recommend` 旧实现对无直接 EBV 行(ABLUP/GBLUP 按树写、`germplasm_id` 为空)的候选种质,用**「其子代树 EBV 均值」回退代表该亲本育种值**。三条质疑核实成立:① 这是 **progeny-test 值**(子代世代预测值 ≈½亲本BV+共亲本渗入+孟德尔抽样),不是亲本自身育种值;② 同一子代树若双亲都缺直接 EBV,被**等权计入 dam 与 sire 两侧**,稀释严重;③ 跨组合混合无区分。会误导选配排序。用户提出修复方向:**优先用亲本自身预测值;回退值必须显式标注「基于子代测验的近似」并降权参与打分**。
|
||
|
||
**修复**(`statistics/service.py` `mating_recommend`):
|
||
|
||
1. **direct 优先**:种质级 EBV 行(`germplasm_id` 直连)=亲本自身预测值,无条件最优先;有 direct 的候选**绝不被其子代树值污染**(回退仅对 `missing` 集生效,杜绝树级 99.0 泄漏进亲本)。
|
||
2. **回退显式标注 + 降权**:新增 `_EBV_SOURCE_FACTOR = {direct:1.0, progeny:0.5, missing:0.0}`;打分改 `mid=(f_a·ebv_a+f_b·ebv_b)/2`、`score=w_ebv·mid−w_kin·pen`——progeny 近似按**半权**参与,绝不冒充亲本自身值、不掩盖 direct;missing 按 0 计(与旧行为一致,全缺失时排序不变)。
|
||
3. **双侧等权稀释修复**:子代树双亲均在 `missing` 集(如 FM×MM 双亲均无 direct)→ **剔除**(该树均值无法归属,防止同值计入两侧);仅单侧可归属的树才计入对应亲本。
|
||
4. **跨组合辨别**:回退亲本记 `n_progeny`(子代数)/`n_combos`(跨组合数),供调用方判断子代测验近似的稳健性。
|
||
5. **显式可查,绝不静默降级**:返回体新增 **`candidate_ebv`**(每候选 `germplasm_id/name/value/source/n_progeny/n_combos`,missing 的 value=None)+ **`ebv_source.coverage`**(direct/progeny/missing 计数)+ 逐对 `flags` 加「亲本EBV为子代测验近似(降权0.5)」/「亲本无EBV(按0计)」。
|
||
|
||
**验证**(`Temp/claude/e2e_mating_ebv_20260805.py`,**5 组断言全过**):① candidate_ebv 来源可查——P0=direct/10.0(子代树值 99.0 未泄漏)、P1=progeny/8.0(n_progeny=3、n_combos=2)、P2/P3/P4=missing/None;② `ebv_source.coverage={direct:1,progeny:1,missing:3}`;③ 降权打分——P0×P1 `ebv_mid=7.0=(1.0·10+0.5·8)/2`(≠9.0 原始均值)+「子代测验近似」旗标、P0×P2 `ebv_mid=5.0`+「无EBV」旗标;④ 双侧去重——P3×P4 双亲均缺 → 子代树剔除 → source=missing、`ebv_mid=0.0`(旧代码会 progeny=7.0);⑤ score 降序、榜首 P0×P1(加权 EBV 互补最高)。**回归**:e2e_data_mating_gain(A6 无 Prediction 行 → 全 missing → 排序不变)/ e2e_mating_kinship(ok=14)/ e2e_batch_selection / e2e_gaps_base(19 ok)全过零回归。**HTTP 核验**:后端重启后 `/bre/statistics/mating-recommend` 真实数据返回 `candidate_ebv`(12 候选全 source=missing/value=None)+ `ebv_source.coverage={direct:0,progeny:0,missing:12}` + 逐对旗标。
|
||
|
||
### 18.8 数据质量「离群值」方向语义错位修复:同向=极值候选(精英)/ 反向=疑似录入错误(2026-08-05 跟进)
|
||
|
||
> **用户报告语义错位**:`data_quality_report`(§8.17①/§8.23① 的 A5 数据质量端点)旧实现用 IQR(Q1−1.5IQR/Q3+1.5IQR) 超界 + MAD 稳健 z-score(>3.5) 双通道把**任何偏离分布的值**都标为「离群株(疑似异常)」。但桃育种**按选育目标选极端表型**——果重/固酸比/可溶性固形物要高的、裂果率/病指要低的——**正向偏离恰恰是育种家要选的精英单株**(与高 EBV 高度相关),把精英候选标成「疑似录入错误」会诱导弃选、误导决策。用户提出修复方向:**仅当偏离方向与选育目标相反才提示疑似录入错误;同向偏离标为「极值候选(精英)」**。
|
||
|
||
**修复**(`statistics/service.py` `data_quality_report`):
|
||
|
||
1. **方向感知**:`trait_row = await self._numeric_trait(trait_id)` 后取 `direction = (trait_row.direction or "desc").lower()`;`desirable_high = direction != "asc"`(desc/None → 高值优;asc → 低值优)。判定标准与 v2.3 性状方向标注链路一致,低优性状(裂果率/病指)反向侧为高值。
|
||
2. **双通道分流**:IQR/MAD 命中的株再按偏离侧分类——`is_high = v > med`;`is_elite = is_high == desirable_high`:**同向偏离 → `extreme_candidates`**(`class="extreme_candidate"`,side=high/low,极值候选·精英);**反向偏离 → `outliers`**(`class="outlier"`,疑似录入错误)。两表**互斥**,精英绝不进错误表。
|
||
3. **返回体**:新增 `direction`、`extreme_candidates`(tree_id/value/z/side/class/reasons)、`summary.n_extreme_candidates`;`summary.has_warning/n_outliers/outlier_rate` 语义收紧为**疑似录入错误**计数(不再把精英株计入告警)。`is_high = v > med` 而非 >0,中位对称稳健。
|
||
4. **前端**(`statistics/index.vue` 数据质量 tab):选育方向指示条(高值优 desc / 低值优 asc)+ 双表——「极值候选(精英)」success 标签表 + 「疑似录入错误」danger 标签表;hint 说明同向=精英/反向=错误;无错误时绿色 info alert「未发现疑似录入错误」而非黄色警告。
|
||
|
||
**验证**(`Temp/claude/e2e_data_mating_gain_20260804.py` **[1] 17 株断言全过**):15 正常树 + 精英树(`{PREFIX}-HI`,值 16.0,G3)+ 错误树(`{PREFIX}-LO`,值 2.0,G3),direction=desc——精英树进 `extreme_candidates`(`class=extreme_candidate`/`side=high`)且**不在** outliers;错误树进 `outliers`(`class=outlier`/`side=low`);`n_trees=17`、`n_extreme_candidates=1`、`n_outliers=1`、`missing_rate=0`。**回归**:e2e_mating_kinship(ok=14)/ e2e_batch_selection / e2e_gaps_base(19 ok)全过零回归。**HTTP 核验**:后端重启后 `POST /bre/statistics/data-quality` 对 asc 裂果率(bB_DIR5668)与 desc 果重(dA_DIR5668)两真实性状返回 `direction`/`extreme_candidates`/`outliers`/`summary.n_extreme_candidates` 全部正确——真实数据无极端偏离 → 双表空(**无误报**)。
|
||
|
||
### 18.9 ΔG 投影假设声明 + 工程健壮性打磨:note 假设 + spatial 缺坐标降级 + numpy 收敛(2026-08-05 跟进)
|
||
|
||
> **用户报告两点,均非功能 bug**(核实确认后拍板落地):① `genetic_gain`(§8.23① A3 遗传增益端点)的 `next_pheno_mean = pheno_mean ± dg` 隐含「环境均值恒定」假设——若年际气候漂移,投影会偏;属投影演示性质,应**显式标注假设**。② 工程健壮性细节——spatial 模型要求所有观测树都有 row/col,否则整批 ValueError(门禁合理但无「剔除缺坐标者继续」的优雅降级);`data_quality_report`/`genetic_gain` 函数体内重复 `import numpy`;多处 numpy 计算未利用托管 venv 向量化优势。
|
||
|
||
**修复**(`statistics/service.py` + `statistics/index.vue`):
|
||
|
||
1. **① ΔG 投影假设显式声明**:`genetic_gain` 返回体新增 `note` 静态常量——`投影假设环境均值恒定(未计入年际气候漂移与栽培措施变化);ΔG=k·r_g·σ_A 仅含遗传增益分量,next_pheno_mean 为投影演示值而非实测预测。`(同性状/同数据重跑不变,探针断言稳定)。前端 gain tab 在描述区后、轮次表前展示 `el-alert type="info"` 提示假设边界。
|
||
2. **② spatial 缺坐标优雅降级**:`run_ablup(spatial=True)` 坐标收集循环把 `row_no/col_no` 为空的观测树记入 `missing_coord_ids`,**剔除其表型但保留系谱**——`blup.solve_spatial` 本就对所有个体(含无表型)输出 EBV,故缺坐标株 EBV 仍由系谱预测;剔除数显式写入批次 note「缺坐标剔除N株表型(EBV由系谱预测)」;**仅当全部观测树都缺坐标(coords 空)才整批 409**(提示先在单株录入填行号/列号)。`input_hash` 随剔除后的表型子集计算(同数据可复现)。**设计红线**:缺坐标仅剔除该株表型、绝不剔除系谱——系谱是空间 EBV 的预测基础。
|
||
3. **③ numpy 工程清理**:`data_quality_report`/`genetic_gain` 及另 5 处(genetic_corr/selection_index/bivariate/genetic/type-B/UPGMA)函数体内重复 `import numpy` 全部收敛为**模块级单次** `import numpy as np`(service.py:24);`data_quality_report` 逐株 flag 循环改 **numpy 布尔掩码向量化**——`z_robust_all = np.where(mad>1e-9, 0.6745·(a−med)/mad, 0)`、`iqr_flag_all = (a<q1−1.5iqr)|(a>q3+1.5iqr)`、`z_flag_all = |z_robust|>3.5`,`flagged_idx = np.nonzero(iqr|z)[0]` 一次性定位命中株,输出逐字节不变(精英/错误分流逻辑不变)。
|
||
|
||
**验证**(`Temp/claude/e2e_spatial_sparse_20260804.py` **降级场景断言全过**):5 株(前 4 株 2×2 网格带 row/col + 第 5 株 `row_no=None`)观测 [10.0,10.5,11.0,11.5,9.0] → `method=AR1×AR1`、`train_n=4`、note 含「缺坐标剔除1株」、**5 株全部有 EBV 行**(缺坐标株由系谱预测);全缺坐标场景仍整批 409 且报错含 row_no/col_no 数据需求。**A6 探针 [2]** 新增 note 断言:`note` 含「环境均值恒定」且两性状稳定一致。**回归**:e2e_spatial_sparse / e2e_data_mating_gain / e2e_mating_kinship(ok=14)/ e2e_batch_selection / e2e_gaps_base(19 ok)五套零回归。**vue-tsc** EXIT=0。**HTTP 核验**:后端重启后 `POST /bre/statistics/genetic-gain`(真实性状 dA_DIR5668)返回 `note`(含「环境均值恒定」);`POST /bre/statistics/data-quality` 返回 `direction: asc`、双表空无误报。
|
||
|
||
### 18.10 A–F 六项功能级缺口·批1 父本验证 + 近交衰退:一致性校验 + F→表型回归(2026-08-05 跟进)
|
||
|
||
> 用户全模块 grep 实证 A–F 六项**功能级缺口**(「有无/深度」问题,非正确性 bug),逐项复核确认 + 拍板「**全部六项分批落地**」。批1 = A 父本验证(pollination 花粉来源一致性 / tree 显式亲本警示 / cross_combination 自交门禁)+ C 近交衰退(`_DATA_VERSION` v2.22)。
|
||
|
||
**A 父本验证**(consistency,不落库):
|
||
|
||
1. **A1 pollination 花粉来源父本一致性**(`pollination/service.py` 新增 `_validate_pollen_parent`):批次 `pollen_lot.male_tree_id` 声明采集父本树时,授粉声明 `male_tree_id` 须一致,否则 409「花粉批次 {lot_code} 采集自父本树 {X},与授粉声明父本树 {Y} 不一致,请确认花粉来源」;**批次无采集父本(混合/外地采集)或授粉未声明父本 → 放行**。create/update 统一在 `_validate_pollen_window` 后调用(update 取 `existing` 回退)。
|
||
2. **A2 tree 显式亲本 vs 组合父母本警示**(`tree/service.py` `_resolve_parents` 改返回 `(dam, sire, warning)`):显式 dam/sire 与组合 female/male_parent 不一致时聚合「显式母本与组合母本不一致;显式父本与组合父本不一致(以显式为准)」;**warning 不阻断**(tree 可独立建,武断 409 会误伤);`tree/schema.py` 加只读 `warning` 字段(仅返回体,不落库)。
|
||
3. **A3 cross_combination 同质自交门禁**(`cross_combination/service.py` `_check_parent_roles` 角色解析后追加):`female_parent_id == male_parent_id` → 409「母本与父本同为「{名}」,自交组合请确认」;create/update 生效亲本统一触发(与既有 S-等位 409 语义一致不冲突)。
|
||
|
||
**C 近交衰退分析**(`statistics/` 三件套 + 前端,计算端点不建表):
|
||
|
||
- **`POST /statistics/inbreeding-depression`**(`InbreedingDepressionIn`:trait_id/trait_code + year/trial_study_id 可选 + min_n=10)——`inbreeding_depression`:tree 系谱(`t{tree_id}` 个体 + `g{germplasm_id}` founder)→ `blup.relationship_matrix` 取 F=A_ii−1;**关键洞见:`inbreeding` dict 仅含 F>0,非近交树须从 `individuals` 默认 F=0 兜底**,否则非近交株被排除出回归;trait 树级表型 `select(obs.tree_id, func.avg(value_numeric)).group_by(tree_id)` 聚合(按 year/trial_study_id 可选过滤)→ 交集树 → 纯 numpy `np.linalg.lstsq` 线性回归 phenotype ~ F。返回 `{sufficient, reason, n_obs, mean_F, max_F, direction, regression:{intercept, slope, r2, t_slope, depression_rate, has_depression, interpretation}, high_inbreeding:[{tree_id, tree_no, F, value}]}`;`has_depression = slope<0 且 t_slope≤−1.645`(单侧 95% 大样本近似);`high_inbreeding` 按 F 降序取前 10;**n<min_n 优雅降级** `sufficient=False` + reason(不 409)。
|
||
- **前端**「亲缘/近交」tab 加「近交衰退(F → 表型)」区:trait select + year input + 运行;`el-alert`(insufficient=warning / has_depression=error / 无衰退=success)+ `el-descriptions` + `high_inbreeding` 表。**修 vue-tsc TS2322:`el-alert :type` 无 danger 合法值,改 `'error'`**。
|
||
|
||
**验证**:`Temp/claude/e2e_parent_validation_20260805.py` **10 断言全过**——A1 不一致 409(含「不一致」)/一致放行/混合批次放行/update 同门禁;A2 双侧警示(含「以显式为准」、dam/sire=显式)/单侧仅父本/一致无警示/update 警示;A3 create/update 同质 409(含「自交」)。`Temp/claude/e2e_inbreeding_depression_20260805.py` **4 断言全过**——12 树(6×F=0 + 6×F=0.5 自交)衰退性状 y=100−60F+ε → slope≈−60/t 显著负/r²>0.9/has_depression=true/depression_rate<0/max_F≈0.5/mean_F≈0.25/high_inbreeding 前 6 全为 S-自交 F=0.5、后 4 F=0;无衰退 y≈100 → slope≈0/「未检出」;min_n=20 → insufficient 含「12 棵」「≥20」;trait_id=99999999 → 409。**回归**:e2e_spatial_sparse(v2.22 断言同步)/ e2e_statsflow / e2e_data_mating_gain / e2e_mating_kinship / e2e_batch_selection / e2e_gaps_base 六套零回归。**vue-tsc** EXIT=0。**HTTP 核验**:后端重启后 `POST /bre/statistics/inbreeding-depression`(真实稀疏数据)返回 code=0、sufficient=false、n_obs=2、reason「同时具备系谱近交系数 F 与表型的树仅 2 棵(需 ≥10)」、mean_F/max_F/regression=null、high_inbreeding=[]。
|
||
|
||
### 18.11 A–F 六项功能级缺口·批2 GS 家系 CV + 试验设计深度:家系阻塞折 + RCBD 生成/区组 ANOVA(2026-08-05 跟进)
|
||
|
||
> A–F 六项缺口批2 = **B GS 家系 CV**(深度:随机分层 → 家系阻塞折)+ **F 试验设计深度**(RCBD 生成 + 设计基 ANOVA)。批1 已落地 §18.10(v2.22);本批 `_DATA_VERSION` v2.23。
|
||
|
||
**B GS 家系 CV**(`genomic.py` + `statistics/service.py` + 前端):
|
||
|
||
1. **引擎** `genomic.kfold_cv_genomic` 加 `split: str = "random"` + `family_of: dict[str, str] | None = None`:`split="random"` → 现有 round-robin `bin_of = {c: i % k}` **逐字节不变**(回归零变化);`split="family"` → 照 `blup.kfold_cv` 的 sire 家系留出模式——`fam_of = {ind: (family_of or {}).get(ind, ("self", ind))}`(无家系个体自成一族)→ `fams` 去重 → `rng.shuffle(fams)` → `fam_bin = {f: i % k}` → `bin_of = {c: fam_bin[fam_of[c]]}`,**同家系个体同折**(防亲缘泄漏高估准确度);**家系数 < 折数 k → 折叠为 n_families 折 + warning**「家系数 {n} < 请求折数,折叠为 {k} 折(family-blocked)」;**单家系(n_families<2)→ folds=[] + warning**「可验证个体仅构成 1 个家系,无法家系阻塞交叉验证(请改用随机分层)」。输出加 `n_families`(逐键对齐 blup.kfold_cv)。
|
||
2. **服务** `run_cv` 加 `split="random"|"family"` 透传(controller/schema,job params_json 记 split):GS 分支 `split=="family"` 时用既有 `ped_rows`(select 顺序 id/dam_id/**sire_id**/trial_study_id/rootstock_id/female_parent_id/**male_parent_id**/combination_id/clone_id/germplasm_id)构建 `family_of = {f"t{tid}": f"s{s}"}`(`s = sire if sire is not None else cm`,sire 缺失回退组合 male_parent);落库 `CvResultModel.note` 记 `split=family · n_families={N}`(+ 引擎 warning 拼接)。
|
||
3. **前端**「交叉验证」tab runCv 参数区加 split 下拉(random=随机分层/family=家系阻塞)+ 结果表 n_families 列。
|
||
|
||
**F 试验设计深度**(`trial_study_entry/model.py` + `weld_trial_study_entry.sql` + `statistics/` 三件 + `anova.py` + 前端):
|
||
|
||
1. **F1 RCBD 生成器**:`bre_trial_study_entry` 加可空 `block_no integer`(model 列 `block_no: Mapped[int | None]` + `sql/weld_trial_study_entry.sql` `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`,create_all 只建新表故 weld 幂等兜底);新端点 `POST /statistics/trial-design`(`TrialDesignIn`:trial_study_id + design_type="rcbd" + seed 可选)——`trial_design`:`db.get(TrialStudyModel)` 409、design_type≠rcbd 409、block_count=study.block_count or 1、按 entry_number 取参试条目(空 409「无参试条目」)→ `random.Random(seed)` 洗牌 + round-robin 分进区组(均分 + 组内随机 = 田间布局)→ `update(...).values(block_no=case(block_of, value=TrialStudyEntryModel.id, else_=None))` 批量落库 + flush;返回 `{trial_study_id, design_type, block_count, seed, n_entries, blocks:{str(b): [entry_number…]}}`。
|
||
2. **F2 设计基 ANOVA**:`anova.solve_rcbd(rows)`(rows=`{"group","block","value"}`)RCBD 双因素 **Type I 顺序**(X1→Xg→Xgb dummy 矩阵:SS_group=rss(X1)−rss(Xg)、SS_block=rss(Xg)−rss(Xgb)、SS_error=rss(Xgb),纯 numpy + `fdist.f_pvalue`),输出含 f_block/p_block/groups/blocks/warning(<2 组合或 <2 区组 ValueError;df_error≤0 → warning「区组设计过饱和」);`anova.solve` 单因素**逐字节不变**。`run_anova` 加 `block: bool=False`:block=False → 原单因素路径不变;block=True → 查 `bre_tree.block_no` 组 rows、过滤空 block、<2 区组 → 409「区组数据不足:需 ≥2 个区组(请先运行 /statistics/trial-design 生成设计并落库 block_no)」,method=ANOVA/H2/RCBD。
|
||
3. **前端** statistics ANOVA tab 重构:顶部「生成 RCBD 设计」工具条(trial_study select + seed input + warning button)+ 设计区组表 + trait select + year + `el-checkbox anovaBlock`「RCBD 区组校正」+ 提交;结果加 n_blocks/f_block/p_block 条件 v-if + 区组均值表。`statistics.ts` 加 `trialDesign()` + `TrialDesignResult`。
|
||
|
||
**验证**:
|
||
|
||
- `Temp/claude/e2e_trial_design_20260805.py` **5 组断言全过**——[1] RCBD 生成(block_count=3/n_entries=9/3 区组×3 均分/9 条目齐全/seed·design_type 回显);[2] block_no 落库核验(紧随首次生成避免复现覆盖;落库区组集合==返回设计集合);[1b] seed=42 复现同一设计 / seed=43 异动;[3] block=False → method=ANOVA/H2、无 f_block/n_blocks/blocks 键(单因素逐字节不变);[4] block=True → method=ANOVA/H2/RCBD、n_blocks=3、ss_block>0、f_block>1、p_block 存在、区组均值随 +3/0/−3 递减;[5] 空研究点 409「无参试条目」。
|
||
- `Temp/claude/e2e_gs_family_cv_20260805.py` **5 组断言全过**——[1] 5 家系×3 全同胞 k=3 → method=KFCV/GBLUP、note「split=family · n_families=5」、家系阻塞折 n_test=[3,6,6];[2] k=5 → 每折恰 1 家系 n_test 全 3;[3] random k=3 → note 无 split=family、n_test=[5,5,5](随机分层回归零变化);[4] 引擎级 6 家系<请求 8 → 折叠 6 折 + warning;[5] 单家系 → folds=[] + warning。注:探针树创建曾漏 `db.add_all([fm, mm])` 致 germplasm.id=None → 组合父母本全空 → sire 全空 → n_families=15,补 add 后修正为 5(服务侧代码位置核实无误)。
|
||
- **回归**:e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_busflow / e2e_mating_kinship / e2e_gaps_base / e2e_molrigor 七套零回归。**vue-tsc** EXIT=0。**HTTP 核验**:后端重启后 `POST /bre/statistics/trial-design` + `POST /bre/statistics/anova/run`(block=true)经真实端点返回。
|
||
|
||
### 18.12 A–F 六项功能级缺口·批3 OCS 最优贡献选择 + MABC 标记辅助回交:投影梯度求解器 + 前景/背景选择工作流(2026-08-05 跟进)
|
||
|
||
> A–F 六项缺口批3(收官)= **D OCS 最优贡献选择** + **E MABC 标记辅助回交**。批1 §18.10(v2.22)、批2 §18.11(v2.23);本批 `_DATA_VERSION` **v2.24**。两端点**纯计算不落库**(对齐 data_quality 惯例);前端同批交付(选配推荐 tab OCS 运行区 + 独立回交 MABC tab,vue-tsc EXIT=0)。
|
||
|
||
**共享 helper 抽取 `_candidate_ebv_map`**(`statistics/service.py:3429-3531`):
|
||
|
||
1. `mating_recommend` 内联 EBV 解析块**原样抽取**为 `_candidate_ebv_map(prediction, tree_ids)` → `{germplasm_id → ebv}`:prediction batch ABLUP/GXEBLUP/GXRBLUP/GBLUP/ssGBLUP 全支持;direct germplasm_id 先取,缺失走 progeny 子代均值并 `_EBV_SOURCE_FACTOR={direct:1.0, progeny:0.5, missing:0.0}` 降权;返回 `ebv_map/source/status/warning/cover/n_progeny/n_combos/ebv_mid`。
|
||
2. **「双亲均缺直接 EBV → 子代树剔除(双侧去重)」规则随抽取原样保留**——经 transcript 抽取前内联块 old_string 实证该规则已存在于抽取前代码(v2.19 方法论),非抽取回归;`e2e_mating_ebv` [4] P3×P4=0.0 权威验证、`e2e_audit_fix_20260804` ④ 已同步语义。
|
||
3. **OCS 端点复用** `_candidate_ebv_map`(candidate germplasm 直接取)+ `mating_recommend` 保留原内联调用(行为不变)——**mating 回归 14/14 零变化**证明抽取无副作用。
|
||
|
||
**D OCS 最优贡献选择**(`POST /statistics/ocs`):
|
||
|
||
1. **`_proj_simplex`**:欧氏投影到单纯形(numpy sort/arange 解析投影,无 scipy),`_solve_ocs` **投影梯度 + 回溯线搜索**:max Σc_i·ebv_i − λ·c'Ac,s.t. Σc=n_select、c≥0;A 由 `_germplasm_pedigree` + `blup.relationship_matrix` rmat 组装(对角=1、非对角候选对 r,覆盖<100% → kinship_status="partial" + warning)。
|
||
2. **输出**:`contributions`(c 降序 + ebv/source/可选 n_progeny/n_combos)、`mean_ebv`、`avg_kinship`(c'Ac)、`kinship_quad`、`vs_top_n`(同 n 贪心 top-n 对照:mean_ebv 相当 + kinship_reduction,量化 OCS 亲缘控制价值)、`ebv_source/kinship_status/kinship_warning`。
|
||
3. **门禁**:空候选 / n_select>候选数 / λ<0 → 409。
|
||
|
||
**E MABC 标记辅助回交**(`POST /statistics/mabc-progress`):
|
||
|
||
1. **前景选择**:复用 `_mas_hit_map`/`_mas_marker_hit`(additive/dominance/recessive/allele/haplotype 五语义),`foreground_pass` = 命中 ≥ `foreground_min_hits`(stage 无关、童期幼苗即可)。
|
||
2. **背景基因组恢复率**:background 面板逐标记候选 vs 轮回亲本「纯合剂量一致」比例(`_pure_homologous`:候选纯合且等位∈轮回亲本等位集;杂合不计),标记均值 = 恢复率 %(round 2)。
|
||
3. **回交代建议**:`_BC_LADDER=["F1","BC1","BC2","BC3","BC4","BC5"]` + `_MABC_GENERATIONS={"F1","BC1","BC2","BC3"}`;晋级 / 再回交 / 补测后判定 / 前景未通过 四分支 reason;`recommended` 前景通过按恢复率降序(None 排尾)。
|
||
4. **门禁**:空候选 / 空前景或背景面板 / generation∉`_MABC_GENERATIONS` / background_target∉(0,100] / 轮回亲本不存在 → 409。
|
||
|
||
**验证**:
|
||
|
||
- `Temp/claude/e2e_ocs_20260805.py` **17 断言全过**——[1] Σc=3、c≥0、coverage=direct 5/5、c 降序、最高=A;[2] mean_ebv 与 vs_top_n 相当 + kinship_reduction=0.0398 + kinship_quad≈4.641;[3] λ↑(0→0.5→1→10)→ avg_kinship 单调非增(1.0→0.5157→0.3211→0.2685);[4] λ=0 退化=贪心 top-n(满额投最高 EBV 单亲);[5] A 缺失 → kinship_status=partial + warning;[6] 三 409。清理干净。
|
||
- `Temp/claude/e2e_mabc_20260805.py` **23 断言全过**——[1] 前景 5 pass/1 fail;[2] 恢复复算 100/75/75/0;[3] reason 晋级 BC2/再回交/前景未通过;[4] recommended 恢复率降序 [100,100,100,75,0];[5] 童期 C6 前景通过+晋级;[6] 轮回亲本缺背景基因型 → None + warning;[7] 六 409。清理干净。
|
||
- **回归**:e2e_molrigor / e2e_gwas / e2e_mating_kinship(14/14)/ e2e_mating_ebv / e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_busflow / e2e_gaps_base / e2e_b8_seed_lot / e2e_prediction_rigor / e2e_audit_fix 全套零回归(`_candidate_ebv_map` 抽取 + mating 语义双核对)。**vue-tsc** EXIT=0。**HTTP 核验**:后端重启后 `POST /bre/statistics/ocs`(最小正例)+ `POST /bre/statistics/mabc-progress`(成功 + 空面板 409 + 非法 generation 409)经真实端点返回。环境性 b34(G1 门禁)为探针脆弱非本批回归。
|
||
|
||
### 18.13 近交衰退两处正确性修复:方向感知检测 + 深层系谱近交系数(2026-08-05 跟进)
|
||
|
||
> 用户实证复查 `inbreeding_depression`(v2.22,§18.10)两处缺陷,本会话核实成立后修复:① **方向盲目判据**——无条件 `slope<0 且 t≤−1.645` 判衰退,对「越低越好」的 asc 性状(如病指)F↑→指标↑=恶化却误报「未检出」;② **浅层近交系数**——系谱只取树级 dam/sire 把每个引用种质当 founder,未走深层系谱,多世代项目(半同胞共享祖亲)低估 F(OCS/mating 已用 `_germplasm_pedigree` 深层解析,故仅近交衰退受影响)。版本仍 v2.24(正确性修复不升版,避免批3 版本断言连锁)。
|
||
|
||
**① 方向感知检测**(`statistics/service.py` `inbreeding_depression`):
|
||
|
||
1. 读 `direction`(此前读取未用)得 `desirable_high = direction != "asc"`;
|
||
2. 高优性状(desc/None)衰退 = `slope<0 且 t≤−1.645`;低优性状(asc)衰退 = `slope>0 且 t≥+1.645`;
|
||
3. `interpretation` 方向化——asc 衰退「F 每升 0.1,{trait} 表型平均**上升(恶化)** …%」/ 未达显著「斜率**偏正**…」/ 未检出「F 对表型无**上升(恶化)**影响」。对齐 `data_quality_report` 既有 `desirable_high` 方向语义。
|
||
|
||
**② 深层系谱近交系数**:
|
||
|
||
1. 系谱构建改复用 `_germplasm_pedigree`(bre_pedigree 名称反查 + tree FK 兜底 + BFS 祖先展开,与 OCS/mating 同源)展开全部被引用种质祖先 + 树节点 + 未解析种质 founder 兜底(软删引用不悬空);`_germplasm_pedigree` 本体零改动。
|
||
2. 多世代半同胞共享祖亲 → F 正确 >0(旧浅层把 G7/G8 当 founder → F=0 低估)。
|
||
|
||
**验证**:
|
||
|
||
- `Temp/claude/e2e_inbreeding_depression_20260805.py` **6 组断言全过**——原 [1] 衰退 / [2] 无衰退 / [3] 样本不足保持,新增 [4] **asc 病指**(12 树同 F 结构 y=10+40F → slope=+40、t 显著正、has_depression=true、文案含「上升(恶化)」、高近交前 6 仍 F=0.5 自交株;旧判据误报未检出)+ [5] **深层系谱 F**(P→G7/G8 tree FK 升谱、6 候选树 dam=G7 sire=G8 半同胞近交 + 6 对照 F=0,y=100−60F → max_F=0.125/mean_F=0.0625、slope≈−61、has_depression=true、高近交前 6 全为 H 半同胞株;旧浅层 F=0)+ [x] trait 不存在 409 保持。**清理干净**(26 树 48 观测 + 4 性状全删)。
|
||
- **回归**:e2e_ocs / e2e_mabc / e2e_mating_ebv / e2e_mating_kinship / e2e_statsflow / e2e_spatial_sparse / e2e_gs_family_cv / e2e_trial_design / e2e_parent_validation / e2e_batch_selection / e2e_gaps_base / e2e_gaps_engines / e2e_gaps_modules 全套零回归。**vue-tsc** EXIT=0(前端仅提示文案方向化一行)。HTTP 核验沿用批3(后端未重启)。
|
||
|
||
### 18.14 分子亲本验证(孟德尔一致性)+ 试验设计深度(增广 + α-格子)(2026-08-05,v2.25)
|
||
|
||
> 用户实证复查指出两处遗留缺口,本会话核实**全部成立**:① `genotype_call` 对 mendelian/parentage 零命中(仅有 `fingerprint_check` 无性系混杂/标签互换检测);② `trial_design` 仅 RCBD。α-格子范围用户拍板:**平方格子(v=k²,闭式构造,平衡可证)+ 一般 v 贪心回退(balance_warning 诚实标注)**。`_DATA_VERSION` v2.25,同步 3 处探针版本断言(e2e_prediction_rigor / e2e_spatial_sparse / e2e_statsflow)。
|
||
|
||
**批4-A 孟德尔/亲本一致性检验**(`genotype_call/service.py` `mendelian_check(dataset_id, compat_threshold=0.98)` + `controller.py` `GET /bre/genotype_call/mendelian/check`,镜像 fingerprint/check 模式,纯计算不落库):
|
||
|
||
1. **数据解析(跨数据集)**:子代样本 = `GenotypeSampleModel.source_type=="tree"` 且 source_id∈dataset → tree 集合;声明亲本 = `tree.dam_id/sire_id`→germplasm(两亲皆空 → `no_declared_parents` + reason「未声明亲本」);亲本基因型 = `source_type=="germplasm"` 样本**跨数据集解析**(同数据集优先,否则其他数据集最低 id 兜底)——探针验证子代样本 D1、亲本样本 D2 跨数据集解析成功;亲本声明但无 germplasm 基因型 → `missing_parent_genotype`(**不 409**,reason 标注「母本/父本」缺哪个)。
|
||
2. **孟德尔规则**:逐标记 `_allele_set`("/" 分割去空白/缺失)得子代/母本/父本等位集;子代等位集 ⊆ dam∪sire 并集即兼容(union 规则);任亲本空白/缺失 → 非信息位点不计分母。单株兼容率 = 兼容/信息位点,`flag = rate < compat_threshold`(0.98 对齐 fingerprint)。
|
||
3. **输出**:`{dataset_id, compat_threshold, trees_checked, trees_flagged, trees_no_parents, trees_missing_parent_genotype, summary{informative_markers/incompatible_markers}, trees:[{tree_id, tree_no, dam, sire, status, informative_markers, compatible, incompatible, compatibility_rate, flag, incompatible_markers:[{marker_id, allele, dam, sire}], reason?}]}`;数据集无样本 → 零值返回 summary=None(不 409)。
|
||
|
||
**批4-B 试验设计深度**(`statistics/service.py` `trial_design` 分派 rcbd/augmented/alpha;**rcbd 路径逐字节不变**;`schema.py` `TrialDesignIn` 加 `check_germplasm_ids: list[int]=[]` / `block_size: int|None` / `reps: int|None`,extra="ignore"):
|
||
|
||
1. **augmented(增广)**:对照 `check_germplasm_ids` 须为参试条目种质 id 子集(否则 409「对照种质不在参试条目中」)、至少 1 对照 + 1 新品系(否则 409「增广设计需至少 1 个对照种质」);对照每区组重复(anchors,`check_reps=block_count`)、新品系 `rng.shuffle` + round-robin 均分区组(不重复);对照条目 `block_no` **不落库**(None)、新品系落 1..block_count。输出加 `checks:[{entry_number,germplasm_id}]`/`n_new_entries`/`n_checks`/`check_reps`。
|
||
2. **alpha(α-格子)**:`block_size=k`(v%k==0 否则 409「α-格子条目数 {v} 须能被 block_size {k} 整除」;k 缺省 v 完全平方自动 k=√v,否则 409「α-格子需指定 block_size(当前 {v} 条目非完全平方)」);`reps=r`(缺省平方 k+1/一般 s;r<2 → 409「α-格子重复数需 ≥2」;平方 r>k+1 → 409「完全平方格子(v={v}=k²)重复数最多 {r_full}」)。**平方 v=k² → 闭式格子**:`rng.shuffle` 打标 (x,y),rep m∈{0..k} 直线 y≡m·x+(b−1) mod k(m=k=竖列),完全格子 r=k+1 任一对至多同块一次 λ≤1;k 素数(`_is_prime`)完全平衡 balance_warning=False,非素数 → balance_warning=True(保守告警,可分解不保证平衡)。**非平方 v → 贪心可分解构造**:逐 rep 贪心填 s 块×k,`used_pairs` 集避免同块对重复,卡死则余下允许复用 + balance_warning=True;rng(seed) 确定性。**block_no 复合编码 rep\*100+block**(rep 1..r、block 1..k)落库。
|
||
3. **探针抓出的真 bug**:平方分支初版 block_no 编码 `m*100+b`(0-based m)致 rep1 落库 `b`(1..3)与贪心分支/文档的 `rep*100+block` 不一致 → 修正 `(m+1)*100+b`(401/402…)。探针 [2] 落库断言由 301/302 → 401/402 验证。
|
||
|
||
**验证**:
|
||
|
||
- `Temp/claude/e2e_mendelian_check_20260805.py` **8 断言全过**——跨数据集解析(子代 D1/亲本 D2):T1 全 0/1 唯 M5=2/2(亲本均无该等位)→ informative=5/compatible=4/incompatible=1/rate=0.8/flag + incompatible_markers[0]={M5,2/2,dam=0/0,sire=1/1};T2 全兼容 rate=1.0/flag=false;T3 双亲空 → no_declared_parents + reason;T4 dam=G3 无基因型 → missing_parent_genotype + reason「母本」不 409;summary informative=10/incompatible=1;D3 空数据集零值 summary=None 不 409。清理干净(call→sample→marker→dataset→tree→germ→combo→target 全删)。
|
||
- `Temp/claude/e2e_trial_design_ext_20260805.py` **19 断言全过**——[1] augmented 12 条目 3 对照×3 区组:n_new=9/n_checks=3/check_reps=3、新品系 block_no∈{1,2,3} 不重复、对照 block_no=None、checks 结构;[2] v=9=k² k=3 素数 r=4 完全格子:4 rep×3 块×3 条、每 rep 覆盖 9、任一对至多同块一次(maxλ≤1 恰 36 对)、balance_warning=False、block_no 复合编码落库;[3] 部分 r=3 仍平衡;[4] v=16 k=4 非素数 r=5 + balance_warning=True;[5] v=12 一般贪心 s=4/r 缺省=s + block_no 落库;[6] 四 409(对照非条目子集/增广无对照/v 不被 k 整除/非平方缺 block_size)。清理干净(entry→study→trial→germ→combo→target 全删)。
|
||
- **回归**:rcbd 由 `e2e_trial_design_20260805.py` 回归零变化兜底;全量套件 e2e_molrigor / e2e_gwas / e2e_mating_kinship / e2e_mating_ebv / e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_gs_family_cv / e2e_batch_selection / e2e_ocs / e2e_mabc / e2e_gaps_base / e2e_gaps_engines / e2e_gaps_modules / e2e_prediction_rigor / e2e_inbreeding_depression / e2e_parent_validation 全套零回归。**vue-tsc** EXIT=0。**HTTP 核验**:后端重启(PID 更换)后 `GET /bre/genotype_call/mendelian/check?dataset_id=999999` → 200 零值结构;`POST /bre/statistics/trial-design` augmented/alpha → 409「该研究点无参试条目」(分派+参数链路通)、design_type=latin → 409「暂不支持设计类型 latin(可用: rcbd=随机完全区组、augmented=增广、alpha=α-格子)」。
|
||
- **方法学保留**:mendelian_check 与 `fingerprint_check` 互补(样本一致性 vs 子代-亲本孟德尔规则);augmented 对照 anchoring + alpha 平衡性显式告警与 RCBD 随机化并存;亲本基因型缺失/双亲空归状态不 409(数据现状透明化)。
|
||
|
||
### 18.15 批5 区组随机效应 ABLUP(N3)+ 孟德尔检验落库/隔离/进报告(N1)+ 统计引擎全量数值校验(N2)(2026-08-05,v2.26)
|
||
|
||
> 用户实证复查提出三项,本会话逐项核实**全部成立**,用户拍板范围:① **N3**(中-高,真实断点)——`trial_design` 已给增广/α-格子落库 `block_no` 不完全区组结构,但 `run_ablup` 只把 block_no 当空间竞争协变量网格 key,未作随机效应([service.py:651](backend/app/api/v1/module_bre/statistics/service.py#L651))→ 用户选「**显式 block 开关**」;② **N1**(中)——`mendelian_check` 只读不落库、不进数据质量报告、不自动隔离可疑树,错配亲本仍污染系谱 → 用户选「**断开错误亲本链**」;③ **N2**(中)——run_gblup/ssGBLUP、genetic_corr、type_b、run_cluster、stability 等大体量新模块只有结构性断言,缺逐文件数值真值校验 → 用户选「**全量统计引擎**」。`_DATA_VERSION` v2.25→**v2.26**(同步 3 处探针版本断言:e2e_prediction_rigor / e2e_spatial_sparse×2 / e2e_statsflow);`blup.ENGINE_VERSION` 1.4.0→**1.5.0**。
|
||
|
||
**批5-A(N3):ABLUP 区组随机效应**:
|
||
|
||
1. **引擎** `blup.py`:`solve` 加 `block: dict|None` 分派 `_solve_block(pedigree, phenotypes, *, fixed, covariate, block_of, record_map, tol)`(镜像 `_solve_gxe`,[blup.py:1006-1205](backend/scripts/breeding_stats/blup.py#L1006-L1205))——Z₂ 按 `block_of: {记录id: 区组水平}` 分组(G×E 的 (g,e) 复合键退化为单区块水平),剖面 REML 坐标上升估 (σ²a/σ²e, σ²block/σ²e)、MME、PEV 可靠性;输出键 `sigma_block/block_ratio/block_effects/n_blocks`、factor_label=「区组」;区组方差收敛到 0 / 无系谱 / 未收敛三警告。`ENGINE_VERSION` → 1.5.0。
|
||
2. **服务** `run_ablup`:新参 `block: bool=False`。互斥并入 [L491-494](backend/app/api/v1/module_bre/statistics/service.py#L491-L494):`block` 与 `gxe/gxr`(共用 Z₂ 槽)409、`block` 与 `spatial`(残差结构与第二随机效应槽)409。新分支:读 `select(TreeModel.id, TreeModel.block_no)` → `block_of={f"t{tid}": int(blk)}`;无 block_no 的树**降级剔除表型保留系谱**(镜像 spatial 缺坐标降级,note 记剔除数);`len(set(block_of))<2` → 409「区组数据不足:需 ≥2 个区组(请先运行 /statistics/trial-design 生成设计并落库 block_no)」;`method="ABLUP-BLOCK"`、model_name 前缀 `ABLUP_BLOCK_`、note_payload 含 `sigma_block/block_ratio/n_blocks/warning`;accuracy 按 block 树均值可靠性。
|
||
3. **Schema/控制器/前端**:`RunAblupIn` 加 `block: bool=False`;controller `/ablup/run` 透传;前端 statistics「多环境 GxE」tab 加 `blockEnabled` 复选框 + 互斥 watch(block↔gxe/gxr/spatial)+ payload.block + 成功文案/说明三元。
|
||
4. **探针** `Temp/claude/e2e_ablup_block_20260805.py` **3 批次落库全过**——[1] 3 区组×5 株已知 σ²block>0 → method/n_blocks/σ²block/block_ratio + EBV 独立矩阵解一致;[2] 单区组 409;[3] 无 block_no 409;[4] block+gxe/block+spatial 409 互斥;[5] 部分缺 block_no 降级剔除 + note 含剔除数;[6] 全收敛数据无区组归零警告。
|
||
|
||
**批5-B(N1):孟德尔检验落库 + 自动隔离 + 进数据质量报告**:
|
||
|
||
1. **新表**(create_all 自动建):`MendelianCheckModel`→`bre_mendelian_check`(dataset_id/compat_threshold/计数/summary_json/data_version/input_hash/engine_version/note)+ 子表 `MendelianCheckTreeModel`→`bre_mendelian_check_tree`(FK check_id CASCADE;tree_id/dam_id/sire_id/status/信息位点/兼容/不兼容/rate/flag/reason/incompatible_markers_json);`TreePedigreeExclusionModel`→`bre_pedigree_exclusion`(tree_id 唯一、reason/source_type="mendelian"/source_check_id/created_id)。
|
||
2. **服务**:`mendelian_check` 纯计算核心抽共享 `_compute_mendelian(dataset_id, compat_threshold)`(GET 预览与 POST 逐字节同源);新 `run_mendelian_check` 计算→落库主表+每树子行→**自动隔离**:flag=true 树 upsert `bre_pedigree_exclusion`,本次未 flag 但此前隔离(同 dataset 范围)删除隔离行(注册表=最新检验结论、**可逆**)。
|
||
3. **控制器**:新 `POST /bre/genotype_call/mendelian/check/run`(Auth `module_bre:genotype_call:edit`,写操作),GET 只读预览保留。
|
||
4. **进数据质量报告**:`data_quality_report` 加可选 `dataset_id`,提供时追加 `mendelian` 段(最新 `bre_mendelian_check` 计数 + flagged 树列表 + 当前隔离状态);`flagged>0 → summary.has_warning=True`;无检验记录 → `mendelian: None`。`DataQualityIn` 加 `dataset_id` 透传。
|
||
5. **系谱消费方断开亲本链**(共享 `_excluded_tree_ids()` 读注册表,树级 dam/sire 置 None + note):`_build_pedigree`(genetic_corr/index/type_b/gblup/ssgblup/gwas)、`run_ablup` 内联系谱循环、`inbreeding_depression`、`kinship_matrix`、`run_cv`、`_germplasm_pedigree`(树→种质亲本链)。**GBLUP/ssGBLUP 基因型样本不过滤**(错配是亲本声明非基因型)。
|
||
6. **前端**:genotype_call 孟德尔对话框主按钮改 POST `mendelianCheckRun`(展示 check_id + 隔离树数 + 新类型);statistics「数据质量」tab 加 dataset 选择器 + mendelian 段(flag 计数 alert + 隔离树表)。
|
||
7. **探针** `Temp/claude/e2e_mendelian_persist_20260805.py` **ok=19 fail=0**——[1] 落库(主表行/计数/子表行/check_id);[2] 隔离生效 + EBV 断开(隔离树与声明亲本亲缘=0);[3] 再跑未 flag → 隔离行清除(可逆);[4] data_quality_report(dataset_id) mendelian 段 + has_warning=True、无检验 None;[5] run_ablup note 含隔离剔除数、genetic_corr 亲缘=0;[6] GET 只读预览 8 断言零回归。
|
||
|
||
**批5-C(N2):统计引擎全量数值真值校验**(`Temp/claude/e2e_stats_numerics_20260805.py`,**ok=101 fail=0**):
|
||
|
||
- **14 个引擎段 + 4 服务端点段全过**:`blup.solve` 普通(独立 V⁻¹ BLUP≡MME + 网格 REML 表面一致)、`_solve_gxe`(MME 恒等 + 方差分解)、`_solve_block`(MME 恒等 + 区组效应恢复)、`solve_spatial(_aniso)`(R 重构 + MME 恒等 + ρ_row/ρ_col 恢复)、`build_g_matrix`(手算 VanRaden method2)、`solve_gblup`(MME 恒等 + 可靠性公式)、`_build_h`(教科书 H⁻¹ 含 Christensen 缩放 + 岭)、ssGBLUP MME 恒等 + 非基因型株 EBV≠0、`solve_bivariate`(完全正相关 r_g→1 / 独立 r_g≈0)、`solve_multi`(已知 G0 恢复 + PSD)、`finlay_wilkinson`(独立 OLS)、`ammi`(解析 2×2 SVD)、`solve_rcbd`(手算 SS/MS/F)、`_solve_diallel`(手算 GCA/SCA)、`_proj_simplex`/`_solve_ocs`/`_selection_intensity`、服务端 `run_cluster`(UPGMA 首次合并=最小距离对)、`genetic_gain`(ΔG=k·r_g·σ_A 复算)、`data_quality_report`(IQR/MAD 手算边界)、`kinship_matrix`(3 节点 A 手算)。
|
||
- **探针自身两处 fixture 缺陷修复(引擎本体零缺陷)**:① A8.4 独立性状 r_g 假收敛 -0.99 / A9 G0 恢复不可靠——根因是 4 创始人+10 子代低 h²(h²≈0.43)小样本 REML 面平坦/近边界(单性状 ve 塌缩、EM 起点被毒化),**换高遗传力(va=[4,3,2.5]、ve=[0.5,0.4,0.35],h²≈0.87-0.9)+ 高真相关(0.95/0.90/0.85)+ 10 全同胞家系×3 株(n=54,24 创始人)良态设计** → r_g 恢复误差 ≤0.06(11.1s 收敛);② B4.2 硬编码 `tree_id==4`(fixture 树真实自增 id 5664 非 4)→ 改 `trees[3]`(值 9.0 精英株)。逐项核实 EM-REML/M-step/固定点/MME/剖面均教科书正确,非引擎 bug 不误报。
|
||
- **runtime 约束记录**:`solve_multi` 3 性状 n≥100 时每次迭代 MME `solve+inv` 0.7s(n=100)超 2 分钟,数值探针 fixture 保持 n≤54。
|
||
|
||
**验证**:
|
||
|
||
- 三新探针(e2e_ablup_block / e2e_mendelian_persist / e2e_stats_numerics)全过;**27 套件全量回归零回归**(含 e2e_mendelian_check / e2e_trial_design / e2e_trial_design_ext / e2e_gxe / e2e_gxr / e2e_molrigor / e2e_gwas / e2e_mating_kinship / e2e_mating_ebv / e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_gs_family_cv / e2e_batch_selection / e2e_ocs / e2e_mabc / e2e_gaps_base / e2e_gaps_engines / e2e_gaps_modules / e2e_prediction_rigor / e2e_inbreeding_depression / e2e_parent_validation / e2e_advanced_gblup / e2e_corr_spatial)。
|
||
- **vue-tsc** EXIT=0(前端 statistics/statistics.ts/genotype_call/index.vue 类型检查通过)。
|
||
- **HTTP 核验**(后端重启):`POST /bre/genotype_call/mendelian/check/run`、`POST /bre/statistics/data-quality`(dataset_id)mendelian 段、`POST /bre/statistics/ablup/run`(block=True / block+gxe 409)、`POST /bre/statistics/ocs`。
|
||
- **备份镜像** `Temp/claude/backup_block_mendelian_numerics_20260805/`(18 文件按相对路径,收尾补 2 文件 → 20:更新版 `e2e_gaps_engines_20260804.py` + `http_v226.py`)。
|
||
- **方法学保留**:block 与 gxe/gxr 共用 Z₂ 槽故互斥(同一数据既跨环境又跨区组时用户二选一);孟德尔隔离**可逆**(数据修正/阈值提高再 run 自动解除);N2 探针与既有结构性探针互补(真值段独立 numpy 实现对照,fixture 良态设计避开小样本 REML 退化区)。
|
||
|
||
**批5 跟进(2026-08-05,收尾)**:
|
||
|
||
- **回归首轮抓 1 处探针陈旧断言(非引擎回归)**:`e2e_gaps_engines_20260804.py:141` 断言 `blup.ENGINE_VERSION == "1.4.0"`,批5 已升 1.5.0 → 改断言 `1.5.0` 复跑通过(与批5 三处 `_DATA_VERSION` 同步同类机械性版本断言更新)。**27 套件全量回归最终全部 exit=0**。
|
||
- **HTTP 核验完成**(`Temp/claude/http_v226.py`,后端重启后真实端点,**ok=14 fail=0**):`POST /bre/genotype_call/mendelian/check/run` 200(check_id + isolated=1);`GET /bre/genotype_call/mendelian/check` 只读预览零回归;`POST /bre/statistics/data-quality`(trait+dataset_id)mendelian 段 flagged=1 + `summary.has_warning=True`;`POST /bre/statistics/ablup/run`(block=True)200 → prediction `method=ABLUP-BLOCK`、model_name 前缀 `ABLUP_BLOCK_`、note 含 `sigma_block/n_blocks=2`;block+gxe / block+spatial 均 409(Z₂/残差互斥文案);`POST /bre/statistics/ocs` 200(contributions 4 条和=2)。fixture 运行后自动清理(bre_mendelian_check/tree/pedigree_exclusion 0 残留)。
|
||
- **核验前需换新 token**:`dpb_token.txt` 旧 token 过期(401「认证已失效」)→ 经 `POST /system/auth/login`(super/123456)刷新(登录在 /system 前缀,不在 /bre)。
|
||
|
||
### 18.16 批6 规划↔目标↔试验 可追溯性闭环:plan/target/trial 三 FK + trace 端点 + 双删除守卫(2026-08-05,v2.27)
|
||
|
||
> 用户全代码库 grep 实证可追溯性缺口成立:`bre_plan` 是**彻底孤立的根表**(零传入外键,`bre_trial` 无 `plan_id`/`target_id`,无 project/program 表)。用户拍板「**加试验挂目标**」最小双链:`bre_target.plan_id` + `bre_trial.plan_id`(双链),另加 `bre_trial.target_id`(试验挂目标)。`_DATA_VERSION` v2.26→**v2.27**(`statistics/service.py:97` + `genotype_call/service.py:45`;5 处探针版本断言同步:e2e_prediction_rigor:102 / e2e_spatial_sparse:175+229 / e2e_statsflow:174 / e2e_mendelian_persist:207)。
|
||
|
||
1. **DB**:新 `backend/sql/weld_plan_trace.sql`(幂等 ALTER 三列 + FK,已应用验证):`bre_target.plan_id` FK→`bre_plan`、`bre_trial.plan_id` FK→`bre_plan`、`bre_trial.target_id` FK→`bre_target`,均**可空**(历史孤目标/独立试验不受影响,可追溯性渐进式)。
|
||
2. **target 三件套**:`TargetModel.plan_id` + relationship;schema `plan_id` 透传;get_list outerjoin 解析 `plan_name`;create 父校验(plan_id 不存在 → 409,None 跳过);delete `assert_no_children`(有 combo 子 → 409)。
|
||
3. **trial 三件套**:`TrialModel.plan_id`/`target_id` + 双 relationship;schema 双字段透传;get_list 解析 `plan_name`+`target_name`;create 双父校验(不存在 → 409,None 跳过);delete `assert_no_children`(有 trial_study 子 → 409)。
|
||
4. **plan trace 端点**:新 `trace(plan_id)` 服务方法 + `GET /bre/plan/trace/{id}`——`{plan, targets:[{…,n_combinations,n_trees,combinations:[{…,trees}]}], trials:[{…,target_name,n_trial_studies,n_trees,trial_studies:[{…,trees}]}], totals}`;组合/试验点**软删过滤**;孤目标不入链;不存在计划 409;plan.delete `assert_no_children`(有 target/trial 子 → 409)。
|
||
5. **前端**:target/trial 表单「所属计划/目标」select(`res.data.data ?? []`)+ 表格/详情列;plan 页「追溯」行操作弹窗(ElCollapse 目标链/试验链 + ElTags)。
|
||
6. **探针** `Temp/claude/e2e_plan_trace_20260805.py` **17 断言全过**(目标链/试验链/totals/软删过滤/孤目标不入链/三父校验 409/双删除守卫 409/标签解析),自清理(含 bre_target 审计行)。
|
||
7. **审计探针根治(本批排查修复)**:`e2e_audit_20260805.py` 残留检查原 `entity_id.in_(CREATED_TARGET_IDS)` 未限定 `entity_type`,而 `entity_id` 按实体表各自序列**非全局唯一**(`breeding_target_id_seq` 推进到 691 后,target id 与既有 `bre_cross_combination`(669/685)/`bre_germplasm`(675) 审计行撞 id → 间歇误报「仍有残留 id=…」)→ 残留检查限定 `entity_type=='bre_target'`(与 clean() 删除范围一致),连续 5 轮 13/13 稳定。
|
||
|
||
**验证**:新探针 17/17 + **全量回归零回归**(60 套件,含批5 三探针零变化)+ **vue-tsc** EXIT=0。**HTTP 核验**(后端重启,`Temp/claude/http_v227.py`):`GET /bre/plan/trace/{id}`、target/trial create 带 plan_id/target_id、三父校验 409、双删除守卫 409。**备份镜像** `Temp/claude/backup_plan_trace_20260805/`(按相对路径)。
|
||
|
||
### 18.17 批7 统计引擎全量十模块 golden 复查·系谱键空间错位修复(2026-08-05,v2.28)
|
||
|
||
> 用户质疑「GBLUP/ssGBLUP、genetic_corr、type_b、cluster、stability、OCS、MABC、inbreeding_depression、trial_design、mendelian 这批新建模块还没逐一数值校验(golden-test 缺失)。历史上 G–L 的静默失效都是靠校验才暴露的」。拍板「**全量十项逐一复查**」。复查确认 **8/10 已 golden**(GBLUP/ssGBLUP、cluster、stability、OCS、MABC、inbreeding_depression、trial_design、mendelian 既有探针已具严格数值断言),**type_b 与 genetic_corr 补齐 golden 缺口**——审计深处抓到**真 bug 就地修 + 探针加回归**。`_DATA_VERSION` v2.27→**v2.28**(`statistics/service.py:97` + `genotype_call/service.py:45` 同步;4 处探针版本断言同步:e2e_spatial_sparse:175+229 / e2e_statsflow:174 / e2e_prediction_rigor:102 / e2e_mendelian_persist:207)。
|
||
|
||
**根因(THE BUG)**:服务层把 **int `tree_id` 表型键** 传给 `mtblup.solve_bivariate`,而 `_build_pedigree` 系谱用 **str `"t{tree_id}"`**。`blup.solve` 的鲁棒逻辑(L382-385)把系谱外个体自动并入 base(视作无关 founder)→ **系谱被静默丢弃**。平衡数据(同株跨环境提供协方差)掩盖;**分裂家系数据**(无同株跨环境、全同胞链跨站点桥接)暴露——int 键 → r_B/r_g **锁死 ±0.99**(平剖面端点假收敛、假阴性负相关)。`run_ablup` 正确(L1020 `phenos_keyed={f"t{tid}": v}`),四个 mtblup 消费路径受影响。
|
||
|
||
**修复**:新增共享 helper `_tree_individual_keys(d)`(service.py:163,`{tree_id:值}→{"t{tree_id}":值}`)收口四个调用点——`_genetic_corr_matrix`(L2214)/ `_smith_hazel_index` mtblup 分支(L2754)/ `run_genetic_corr`(L5122,喂 `solve_multi` 与 `solve_bivariate`,类型注解同步改 `dict[str, dict[str, float]]`)/ `run_type_b_heredity`(L5294)。
|
||
|
||
**探针** `Temp/claude/e2e_rg_golden_20260805.py` **ok=21 fail=0**——20 founder(10 母×10 父)、10 全同胞家系×3 同胞=30 株、3 站点、高遗传力良态设计(VA=4.0/VE=0.5,h²≈0.89,与批5-N2 良态设计经验一致);tY 分裂家系(站1=同胞0,1/站2=同胞2/站3=全株,真 r_B=0.8)+ tA/tB/tC 平衡(真 r_g AB=0.95、AC=BC=0)+ tS1/tS2 分裂家系(真 r_g=0.8):
|
||
|
||
- [P0 诊断] `solve_bivariate` 直接调用:str 键恢复 r_B=0.7+、**int 键锁死 −0.99**(RED 实证);
|
||
- [P1 type_b golden] 服务端点 r_B(1,2)>0.5 + **n_common=0**(三站无共有树、靠全同胞系谱桥接——系谱生效的直接证据)+ 全正 min>0.3;
|
||
- [P2 correlation golden] r_g(A,B)>0.65、|r_g(AC/BC)|<0.4、判别间隙>0.3、h²∈(0,1);
|
||
- [P2b discriminator] r_g(S1,S2)>0.5(分裂家系无共有树,RED 下锁死 −0.99)。
|
||
|
||
探针自身缺陷修复:`_simulate` 初版 int 键 vs 观测循环 str 键 KeyError(统一 str 键)、种子扫描键错位(E0/E1/E2 vs E1/E2/E3 查键致 p2 空)、P2 间隙阈值过紧(r_g(B,C)=0.374 高抽样波动,阈值 0.4→0.3 重校准)、死 `_build_ainv` 占位行删除、**exit-code 通道 bug**(`return ok==0 and fail==0` 恒假,改 `fail==0`,断言 21/21 本就全过)。
|
||
|
||
**验证**:新探针 21/21 + `e2e_statsflow`(B1/B2,单家系 fixture 对键 bug 不敏感,15 断言零变化)+ `e2e_advanced_mtblup`(r_g=0.99/n_common=4/smith-hazel mtblup)回归通过 + **全量回归零回归**(batches 1–3 + final,60 套件,含版本断言同步)+ **vue-tsc** EXIT=0。**HTTP 核验**(后端重启,`Temp/claude/http_v228.py`):`POST /statistics/type-b-heredity`(分裂家系 r_B(1,2)>0.5 + n_common=0 + data_version=v2.28)、`POST /statistics/genetic-corr/run`(tS1,tS2 分裂家系 r_g>0.5 + 平衡 tA,tB r_g>0.65)。**备份镜像** `Temp/claude/backup_keyspace_20260805/`(按相对路径)。**方法学保留**:四个 mtblup 消费路径统一 str 键对齐系谱;探针 fixture 高遗传力 + 分裂家系结构保证判别力;`run_ablup` 正确路径不受影响。
|
||
|
||
### 18.18 回归基建:run_regression.py 统一回归 + 高风险模块正式 tc 套件(ssGBLUP/OCS/MABC/孟德尔)(2026-08-05,测试基建,不 bump 版本)
|
||
|
||
> 用户对批7 提出三点质疑,逐项核实**全部成立**,拍板「**两者都要**」——先建统一回归脚本把所有探针纳入(立即止血),再抽正式 tc 套件。纯测试基建,**无后端代码改动**,`_DATA_VERSION` 保持 v2.28:
|
||
>
|
||
> 1. 全库 `test_bre_*_tc.py`(08-03)只覆盖「数据建链/导入导出/多波次」,对 GBLUP/ssGBLUP、OCS、MABC、近交衰退、试验设计、孟德尔检验这些新建分析模块**零命中**(full_tc 的 correlation 只是 GET 200 冒烟);
|
||
> 2. 19:55 改动(批7)未补 golden 测试——批7 探针建在 Temp/claude 一次性目录、无统一回归脚本;
|
||
> 3. 风险:新模块若算偏(ssGBLUP 的 H⁻¹ 拼接、OCS 投影梯度收敛)会当「正常结果」输出——正是当年 G/I 静默失效的同款隐患(int-key bug 即活证据)。
|
||
|
||
**统一回归脚本 `run_regression.py`**(仓库根):`glob Temp/claude/e2e_*.py`(排除 `e2e_probe*` 探查工具)+ `backend/scripts/test_bre_analysis_*_tc.py` = **63 测试**;**顺序串跑不并发**(历史 RC=124 机器争用超时前科);每测试独立子进程(`cwd=os.path.dirname(p)`、timeout=1800s)完整输出写 `Temp/claude/regression_logs/<name>.log`,控制台回显尾部 + EXIT;`EXIT` 汇总任一失败整体 exit≠0(供交付流程判断);`DPB_PYTHON` 环境变量覆盖解释器(须 dpb env python,基础 miniconda 缺 PEP 695 generics SyntaxError);`sys.stdout.reconfigure(encoding="utf-8")` 防 GBK 崩溃;过滤器 `python run_regression.py gwas ocs`;`--keep-logs` 保留日志。**验证**:全量 58/59 通过,唯一失败 gaps_engines 批量卡死(10 分钟无输出)单跑 RC=0 确认通过——机器争用非探针问题。
|
||
|
||
**4 个正式 tc 套件**(`backend/scripts/`,TestClient 走真实 API + lifespan,URL 带 `/api/v1/bre/...` 前缀,登录 super/123456 form)——高风险模块必测,fixture 自带清理:
|
||
|
||
- `test_bre_analysis_ssgblup_tc.py` **ok=14 fail=0**:GBLUP vs ssGBLUP 同 fixture(5 株表型 + 基因型数据集:树0/1/3 直连、树2 名称兜底、树4 全多等位无有效剂量)。**H⁻¹ 拼接判别核心**——非基因型株(树4)GBLUP EBV=0 / ssGBLUP EBV≠0(若 H⁻¹=A⁻¹+[0;G⁻¹−A22⁻¹] 拼接错,非基因型亲属 EBV 为 0 或爆炸);h²∈(0,1)、5 条 EBV、全部有限。
|
||
- `test_bre_analysis_ocs_tc.py` **ok=23 fail=0**:8 种质(F1/F2/F3/D/E + A/B 全同胞 + C 半同胞)EBV 全 direct。Σc=3/c≥0/coverage direct 5/最高贡献 A≈1.419、vs_top_n mean_ebv 9.7667/avg_kinship 0.5556/c'Ac≈4.641、λ↑→avg_kinship 单调非增 [1.0,0.5157,0.3211,0.2685]、λ=0 满额投 A、kinship_status=partial+告警 D/E、n_select>候选/空候选→**409**、λ<0→**422**(schema 层 Pydantic ge=0 拦截)。
|
||
- `test_bre_analysis_mabc_tc.py` **ok=24 fail=0**:轮回亲本 + 6 候选(C6 童期)、前景 F1/F2 + 背景 M1-M4。前景命中/背景恢复率 100/75/0 复算、回交建议(晋级 BC2/再回交/维持)降序、童期 C6 晋级、轮回亲本无基因型 warning、target 越界→**422**(le=100 schema 校验)、其余 409。
|
||
- `test_bre_analysis_mendelian_tc.py` **ok=9 fail=0**:P1/P2 全 0/1→T1、P3/P4 全 0/0→T2(5 标记)。POST `/bre/genotype_call/mendelian/check/run`(**下划线** `genotype_call`,非连字符)落库 + T2 flag 进隔离注册表 `bre_pedigree_exclusion`(source=mendelian/source_check_id)+ 阈值 0.0 重跑可逆(隔离行清除)+ GET 只读预览零回归;data_version=v2.28 落库。
|
||
|
||
**tc 套件关键教训**(写进探针防再犯):
|
||
|
||
- **HTTP 语义差异**:schema 层 Pydantic 校验(ge/le 约束)拦截 → **422**;服务层 CustomException → **409**(e2e 直调只见 409,tc 走 HTTP 见 422)——断言错误码须按路径定;
|
||
- **Mapper 注册**:`PlantingModel` 等 relationship 引用 `UserModel`,tc 套件必须显式 `from app.api.v1.module_system.user.model import UserModel` 注册,否则 SQLAlchemy `InvalidRequestError: expression 'UserModel' failed to locate a name`;
|
||
- **时序验证**:孟德尔 tc 的隔离注册表断言必须在 run1 落库后、run2(阈值 0.0 清除)**之前**验证,否则必然 n=0 假失败;
|
||
- **启动残留预清理**:`_wipe()` 按前缀清残留(防上次进程被杀/建 fixture 中途失败留下 `uq_bre_trait_code` 等唯一键脏数据),套件可重复跑。
|
||
|
||
**验证**:4 个 tc 套件 EXIT=0(14/23/24/9)+ 全量回归 58/59(gaps_engines 单跑确认)。**备份镜像** `Temp/claude/backup_test_rigor_20260805/`(root/run_regression.py + backend/scripts 4 tc 套件)。**交付流程**:凡改动统计引擎/业务链后端代码,跑 `python run_regression.py`(dpb env 解释器)全量回归 EXIT=0 后方可交付;新 tc 套件命名 `test_bre_analysis_<模块>_tc.py` 由驱动自动纳入。
|
||
|
||
### 18.19 回归基建 2:分析模块 tc 补齐(5 套)+ pytest 接入 + 本机 CI stage(2026-08-05,测试基建,不 bump 版本)
|
||
|
||
> 用户对 §18.18 的 4 套 tc 认可后,继续补齐 5 个静默失效风险较低但属相关性/回归/生成器类的分析模块(genetic_corr / type_b_heredity / inbreeding_depression / trial_design / run_stability),并把 v8 验收标准定为「**CI 跑通 pytest 全绿**」。两条硬约束:① **基于真实 PostgreSQL 16 + Redis**(工程无 SQLite,tc 全部在真实 PG+Redis 实跑);② **不做 GitHub Actions / 不登录 GitHub**(全工程无 git 仓库,GitHub Actions 云端本机用不上)——CI stage 落地为本机驱动脚本 `run_ci.py`。纯测试基建,无后端代码改动,`_DATA_VERSION` 保持 v2.28。
|
||
|
||
**补齐 5 套 tc**(`backend/scripts/`,TestClient 真实 API + `-X utf8` + `_wipe()` 残留预清理 + 自带清理):
|
||
|
||
- `test_bre_analysis_genetic_corr_tc.py` **ok=19**:平衡 3 性状(VA=4/VE=0.5,真 r_g AB=0.95/AC=BC=0,h²≈0.89)——matrix_json 对角 1/对称/r_g(AB)>0.65/|r_g(AC,BC)|<0.4/判别间隙>0.3/h²∈(0,1);**分裂家系判别** tS1(测同胞 0/1)+tS2(测同胞 2):r_g(S1,S2)>0.5 且 **n_common=0**(无共有树,全同胞系谱桥接生效;**rng 消耗序敏感性**——S1/S2 用独立种子 `SEED_S=3`(扫描 0-39 验证 r≈0.99)解耦自探针 tY-first 顺序);409×3。
|
||
- `test_bre_analysis_type_b_tc.py` **ok=18**:3 站点分裂家系(站1=同胞0/1×20 株/站2=同胞2×10/站3=全株×30):3 环境 envs_json 20/10/30、r_B(1,2)/r_B(1,3)/r_B(2,3)>0.5、min>0.3、**n_common=0**;**复刻探针 tY-first rng 消耗序 → r=0.990**;409×3(坏 trait/env_dim/method)。
|
||
- `test_bre_analysis_inbreeding_tc.py` **ok=44**:12 树(6×F=0 + 6 自交 dam==sire F=0.5),y=100−60F+ε → slope<−40/t<−3/r²>0.9/has_depression=true/高 F 前 6 自交株;无衰退 slope≈0 未检出;**方向感知** asc 病指 y=10+40F slope>30(上升=指数型);deep 系谱 GP→G7/G8→H 树 F=0.125(mean_F≈0.0625);min_n=20 insufficient("12 棵"/"≥20")不 409;409+422。
|
||
- `test_bre_analysis_trial_design_tc.py` **ok=25**:增广 12 条目(9 新品系+3 对照)——新品系 3 区组×3 条不重复、**对照 block_no=None 不落库**(check_reps=3);α-格子平方 v=9 k=3 r=4(λ≤1、每 rep 可分解、warn=False)/ 部分 r=3 仍平衡 / v=16 k=4 非素数 warn=True / 一般 v=12 贪心(r 缺省=s=4);**block_no=rep*100+block 复合编码 DB 读回**(TestClient 退出后单一 asyncio.run 防嵌套 loop);409×4;**教训**:α-格子 r=4 会 case() 整表覆写 block_no——部分 r=3 重跑须在 r=4 **之前**,否则 DB 读回是部分态。
|
||
- `test_bre_analysis_stability_tc.py` **ok=16**:3 组合×3 站点 cell means C0=[0,6,12]/C1=[2,5,8]/C2=[4,4,4] → FW b≈2.0/1.0/−0.0、flag_stable C1=True 其余 False(|b−1|≤2se)、r²≈1(常量响应基因型 r²=None 合法);AMMI n=9、rank 按 ASV 升序、IPC1 占比 1.0≥IPC2、ss_interaction=36>0;engine_version 落库断言;year 维度 + 409×2(坏 methods/gxe_env)。
|
||
|
||
**pytest 包装层 `backend/tests/test_stat_analysis_tc.py`**:9 套 tc 各一个 pytest 测试(`@pytest.mark.pg` + parametrize),subprocess 顺序串跑真实脚本(镜像 run_regression 契约:`DPB_PYTHON` 覆盖、`-X utf8`、timeout=1800)。**环境控制关键**——包装层不 import 任何 app 模块(防 conftest sqlite 污染);subprocess env 显式构建:剥掉 conftest 注入的 `DATABASE_TYPE/DATABASE_NAME/POOL_SIZE/MAX_OVERFLOW/CAPTCHA_ENABLE`,置 `ENVIRONMENT=dev`/`DATABASE_TYPE=postgres`/`PYTHONPATH=backend`/`PYTHONUTF8=1`,再并入从 `backend/env/.env.dev` 解析的真实连接值(`TC_CI_*` 可覆盖验证 skipif 路径)。**skipif 探测**:asyncpg 连 PG + redis.asyncio ping;**`protocol=2` 必须显式**——redis-py 7.x 默认 RESP3,本机 WSL redis-server 版本较老 `hello` 报 `ResponseError`,与 `app.core.database.redis_connect`(`Redis.from_url(...protocol=2)`)对齐即通;任一失败 `pytest.skip`。`pyproject.toml` 注册 `pg` marker(消 PytestUnknownMarkWarning);`conftest.py` 加 `collect_ignore_glob=["../scripts/test_*.py"]` 防收集 import 独立脚本污染 sqlite 环境。
|
||
|
||
**本机 CI stage `run_ci.py`**(仓库根):step 0 探测真实 PG16+Redis(asyncpg + redis.asyncio protocol=2,失败给明确指引并 exit≠0);step 1 `pytest -m pg`(dpb python + `-X utf8`,cwd=backend)跑 9 套;step 2 汇总 EXIT=0 →「✅ CI 全绿」;日志写 `Temp/claude/ci_logs/`。与 run_regression 并存(run_regression=手动全量回归 / run_ci=验收门)。
|
||
|
||
**验证**:5 套逐个 EXIT=0(19+18+44+25+16=**122 断言**);`pytest -m pg` **9 passed**(真实 PG+Redis,146s,含既有 4 套零回归);skipif 路径(`TC_CI_DB_PORT=1` 指错端口)**9 skipped** 不红、无 unknown-marker 警告、scripts 未被收集(88 collected/79 deselected/9 pg);`run_ci.py` **EXIT=0「CI 全绿」**;`run_regression.py test_bre_analysis` glob 自动纳入 9 套。**备份镜像** `Temp/claude/backup_analysis_tc2_20260805/`。**交付流程**:v8 验收 = `python run_ci.py` EXIT=0(或 `cd backend && pytest -m pg` 全绿);改动统计引擎/业务链后端仍跑 `python run_regression.py` 全量。
|
||
|
||
### 18.20 O2–O4 统计方法学广度:幼年–成年遗传相关 + 非线性基因组预测 + 约束选择指数(2026-08-05,v2.29)
|
||
|
||
> 用户系统核对统计引擎能力后确认三项 **P2 方法学缺口**(均零命中、不影响当前业务正确性,属统计方法库广度),拍板「O2–O4 先落地」+ 两项决策:① O4 用经典 Kempthorne–Nordskog **=0 闭式解**(纯 numpy 不迭代);② 前后端同步扩展。方法学扩展 → `_DATA_VERSION` v2.28 → **v2.29**、`genomic.ENGINE_VERSION` 1.3.0 → **1.4.0**。**无新表**:O2 复用 `bre_type_b_result`(env_dim 自由字段)、O3 复用 `bre_prediction`/`bre_prediction_value`(method 标签扩展)、O4 复用 `bre_selection_index`(result_json 已含 extra)。
|
||
|
||
**O2 幼年–成年遗传相关(env_dim="stage")**:`_values_by_tree_env`(service.py:324)加 stage 分支——`coalesce(obs.stage, TraitModel.stage)` 分组(观测缺省继承 `bre_trait.stage`)、group_by 含 coalesce 表达式、同树同阶段多次观测取均值;`run_type_b_heredity` env_dim 校验扩 `("site","year","stage")`。发育阶段当"环境"→ 逐对 `mtblup.solve_bivariate` REML 精确估幼-成遗传相关 r_g(>0.5 表示童期可借力成株、早期间接选择有效)。前端 Type-B 页签 env_dim 下拉加「stage=发育阶段(幼/成)」。
|
||
|
||
**O3 非线性基因组预测(genomic 1.4.0)**:
|
||
- `solve_rrblup`(service 5774 分派):**岭回归逐标记** y=μ+Xu+e,u=(Xc'Xc+λI)⁻¹Xc'yc,λ 由剖面 REML σa²/σe² 定(σu²=σa²/c、c=2Σp(1-p)),EBV=Xc·u+μ —— **与 GBLUP 数学对偶**(G=XcXc'/c 时闭式解 ĝ=G(G+λa·I)⁻¹yc+μ 逐位吻合,探针 1.42e-13);输出 marker effects(GBLUP 无的解释能力)+ PEV 可靠性近似。
|
||
- `solve_bayesb`:**BayesB Gibbs 可变选择**——δ_j~Bernoulli(1−π)+方差尺度混合、σ²j~inv-χ²(df_s+1,(df_s·scale0+u_j²)/(df_s+1))、σe²~inv-χ²(df_e+m,...),**`numpy.random.default_rng(seed)` 确定性**(MLOps 铁律:同 seed 两次 EBV 逐位一致);π 默认 0.95、稀疏 QTL 场景取 0.7 更贴合 30% QTL 真值。
|
||
- `kfold_cv_genomic` 加 dosage/markers 分派:rrblup/bayesb 折内走对应求解器(**实证 CV**);`run_cv` GS 分支透传 seed + genotypes + markers,method_name=KFCV/RRBLUP·KFCV/BayesB。
|
||
- `run_gblup` method 扩 `("gblup","ssgblup","rrblup","bayesb")` + seed 透传,rrblup/bayesb 从 `_gather_gblup_inputs` dosage 构 X → `asyncio.to_thread` 引擎,落 `PredictionModel(method=RRBLUP/BayesB)` + `PredictionValueModel`(EBV/rel/pa/rank)、engine_version=1.4.0。前端 GBLUP/CV 页签 method radio 加 RRBLUP/BayesB + seed 输入。
|
||
|
||
**O4 约束选择指数(restricted 闭式解 + economic weights)**:
|
||
- `_smith_hazel_index` 加 `restricted_traits`/`economic_weights`。受限时 **Kempthorne-Nordskog Lagrange 闭式投影**:C(第 j 行=第 j 个受限性状单位向量)、**M = C'(C·G·P⁻¹·G·C')⁻¹·C·G·P⁻¹·G**、b = P⁻¹·G·(I−M)·a → 约束 C·G·b=0 ⇔ **受限性状 ΔG=0**(纯 numpy pinv,不迭代)。**对照旧公式 M=C'(C·P⁻¹·C')⁻¹·C·P⁻¹ 实测 ΔG=4.46 不满足 → 修正必要**(e2e O4-1c 断言锁定)。
|
||
- economic_weights 直接作 a(绝对尺度、**不归一化**统计权重、未列性状按 0 不进聚合基因型),可与 restricted 叠加;`direction=asc` 仍翻转 a[i](b=P⁻¹Ga 线性于 a → 保证该性状 b 相对下降,(P⁻¹G)₀₀>0 保号,非必 sign flip——tc 断言用严格下降)。
|
||
- extra 落 `restricted`/`constraint_mode=ΔG=0`/`economic` + warnings;method 校验扩 `("zsum","smith_hazel","restricted")`、缺 restricted_traits 409、restricted_traits ⊆ cols(越界 409)、economic_weights 性状 ⊆ tmap。落库 method=SI_RES。前端指数页 method radio 加 restricted + restricted_traits 多选 + 每性状经济权重输入。
|
||
|
||
**顺手修复(tc 暴露的既有缺口)**:`cv_detail` 折明细 dict 缺 `cv_result_id`(CvFoldOut 必填字段)→ 任意 GET /cv/{id} **400**(既有 tc 均未触达该端点,静默失效风险同款);补 `"cv_result_id": cv_id` 后 rrblup/bayesb CV 详情可查。
|
||
|
||
**验证**:`e2e_o234_20260805.py` 探针 19 断言(O3 对偶逐位 1.42e-13 + marker effects + BayesB 可复现 + kfold 5 折;O4 受限 ΔG=0 机器精度 + 旧公式失败 + economic asc 翻转;O2 真实 PG 16 树 r_g=0.6145);正式 tc `test_bre_analysis_o234_tc.py` **ok=41 fail=0**(TestClient 真实 API + golden:O2 env_dim=stage r_g=0.8995/n_common=12/双阶段 12 株/data_version=v2.29;O3 落库 method+engine_version 1.4.0/bayesb 同 seed 两次逐位一致/rrblup·GBLUP EBV 相关 1.000/CV 折数=5/非法 method 409;O4 restricted b_受限=0.0/economic desc>0·asc<0/缺 restricted_traits 409)+ TC_SCRIPTS 注册第 10 套 + **全量回归零回归**(61 e2e + 10 tc)+ `run_ci.py` EXIT=0「CI 全绿」。备份镜像 `Temp/claude/backup_o234_20260805/`。
|
||
|
||
## 十、文件清单与备份
|
||
|
||
### 新增/修改文件(2026-08-03)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | G×E 引擎 + 异步任务 + 门禁(含 `blup.solve` 传参) |
|
||
| `backend/app/api/v1/module_bre/statistics/model.py` | `StatisticsJobModel`(job_type/status/error_msg/result_ref) |
|
||
| `Temp/claude/e2e_gxe_20260803.py` | G×E e2e 探针(5 场景) |
|
||
|
||
### 新增/修改文件(2026-08-04)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_trait_direction.sql` | 幂等 ALTER 三列 |
|
||
| `backend/sql/bre_trait_seed.sql` | 种子数据含三新列(43 行) |
|
||
| `backend/app/api/v1/module_bre/trait/model.py` / `schema.py` / `service.py` | 三字段透传 + 批量导入导出兼容 |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | 方向翻转 + into_ebv 剔除 + default_h2 兜底 + 排行/对比方向修复 |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | `selection_only` query 参数 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `listTraits` 带 selection_only |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | selTraits 解耦 + asc 角标 |
|
||
| `frontend/web/src/views/module_bre/trait/index.vue` | 三字段表单/表格/详情/搜索 |
|
||
| `frontend/web/src/views/module_bre/selection_rule/index.vue` | 规则 JSON 说明 |
|
||
| `Temp/claude/e2e_direction_20260804.py` | 方向标注 e2e 探针(7 组) |
|
||
|
||
### 新增/修改文件(2026-08-04 无性系级指数)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `SelectionIndexIn.aggregate`(clone 默认 / tree)+ 文件头补 UTF-8 编码声明 |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | selection_index 透传 `data.aggregate` |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_clone_units` 可靠加权聚合 + 自株退化;zsum/Smith-Hazel 改单元 key 排名;`apply_selection` 按遗传实体写(clone_id + 溯源株 + 系内N株)+ 幂等晋升建 clone |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `selectionIndex` data 加 `aggregate` |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 聚合粒度 radio + clone 结果列 |
|
||
| `Temp/claude/e2e_clone_index_20260804.py` | 无性系级指数 e2e 探针(6 组) |
|
||
|
||
### 新增/修改文件(2026-08-04 配合力交配设计)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_combining_design.sql` | 幂等 ALTER:`bre_cross_combination` / `bre_combining_ability` 加 `design_type` |
|
||
| `backend/app/api/v1/module_bre/cross_combination/model.py` / `schema.py` / `service.py` | `design_type` 字段 + create/update 校验归一化 + 导出/导入/模板兼容 |
|
||
| `backend/scripts/breeding_stats/combining.py` | `solve(rows, design_type)` 按设计分支:双列 model A / line_tester+NCIII model B(双因素、顺序 ANOVA、角色重叠/NCIII 门禁、gca_se) |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` / `schema.py` / `service.py` | `run_combining` 透传 design_type + 按设计过滤 + 落库 + `anova.gca_se` |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` / `cross_combination.ts` | design_type 类型透传 |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` / `cross_combination/index.vue` | 运行对话框设计选择 + 结果分显示 + CRUD 四处支持 |
|
||
| `Temp/claude/e2e_combining_design_20260804.py` | 配合力交配设计 e2e 探针(5 组) |
|
||
|
||
### 新增/修改文件(2026-08-04 统计严谨·预测完整性与 MLOps 复现性)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_prediction_rigor.sql` | 幂等 ALTER:`bre_prediction_value.pa` + `bre_prediction.data_version/input_hash/engine_version` |
|
||
| `backend/sql/weld_rootstock.sql` | 幂等 ALTER:`bre_rootstock.dwarf_class/compatibility` |
|
||
| `backend/app/api/v1/module_bre/statistics/model.py` / `schema.py` | `pa`/`data_version`/`input_hash`/`engine_version` 字段 + OutSchema 透出 |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_DATA_VERSION="v2.7"`;PA 落库 + 批次真 PA;输入哈希(确定性序列化);germplasm_id 回填;Calo 相关校正(`rel_by_trait` + `g_corr`/`g_note`);`covariate="competition"`(Chebyshev 邻域 + G×E 泛化 + 无坐标报错) |
|
||
| `backend/scripts/breeding_stats/blup.py` | `ENGINE_VERSION="1.0.0"` |
|
||
| `backend/app/api/v1/module_bre/rootstock/model.py` / `schema.py` / `service.py` | `dwarf_class`/`compatibility` 字段 + 导入导出/模板下拉 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | 指数批次表/EBV 行类型加 `germplasm_id`/`pa` |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 批次表新列 + 协变量 radio(无/crop_load/competition) |
|
||
| `frontend/web/src/api/module_bre/rootstock.ts` | Rootstock 类型加两字段 |
|
||
| `frontend/web/src/views/module_bre/rootstock/index.vue` | 两字段全量(常量/搜索/表格/详情/表单) |
|
||
| `Temp/claude/e2e_prediction_rigor_20260804.py` | ②③④ e2e 探针(4 组) |
|
||
| `Temp/claude/e2e_rootstock_20260804.py` | ⑤ e2e 探针 |
|
||
| `Temp/claude/e2e_corr_spatial_20260804.py` | ①⑥ e2e 探针(3 组) |
|
||
| `backend/sql/weld_combination_funnel.sql` | 幂等建 `v_combination_funnel`(六级聚合普通 VIEW) |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` / `controller.py` | `combination_funnel()` 查视图 + `GET /statistics/combination-funnel` |
|
||
| `Temp/claude/e2e_combination_funnel_20260804.py` | 组合得失漏斗 e2e 探针(3 组) |
|
||
|
||
### 新增/修改文件(2026-08-04 分子育种建数据能力)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_molecular.sql` | 幂等补 `bre_genotype_sample.sample_name` + (dataset_id, sample_name) 索引 |
|
||
| `backend/sql/bre_menu.sql` | 900210-900213 切真实页面 + F 段按钮 900700-900799 + 角色关联 |
|
||
| `backend/app/api/v1/module_bre/marker/` | 五件套(marker_name UNIQUE 校验、CRUD/导入导出/模板) |
|
||
| `backend/app/api/v1/module_bre/genotype_dataset/` | 五件套(v1.4 规划表首次建服务) |
|
||
| `backend/app/api/v1/module_bre/genotype_sample/` | 五件套(dataset FK 校验 + dataset_name 透出) |
|
||
| `backend/app/api/v1/module_bre/genotype_call/` | 五件套 + `import_vcf` + `fingerprint_check` 两个专属端点 |
|
||
| `backend/app/api/v1/module_bre/__init__.py` | 注册 4 组路由 |
|
||
| `frontend/web/src/api/module_bre/marker.ts` | MarkerAPI |
|
||
| `frontend/web/src/api/module_bre/genotype_dataset.ts` | GenotypingDatasetAPI |
|
||
| `frontend/web/src/api/module_bre/genotype_sample.ts` | GenotypeSampleAPI |
|
||
| `frontend/web/src/api/module_bre/genotype_call.ts` | GenotypeCallAPI + VCF/指纹接口与结果类型 |
|
||
| `frontend/web/src/views/module_bre/marker/index.vue` | 标记 CRUD 页 |
|
||
| `frontend/web/src/views/module_bre/genotype_dataset/index.vue` | 数据集 CRUD 页 |
|
||
| `frontend/web/src/views/module_bre/genotype_sample/index.vue` | 样本 CRUD 页(dataset 下拉) |
|
||
| `frontend/web/src/views/module_bre/genotype_call/index.vue` | 分型 CRUD 页 + 导入 VCF / 指纹检测对话框 |
|
||
| `Temp/claude/e2e_molecular_20260804.py` | 分子育种 e2e 探针(CRUD/唯一键/父级/指纹/VCF/幂等) |
|
||
|
||
### 新增/修改文件(2026-08-04 精修项四连发:DUS 数据能力 + stage 感知 + k-fold CV + 公平性报告)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_refine.sql` | 幂等 ALTER:`bre_prediction.stage varchar(16)` + COMMENT |
|
||
| `backend/sql/bre_dus_seed.sql` | UPOV TG/53 桃描述符 15 条种子(trait_code LEFT JOIN 解析 trait_id,ON CONFLICT DO NOTHING) |
|
||
| `backend/sql/bre_menu_refine.sql` | 900230 切真实页 + G 段按钮 900800-900808 + 角色关联 |
|
||
| `backend/app/api/v1/module_bre/dus/` | 五件套 ×3 资源(descriptor 9 端点含导入导出模板 / test 9 / observation 6),注册 `/bre/dus_test/*` |
|
||
| `backend/app/api/v1/module_bre/statistics/model.py` | `PredictionModel.stage` + `CvResultModel` + `CvFoldModel`(create_all 建表) |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `PredictionOut.stage` + `CvRunIn/CvResultOut/CvFoldOut` + `SelectionIndexIn/DecisionPreviewIn.stage` |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_trait_meta_map` 取 stage;`run_ablup` 落 stage;`run_cv/list_cv/cv_detail`;`fairness_report`;`selection_index/decision_preview` stage 过滤 + `stage_warning`/`skipped_stage` |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | `/statistics/cv/run` `/statistics/cv` `/statistics/cv/{id}` `/statistics/fairness` + 指数/决策 stage 透传 |
|
||
| `backend/scripts/breeding_stats/blup.py` | `kfold_cv`:sire 家系分层留出 + 逐折 try/except + 留出 EBV 系谱预测 |
|
||
| `frontend/web/src/api/module_bre/dus.ts` | 三组 API + 类型 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `runCv/listCv/cvDetail/fairnessReport` + `listTraits` 补 stage |
|
||
| `frontend/web/src/views/module_bre/dus/index.vue` | 单页三 tab(描述符模板/DUS 测试/观测录入) |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 「交叉验证」「公平性报告」双 tab + 指数/决策 stage 三态 + `stage_warning` ElAlert |
|
||
| `Temp/claude/e2e_refine_20260804.py` | 精修项四连发 e2e 探针(4 组,ABLUP/GXE CV + 2 site 公平性) |
|
||
|
||
### 新增/修改文件(2026-08-04 六项能力完善:MT-BLUP + GBLUP/ssGBLUP + DUS 特异性 + AMMI/FW 稳定性 + MLOps 重训 + stage 拆分)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_advanced.sql` | 幂等 ALTER:`bre_prediction.is_active` + `bre_trait_observation.stage` + `bre_dus_test.analysis_json`(jsonb)+ COMMENT |
|
||
| `backend/app/api/v1/module_bre/statistics/model.py` | `PredictionModel.is_active` + `GeneticCorrResultModel` + `StabilityResultModel`(create_all 建 2 新表) |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `GeneticCorrIn/GeneticCorrResultOut/StabilityRunIn/StabilityResultOut/GblupRunIn` + `SelectionIndexIn.g_method` + `RunStatsIn.stage` + `PredictionOut.is_active/stage` |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `run_genetic_corr/list/detail`、`run_stability/list/detail`、`run_gblup/list_genotyping_datasets`、`model_drift/retrain/activate`、`run_ablup(stage)`、`_gather_digest_inputs`、`_smith_hazel_index(g_method)`;修复未定义 `tid`、retrain 不激活新批次 |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | 6 组新端点(genetic-corr×3 / stability×3 / gblup×2 / model drift·retrain·activate×3)+ 透传 g_method/stage |
|
||
| `backend/app/api/v1/module_bre/dus/service.py` | `distinctness` 求解器 + `test_distinctness`/`distinctness_report`(落 analysis_json + conclusion 自动建议) |
|
||
| `backend/app/api/v1/module_bre/dus/controller.py` / `schema.py` | `POST/GET /bre/dus_test/distinctness/{test_id}` + `DusTestOutSchema.analysis_json` |
|
||
| `backend/app/api/v1/module_bre/trait_observation/model.py` / `schema.py` / `service.py` | `stage` 字段(model 列 + create/update/out schema 透传 + 导入/导出映射,schema 暴露为收尾补丁) |
|
||
| `backend/scripts/breeding_stats/mtblup.py` | `solve_bivariate`(成对双性状 REML,ENGINE_VERSION=1.0.0) |
|
||
| `backend/scripts/breeding_stats/genomic.py` | `build_g_matrix`/`solve_gblup`/`solve_ssgblup`(ENGINE_VERSION=1.0.0;修复 V 块用 H 协方差) |
|
||
| `backend/scripts/breeding_stats/stability.py` | `finlay_wilkinson`/`ammi`(ENGINE_VERSION=1.0.0;修复完美拟合 flag_stable) |
|
||
| `backend/scripts/breeding_stats/fdist.py` | `f_icdf`(二分反解)+ `t_crit` |
|
||
| `backend/scripts/breeding_stats/blup.py` | `ENGINE_VERSION="1.1.0"` |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | 三 tab 组 API + modelDrift/Retrain/Activate + g_method/stage 类型 |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 「遗传相关 MT-BLUP」「稳定性 AMMI/FW」「基因组选择 GBLUP」三 tab + stage 三态 + g 矩阵来源 radio + 当前版本标签/漂移/重训/回滚按钮 |
|
||
| `frontend/web/src/views/module_bre/dus/index.vue` | 测试行「特异性判定」对话框 |
|
||
| `frontend/web/src/api/module_bre/tree_evaluation.ts` / `views/module_bre/tree_evaluation/index.vue` | 观测表单「观测阶段」下拉(juvenile/evaluation,写入每条观测 stage) |
|
||
| `Temp/claude/e2e_advanced_stability.py` / `stage.py` / `mtblup.py` / `gblup.py` / `dus.py` / `mlops.py` | 6 组 e2e 探针(运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.10 版本行 + §8.18 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.10.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十一 六项能力完善 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑨ + EBV/分子行更新 |
|
||
|
||
### 新增/修改文件(2026-08-04 田间试验精度补强:砧木×接穗随机互作 G×R)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/blup.py` | `_solve_gxe` 加 `factor_label/factor_name` 参数(仅喂警告文案,默认保 G×E 不变)+ 公开 `solve()` 透传 + ENGINE_VERSION 1.2.0 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `RunStatsIn.gxr` |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | run_ablup 透传 gxr |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `run_ablup(gxr)`:互斥门禁 + job_type=GXR + `elif gxr:` 分支(rootstock 剥离/门禁三件套/GXRBLUP/note σ²gxr)+ 克隆坍缩系谱上移共享 + `_DATA_VERSION` v2.10 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `RunStatsPayload.gxr` |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | G×R 复选框 + 互斥 watcher + fmtGxeNote σ²gxr 分支 + 批次表 v-if |
|
||
| `Temp/claude/e2e_gxr_20260804.py` | e2e 探针(4 组断言,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.11 版本行 + §8.19 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.11.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十二 G×R 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑩ + EBV/田间试验精度行补 G×R |
|
||
|
||
### 新增/修改文件(2026-08-04 基因组选择实证严谨性:GS 专用 k-fold CV)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/genomic.py` | 抽取 `_build_h`(缺失基因型补 base)+ 新增 `kfold_cv_genomic`(掩蔽留出 pearson/RMSE,输出对齐 blup.kfold_cv)+ ENGINE_VERSION 1.1.0 |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_gather_gblup_inputs` 提取(run_gblup↔GS CV 复用);`run_cv` 加 `dataset_id/method/maf_min` + GS 分支(与 gxe/ABLUP 互斥)+ engine_version 按分支 + `_DATA_VERSION` v2.11 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `CvRunIn.dataset_id/method/maf_min` |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | run_cv 透传三参 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `CvRunPayload.dataset_id/method/maf_min` |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | CV tab mode radio(ABLUP/GS)+ dataset/method/MAF + 隐藏 G×E + submitCv 按 mode |
|
||
| `Temp/claude/e2e_gblup_cv_20260804.py` | GS CV e2e 探针(3 组:GBLUP/ssGBLUP 正例 + 门禁,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.12 版本行 + §8.20 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.12.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十三 GS k-fold 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑪ + EBV/GS 行补「GS k-fold 实证验证」 |
|
||
|
||
### 新增/修改文件(2026-08-04 现代桃育种领域覆盖:S-allele + 抗病/需冷量性状)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/bre_disease_chilling_traits.sql` | 5 条 numeric trait 种子(3 抗病 0-5 级病情指数 + 需冷量 h + 需热量 GDD,into_ebv=1、direction=asc,幂等 ON CONFLICT) |
|
||
| `backend/app/api/v1/module_bre/germplasm/model.py` | `s_alleles` 列(String(32),Sf=自交亲和型) |
|
||
| `backend/app/api/v1/module_bre/germplasm/schema.py` | Create/Update 加 `s_alleles`(Out 继承 Create) |
|
||
| `backend/app/api/v1/module_bre/cross_combination/schema.py` | `CrossCombinationOutSchema.s_compat`(可选派生字段) |
|
||
| `backend/app/api/v1/module_bre/cross_combination/service.py` | `_parse_s_alleles`/`_s_compat_check`/`_check_s_compat` + create/update 校验(Sf 放行、共享 2→409、共享 1→半兼容警示) |
|
||
| `frontend/web/src/api/module_bre/germplasm.ts` | `GermplasmForm/GermplasmTable.s_alleles?` |
|
||
| `frontend/web/src/views/module_bre/germplasm/index.vue` | 表单加 S-等位基因输入 + 导出列 |
|
||
| `frontend/web/src/views/module_bre/cross_combination/index.vue` | 包装 createApi/updateApi 展示 `s_compat` 警示 |
|
||
| `Temp/claude/e2e_s_allele_20260804.py` | S-allele 兼容校验探针(纯函数 8 例 + service 层 5 组,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.13 版本行 + §8.21 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.13.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十四 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑫ + 相关行补「S-allele 兼容 + 抗病/需冷量性状字典」 |
|
||
|
||
### 新增/修改文件(2026-08-04 GWAS/QTL/MAS 标记辅助选择闭环)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/gwas.py` | GWAS 求解器(GLM+PC:SVD 群体结构 + `fdist.f_pvalue` p 值 + Bonferroni/BH-FDR + QTL 合并 + 岭回归共线兜底,ENGINE_VERSION=1.0.0,纯 numpy) |
|
||
| `backend/sql/weld_gwas.sql` | 幂等 `CREATE TABLE IF NOT EXISTS`:bre_gwas_result/bre_gwas_snp/bre_qtl/bre_mas_panel/bre_mas_panel_marker(5 新表兜底) |
|
||
| `backend/sql/bre_menu.sql` | §6d:`sys_menu 900214` component_path 翻转为 `module_bre/gwas/index` |
|
||
| `backend/app/api/v1/module_bre/statistics/model.py` | `GwasResultModel`/`GwasSnpModel`/`QtlModel`/`MasPanelModel`/`MasPanelMarkerModel` |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `GwasRunIn/GwasResultOut/GwasSnpOut/QtlIn/QtlOut/MasPanelIn/MasPanelOut/MasPanelMarkerIn/MasPanelSetMarkersIn` |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | gwas×3 + qtl×5 + mas-panel×4 端点(复用 `module_bre:statistics:*` 权限) |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_gather_gwas_inputs` + `run_gwas/list_gwas/gwas_detail` + qtl/mas_panel CRUD + `mas_panel_set_markers` + `_mas_hit_map` + decision_preview marker 条件 + `_DATA_VERSION` v2.12 |
|
||
| `frontend/web/src/api/module_bre/gwas.ts` | runGwas/listGwas/gwasDetail + Qtl/MasPanel/MasPanelMarker API |
|
||
| `frontend/web/src/views/module_bre/gwas/index.vue` | 三 tab(GWAS 结果 Manhattan/QQ 裸 echarts + QTL 定位 + MAS 面板)+ 运行对话框 |
|
||
| `Temp/claude/e2e_gwas_20260804.py` | GWAS/QTL/MAS 闭环探针(7 段断言,运行后自动清理;含数据设计要点避免 PC 吞噬 QTL) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.14 版本行 + §8.22 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.14.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十五 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑬ + 900214 行「GWAS/QTL 已落地」 |
|
||
|
||
### 新增/修改文件(2026-08-04 九缺口补齐:经典侧计算端点 + 分子侧严谨性 + 求解器核心)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | `POST /data-quality` + `POST /genetic-gain` + `POST /mating-recommend` + `POST /gwas-qtl-x-e` |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `data_quality_report`/`genetic_gain`/`mating_recommend`/`qtl_x_e` + `_allelic_from_gt`/装配 marker_type 分支 + `_DATA_VERSION` v2.13 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | 4 新端点入参出参 + `RunStatsIn.spatial` 等 |
|
||
| `backend/scripts/breeding_stats/blup.py` | `solve_spatial`(AR1×AR1,ENGINE_VERSION 1.3.0)+ `_build_ainv_sparse`/`_cg_solve`/Hutchinson(N_SPARSE=1000 阈值分派稀疏-CG 路径,稠密路径逐字节不变) |
|
||
| `backend/scripts/breeding_stats/gwas.py` | `_emmax` + 后处理抽共享 `_bh_qvalues`/`_finalize`/`_cluster`(GLM 逐字节不变,ENGINE_VERSION 1.1.0) |
|
||
| `backend/scripts/breeding_stats/genomic.py` | `build_g_matrix` 多等位 VanRaden 推广(ENGINE_VERSION 1.2.0) |
|
||
| `backend/app/api/v1/module_bre/genotype_call/service.py` | VCF 导入按 ALT 数定 `marker_type`(ssr/snp) |
|
||
| `backend/sql/weld_mas_semantics.sql` | 幂等 ADD COLUMN:bre_mas_panel_marker.mode / favorable_allele / haplotype_group |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 数据质量/遗传增益/选配 3 入口 + spatial 复选框 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | 3 新端点 + spatial 参数 |
|
||
| `frontend/web/src/views/module_bre/gwas/index.vue` | method 下拉(gwas/emmax)+ QTL×E tab + 面板标记编辑器三控件(xeForm 类型断言修复 vue-tsc) |
|
||
| `frontend/web/src/api/module_bre/gwas.ts` | `GwasQtlXEIn` + method 枚举 |
|
||
| `Temp/claude/e2e_data_mating_gain_20260804.py` | 批1 探针(数据质量/遗传增益/选配,运行后自动清理) |
|
||
| `Temp/claude/e2e_molrigor_20260804.py` | 批2 探针(EMMAX/SSR/QTL×E/MAS 语义,运行后自动清理) |
|
||
| `Temp/claude/e2e_spatial_sparse_20260804.py` | 批3 探针(AR1×AR1/稀疏-CG/Hutchinson,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.15 版本行 + §8.23 台账(+ 补 v2.13 缺失版本行) |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.15.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十六 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑭ + EBV/ABLUP 行、GWAS/QTL/MAS 行补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 十二项真缺口补齐:引擎三件 + 模块四件 + 底座五件)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/blup.py` | `solve_spatial` 加 `aniso`(ρ_row/ρ_col 双参,ENGINE_VERSION 1.4.0) |
|
||
| `backend/scripts/breeding_stats/mtblup.py` | `solve_multi` 全多变量 EM-REML(ENGINE_VERSION 1.1.0) |
|
||
| `backend/scripts/breeding_stats/gwas.py` | `_ssgwas` 单步 GWAS MEM 对角近似(ENGINE_VERSION 1.2.0) |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `full_mtblup=True` 模式 + `_DATA_VERSION` v2.14 + `_allelic_columns` SSR 兜底限定空 marker_type(回归修复) |
|
||
| `backend/app/api/v1/module_bre/field_operation/{model,crud,service,controller,schema}.py` | 农事操作 900051 五件套 |
|
||
| `backend/app/api/v1/module_bre/observation/{model,crud,service,controller,schema}.py` | 通用观测 900050 五件套 |
|
||
| `backend/app/api/v1/module_bre/breeding_report/{model,crud,service,controller,schema}.py` | 育种报告 900075 五件套 + `POST /report/generate` |
|
||
| `backend/app/api/v1/module_bre/analysis_dataset/{model,crud,service,controller,schema}.py` | 分析数据集 900070 五件套 + 新表 bre_analysis_dataset |
|
||
| `backend/app/api/v1/module_bre/audit/{model,crud,service,controller,schema}.py` | 审计切面 + `GET /bre/audit/list|detail` |
|
||
| `backend/app/api/v1/module_bre/alert/{model,crud,service,controller,schema,job}.py` | 超期预警 + `GET /bre/alert/list|resolve` |
|
||
| `backend/app/api/v1/module_bre/brapi/controller.py` | BrAPI 2.x /brapi/v2 五只读端点 + MIAPPE |
|
||
| `backend/app/utils/number_gen.py` | NumberGenService + pg_advisory_xact_lock 原子取号 |
|
||
| `backend/app/api/v1/module_bre/sequence/model.py` | bre_sequence 表 |
|
||
| `backend/app/api/v1/module_bre/{cross_combination,tree,selection_result,seedling}/service.py` | 4 处编号迁移(YY+3位/组合-序号/clone_code 扩位/batch_no YP-…) |
|
||
| `backend/app/core/ap_scheduler.py` | 3 系统 job(cleanup Sun 03:00 / alert 08:37 / backup 02:17) |
|
||
| `backend/app/utils/backup_job.py` | 每日备份 job 包装 pg_backup.sh(Git Bash + MSYS 路径) |
|
||
| `backend/scripts/pg_backup.sh` / `pg_restore.sh` | pg_dump 自定义格式 + N 天轮转 / 恢复脚本 |
|
||
| `backend/app/init_app.py` | brapi_router 根注册(/brapi/v2 非 /bre 前缀) |
|
||
| `backend/sql/weld_*.sql`(op_type 字典/菜单翻转/文案清理/bre_alert/bre_sequence/bre_analysis_dataset) | 幂等 weld 兜底 |
|
||
| `frontend/web/src/views/module_bre/{field_operation,observation,breeding_report,analysis_dataset,alert}/index.vue` | 4 新模块页 + 预警中心 |
|
||
| `frontend/web/src/api/module_bre/{field_operation,observation,breeding_report,analysis_dataset,alert}.ts` | 5 新 API |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | spatial aniso 复选框 + gwas method=ssgwas 下拉 |
|
||
| `Temp/claude/e2e_gaps_engines_20260804.py` | 批1 探针(ssgwas/solve_multi/aniso,运行后自动清理) |
|
||
| `Temp/claude/e2e_gaps_modules_20260805.py` | 批2 探针(四模块 CRUD + report generate + 菜单翻转,运行后自动清理) |
|
||
| `Temp/claude/e2e_gaps_base_20260804.py` | 批3 探针(审计/编号并发/预警/备份/BrAPI,运行后自动清理) |
|
||
| `Temp/claude/regress_logs/` | 全量回归日志(8 旧探针 + 3 批探针) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.16 版本行 + §8.24/8.25/8.26 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.16.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十七 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑮ + 相关行补注 + 过时「待建」标记修正 |
|
||
|
||
### 新增/修改文件(2026-08-05 桃育种业务流全面完善:批A 业务数据链 + 批B 统计算法 + 批C 前端)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/field_operation/model.py` | 4 采收列 yield_kg/fruit_count/avg_fruit_weight/marketable_rate |
|
||
| `backend/app/api/v1/module_bre/field_operation/{service,schema}.py` | harvest 结构化产量同步 `bre_trait_observation`(A1)+ 表单 4 字段 |
|
||
| `backend/app/api/v1/module_bre/observation/model.py` | germplasm_id 可空 FK(A3) |
|
||
| `backend/app/api/v1/module_bre/observation/{service,schema}.py` | 种质校验 + EAV 校验(A5)+ 4 查询过滤 tree/plot/germplasm/trial_study + germplasm 表单字段 |
|
||
| `backend/app/api/v1/module_bre/seed_lot/{model,schema}.py` | pollination_id FK(A4) |
|
||
| `backend/app/api/v1/module_bre/seed_treatment/{model,schema}.py` | seed_lot_id FK(A4) |
|
||
| `backend/app/api/v1/module_bre/tree/service.py` | create 阶段自动设置(A6,breeding_generation→juvenile/evaluation) |
|
||
| `backend/app/api/v1/module_bre/trait_observation/service.py` | EAV 校验(numeric/date parse + valid_min/max + 重复)+ 成株性状门禁(A5/A6) |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_values_by_tree_env` + `run_type_b_heredity`(B1)+ `_genetic_corr_matrix`(B2)+ `auto_weights`(B3)+ `run_cluster`(B4)+ `_DATA_VERSION` v2.15 |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | POST /type-b-heredity + GET /type-b + GET /type-b/{id} + POST /cluster + correlation mode/g_method/year 透传 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | TypeBIn/Out + CorrelationIn mode/g_method/year + SelectionIndexIn auto_weights + ClusterIn |
|
||
| `backend/app/api/v1/module_bre/statistics/model.py` | `bre_type_b_result` 新表(TypeBResultModel) |
|
||
| `backend/sql/weld_busflow.sql` | A1/A3/A4 四处 ALTER ADD COLUMN IF NOT EXISTS + index(幂等) |
|
||
| `backend/sql/bre_yield_phenology_traits.sql` | A2 产量/物候/品质/生长量/描述性状种子 19 条(ON CONFLICT 幂等) |
|
||
| `frontend/web/src/plugins/echarts.ts` | 注册 HeatmapChart + VisualMapComponent |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | type-b/cluster/correlation mode/funnel/auto_weights 类型 |
|
||
| `frontend/web/src/api/module_bre/observation.ts` | ObservationPageQuery 四过滤 + ObservationForm germplasm_id |
|
||
| `frontend/web/src/api/module_bre/field_operation.ts` | FieldOperationTable/Form 四采收字段 |
|
||
| `frontend/web/src/views/module_bre/observation/index.vue` | plot/站点/germplasm 过滤 + germplasm 表单(C1) |
|
||
| `frontend/web/src/views/module_bre/field_operation/index.vue` | harvest 结构化表单/表格 4 列(C1) |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | correlation/gblup 热图折线 + type-B tab + cluster 树状图 + funnel 对话框(C2/C3) |
|
||
| `frontend/web/src/views/module_bre/stage_phenotype/index.vue` | tabs 通用观测/农事操作翻真实页(C4) |
|
||
| `frontend/web/src/views/module_bre/_shared/StageView.vue` | compMap 注册 Observation/FieldOperation(C4) |
|
||
| `Temp/claude/e2e_busflow_20260805.py` | 批A 探针(A1-A6,11 组断言,运行后自动清理) |
|
||
| `Temp/claude/e2e_statsflow_20260805.py` | 批B 探针(B1-B4,15 组断言,运行后自动清理) |
|
||
| `Temp/claude/smoke_busflow_c_20260805.py` | 批C HTTP smoke(10 检查,不建数据) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.17 版本行 + §8.27 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.17.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §十八 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑯ + 相关行补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 世代闭环:单株晋级落系谱)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/selection_result/service.py` | `_promote_tree_to_clone` 建种质时同步落 `bre_pedigree`(child_code=品种名、dam/sire=tree.dam/sire 回退组合 female/male_parent_id、combination_id、generation,child_code 幂等)+ 种质携带 generation/stage + `combo=None` 初始化防 UnboundLocalError |
|
||
| `Temp/claude/e2e_pedigree_closure_20260805.py` | 世代闭环探针(11 组断言,运行后自动清理) |
|
||
| `Temp/claude/cleanup_pedigree_test.py` | 前缀清理脚本(幂等,探针残留兜底) |
|
||
|
||
### 新增/修改文件(2026-08-05 近交惩罚静默关闭修复:亲缘矩阵多源解析)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | 重写 `_germplasm_pedigree` 多源级联(① 规范化名称反查显式系谱 → ② tree FK 兜底唯一一致 → ③ founder;BFS 祖先展开去重;返回 (pedigree, coverage));`mating_recommend` 加 kinship_status/kinship_warning/kinship + 逐对「亲缘未解析(r 按 0 计)」旗标 |
|
||
| `Temp/claude/e2e_mating_kinship_20260805.py` | 近交惩罚静默关闭修复探针(14 组断言,运行后自动清理) |
|
||
|
||
### 新增/修改文件(2026-08-05 EBV 回退方法学修复:direct 优先 + 子代测验降权)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `mating_recommend` EBV 回退重写——direct 优先(有 direct 绝不被树级值污染);回退显式标注 progeny + `_EBV_SOURCE_FACTOR` 降权 0.5 参与打分(`mid=(f_a·ebv_a+f_b·ebv_b)/2`);双亲均缺直接值的子代树剔除(防双侧等权重复计);记 n_progeny/n_combos;返回体加 `candidate_ebv` + `ebv_source.coverage` + 逐对旗标 |
|
||
| `Temp/claude/e2e_mating_ebv_20260805.py` | EBV 回退方法学修复探针(5 组断言,运行后自动清理) |
|
||
|
||
### 新增/修改文件(2026-08-05 数据质量离群值方向语义错位修复:同向=精英 / 反向=疑似错误)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `data_quality_report` 方向感知分流——取 `trait_row.direction`(desc/None→`desirable_high=True` 高值优;asc→False);IQR/MAD 命中的株按偏离侧双通道分类(`is_high=v>med`、`is_elite=is_high==desirable_high`):同向→`extreme_candidates`(class=extreme_candidate)/ 反向→`outliers`(class=outlier);返回体加 `direction` + `extreme_candidates` + `summary.n_extreme_candidates`;`has_warning/n_outliers/outlier_rate` 语义收紧为疑似录入错误计数 |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 数据质量 tab 改双表——「极值候选(精英)」success 标签表 + 「疑似录入错误」danger 标签表 + 选育方向指示条 + 无错误绿色 info alert(提示文案改方向语义) |
|
||
| `Temp/claude/e2e_data_mating_gain_20260804.py` | A6 探针 [1] 扩展——17 株(15 正常 + 精英高值 16.0 + 错误低值 2.0):精英进 extreme_candidates/class=extreme_candidate/side=high 且不在 outliers;错误进 outliers/class=outlier/side=low;n_extreme_candidates=1 |
|
||
|
||
### 新增/修改文件(2026-08-05 ΔG 投影假设声明 + 工程健壮性打磨:note 假设 + spatial 缺坐标降级 + numpy 收敛)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | ① `genetic_gain` 返回体加 `note` 投影假设声明(环境均值恒定/演示值);② `run_ablup(spatial=True)` 缺坐标株记 `missing_coord_ids` → 剔除表型保留系谱(EBV 由系谱预测)、剔除数写批次 note「缺坐标剔除N株表型(EBV由系谱预测)」、全缺才整批 409、`input_hash` 用剔除后子集;③ 模块级 `import numpy as np`(:24)+ 移除 7 处局部 import;`data_quality_report` 逐株 flag 循环改 numpy 布尔掩码向量化(输出逐字节不变) |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | gain tab 描述区后、轮次表前加 `el-alert type="info"` 展示 `gainData.note`(投影假设边界) |
|
||
| `Temp/claude/e2e_spatial_sparse_20260804.py` | spatial 探针新增强健降级场景——5 株(4 株 2×2 网格 + 1 株无坐标):method=AR1×AR1/train_n=4/note 含剔除标注/5 株均有 EBV 行;全缺坐标仍整批 409;trait 清理含 tD_{P} |
|
||
| `Temp/claude/e2e_data_mating_gain_20260804.py` | A6 探针 [2] 加 note 断言——含「环境均值恒定」且两性状稳定一致 |
|
||
|
||
### 新增/修改文件(2026-08-05 A–F 六项功能级缺口·批1 父本验证 + 近交衰退)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/pollination/service.py` | A1 `_validate_pollen_parent`(create/update 统一:批次采集父本≠授粉父本 409,混合/未声明放行) |
|
||
| `backend/app/api/v1/module_bre/tree/service.py` | A2 `_resolve_parents` 改返回 `(dam, sire, warning)` + create/update 返回体 warning(以显式为准,不阻断) |
|
||
| `backend/app/api/v1/module_bre/tree/schema.py` | `warning: str | None` 只读字段(仅返回体不落库) |
|
||
| `backend/app/api/v1/module_bre/cross_combination/service.py` | A3 `_check_parent_roles` 同质自交 409(create/update 生效亲本统一) |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `InbreedingDepressionIn`(trait_id/trait_code + year/trial_study_id + min_n) |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | `POST /bre/statistics/inbreeding-depression` |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `inbreeding_depression`(F=A_ii−1 + 树级表型均值 → numpy lstsq 回归,F=0 兜底)+ `_DATA_VERSION` v2.22 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `inbreedingDepression` API |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 亲缘/近交 tab 近交衰退区(trait/year + el-alert + el-descriptions + 高 F 株表;el-alert `'error'` 修复 TS2322) |
|
||
| `Temp/claude/e2e_parent_validation_20260805.py` | 批1-A 父本验证探针(10 断言,运行后自动清理) |
|
||
| `Temp/claude/e2e_inbreeding_depression_20260805.py` | 批1-C 近交衰退探针(4 断言,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.22 版本行 + §8.32 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.22.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.10 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ⑳ + 相关行补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 A–F 六项功能级缺口·批2 GS 家系 CV + 试验设计深度)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/genomic.py` | B `kfold_cv_genomic` 加 `split="random"|"family"` + `family_of`(家系阻塞折、无家系个体自成一族、家系数<k 折叠 warning、单家系边界、输出 n_families;random 逐字节不变) |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `AnovaIn.block`(RCBD 区组校正开关)+ `TrialDesignIn`(trial_study_id/design_type/seed) |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | `POST /bre/statistics/trial-design` + run_anova 透传 block |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `run_cv` 加 split 透传 + GS family_of 构建 + note 记 n_families;`trial_design` RCBD 生成器(random.Random(seed) 洗牌 + case() 批量落库);`run_anova` 加 block 分支(solve_rcbd);`_DATA_VERSION` v2.23 |
|
||
| `backend/scripts/breeding_stats/anova.py` | F2 `solve_rcbd`(RCBD 双因素 Type I 顺序,SS_group/SS_block/SS_error + f_block/p_block + 区组均值;solve 单因素逐字节不变) |
|
||
| `backend/app/api/v1/module_bre/trial_study_entry/model.py` | F1 `block_no` 列(可空 integer) |
|
||
| `backend/sql/weld_trial_study_entry.sql` | F1 `ALTER TABLE bre_trial_study_entry ADD COLUMN IF NOT EXISTS block_no integer`(幂等) |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `runAnova` 加 block + `trialDesign()` + `TrialDesignResult` |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | ANOVA tab 重构(生成 RCBD 设计工具条 + 设计区组表 + anovaBlock checkbox + 区组均值/block 结果 v-if) |
|
||
| `Temp/claude/e2e_trial_design_20260805.py` | 批2-F 探针(5 组断言,运行后自动清理) |
|
||
| `Temp/claude/e2e_gs_family_cv_20260805.py` | 批2-B 探针(5 组断言,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.23 版本行 + §8.33 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.23.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.11 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ㉒ + 相关行补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 A–F 六项功能级缺口·批3 OCS 最优贡献选择 + MABC 标记辅助回交)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | D `_proj_simplex`/`_solve_ocs` + `ocs`(投影梯度,A=pedigree+rmat 组装,vs_top_n 对比);共享 helper `_candidate_ebv_map` 抽取(mating_recommend 内联原样提取,direct/progeny 降权 0.5/双侧去重保留);E `_pure_homologous` + `mabc_progress`(前景 `_mas_hit_map` + 背景恢复率 + `_BC_LADDER` 晋级建议);`_DATA_VERSION` v2.24 |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | `POST /bre/statistics/ocs` + `POST /bre/statistics/mabc-progress` |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `OcsIn`(candidate_germplasm_ids/n_select/lam/prediction_id)+ `MabcIn`(candidate_tree_ids/foreground_panel_ids/background_panel_ids/recurrent_parent_tree_id/foreground_min_hits/generation/background_target)均 extra="ignore" |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `ocs()` + `mabcProgress()` API |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 「选配推荐」tab OCS 运行区(n_select + λ 滑杆 + contribution 表 + vs_top_n 对比)+ 独立「回交 MABC」tab(面板/轮回亲本/候选树 + 参数 + 逐株结果 + recommended 降序表) |
|
||
| `Temp/claude/e2e_ocs_20260805.py` | 批3-D OCS 探针(17 断言,运行后自动清理;λ 梯度/退化/partial 告警/三 409) |
|
||
| `Temp/claude/e2e_mabc_20260805.py` | 批3-E MABC 探针(23 断言,运行后自动清理;前景/背景复算/reason/童期/六 409) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.24 版本行 + §8.34 台账 |
|
||
| `doc/桃育种系统模块扩展需求规格.v2.24.md` | 冻结快照 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.12 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | header ㉓ + 相关行补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 近交衰退两处正确性修复:方向感知 + 深层系谱)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `inbreeding_depression` 方向感知检测(`desirable_high=direction!="asc"`,asc 衰退=slope>0 且 t≥+1.645,interpretation 方向化)+ 深层系谱 F(复用 `_germplasm_pedigree` BFS + 树节点 + 未解析 founder 兜底;`_germplasm_pedigree` 本体零改动) |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | 近交衰退提示文案方向化(「高优性状显著负斜率 / 低优性状(如病指)显著正斜率 = 近交衰退」) |
|
||
| `Temp/claude/e2e_inbreeding_depression_20260805.py` | 批1-C 近交衰退探针扩展 4→6 组断言(新增 [4] asc 病指方向感知 + [5] 深层系谱 F 多世代;原 [1][2][3][x] 保持) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | §8.35 跟进台账 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.13 跟进 + 文件清单/备份/复跑 |
|
||
|
||
### 新增/修改文件(2026-08-05 分子亲本验证 + 试验设计深度·批4)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/genotype_call/service.py` | `mendelian_check`(子代 vs 声明亲本 union 规则、跨数据集亲本基因型解析、no_declared_parents/missing_parent_genotype 状态、incompatible_markers 明细)+ `_allele_set` 复用 + import TreeModel |
|
||
| `backend/app/api/v1/module_bre/genotype_call/controller.py` | `GET /bre/genotype_call/mendelian/check`(Auth `module_bre:genotype_call:query`,Query dataset_id + compat_threshold=0.98,镜像 fingerprint/check) |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `trial_design` 分派 rcbd/augmented/alpha(rcbd 逐字节不变)+ `_trial_design_augmented`(对照 anchoring/新品系 round-robin/对照 block_no 不落库)+ `_trial_design_alpha`(平方闭式格子 + 一般贪心可分解 + `_is_prime` + balance_warning + block_no 复合编码)+ `_DATA_VERSION` v2.25 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `TrialDesignIn` 加 `check_germplasm_ids: list[int]=[]` / `block_size: int\|None` / `reps: int\|None`(extra="ignore")+ design_type 描述改 rcbd/augmented/alpha |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | trial_design 透传三新参 + summary 更新「RCBD/增广/α-格子(落库 block_no)」 |
|
||
| `frontend/web/src/api/module_bre/genotype_call.ts` | `mendelianCheck()` + `GenotypeCallMendelianParams/Result/Tree/IncompatMarker` 类型 |
|
||
| `frontend/web/src/views/module_bre/genotype_call/index.vue` | 工具栏「孟德尔/亲本一致性」按钮 + FaDialog(dataset select + compat_threshold + summary 计数 + trees 表 tree_no/dam/sire/informative/rate/flag/incompatible_markers 展开) |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `trialDesign` design_type 枚举扩 augmented/alpha + check_germplasm_ids/block_size/reps + `TrialDesignResult` 加 checks/n_new_entries/n_checks/check_reps/block_size/reps/balance_warning + blocks 联合类型 |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | DESIGN_TYPE_LABELS 补 增广/α-格子 + 条件参数(augmented 对照多选 / alpha block_size+reps)+ α-格子平衡性 el-alert + alpha 块渲染「重复{rep}·块{blk}」 |
|
||
| `Temp/claude/e2e_mendelian_check_20260805.py` | 批4-A 探针(8 断言:跨数据集解析/alien 等位/rate/状态/空数据集零值,运行后自动清理) |
|
||
| `Temp/claude/e2e_trial_design_ext_20260805.py` | 批4-B 探针(19 断言:增广/平方格子/部分 r/非素数告警/一般贪心/四 409,运行后自动清理) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.25 版本行 + §8.36 台账 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.14 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | 相关行补注(分子育种 mendelian + 试验设计行增广/α-格子) |
|
||
|
||
### 新增/修改文件(2026-08-05 批5 区组随机效应 + 孟德尔落库隔离 + 统计引擎数值校验)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/blup.py` | `solve` 加 `block` 参数分派新 `_solve_block`(区组第二随机效应,镜像 `_solve_gxe`)+ `ENGINE_VERSION` 1.5.0 |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `run_ablup` block 开关 + block 分支(block_no 读取/降级剔除/≥2 区组 409)+ 互斥(block×gxe/gxr/spatial)+ `data_quality_report` dataset_id 可选 + mendelian 段 + `_excluded_tree_ids` 系谱消费方断链(_build_pedigree/run_ablup/inbreeding/kinship/cv/_germplasm_pedigree)+ `_DATA_VERSION` v2.26 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | `RunAblupIn.block` + `DataQualityIn.dataset_id` |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | run_ablup block 透传 + data-quality dataset_id 透传 |
|
||
| `backend/app/api/v1/module_bre/genotype_call/model.py` | `MendelianCheckModel`→`bre_mendelian_check` + `MendelianCheckTreeModel`→`bre_mendelian_check_tree`(FK CASCADE) |
|
||
| `backend/app/api/v1/module_bre/genotype_call/service.py` | 纯计算核心抽共享 `_compute_mendelian` + 新 `run_mendelian_check`(落库 + flag upsert 隔离/未 flag 清除,可逆) |
|
||
| `backend/app/api/v1/module_bre/genotype_call/controller.py` | 新 `POST /bre/genotype_call/mendelian/check/run`(Auth edit,GET 只读预览保留) |
|
||
| `backend/app/api/v1/module_bre/tree/model.py` | `TreePedigreeExclusionModel`→`bre_pedigree_exclusion`(tree_id 唯一) |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | `RunAblupPayload.block` + `DataQualityPayload.dataset_id` |
|
||
| `frontend/web/src/api/module_bre/genotype_call.ts` | `mendelianCheckRun` + `GenotypeCallMendelianRunResult`(check_id/isolated/cleared) |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | GxE tab block 开关 + 互斥 + 数据质量 tab dataset 选择器 + mendelian 段(flag alert + 隔离树表) |
|
||
| `frontend/web/src/views/module_bre/genotype_call/index.vue` | 孟德尔对话框主按钮改 POST run + check_id/隔离树数展示 |
|
||
| `Temp/claude/e2e_ablup_block_20260805.py` | 批5-A 探针(6 场景:已知 σ²block 恢复/409 门禁/互斥/降级/无归零警告) |
|
||
| `Temp/claude/e2e_mendelian_persist_20260805.py` | 批5-B 探针(ok=19 fail=0:落库/隔离断开 EBV/可逆清除/data-quality 段/只读零回归) |
|
||
| `Temp/claude/e2e_stats_numerics_20260805.py` | 批5-C 探针(ok=101 fail=0:全量统计引擎逐段 ground-truth 真值) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.26 版本行 + §8.37 台账 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.15 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | 相关行补注(孟德尔落库隔离 + block 随机效应 + 统计引擎数值校验) |
|
||
|
||
### 新增/修改文件(2026-08-05 批6 规划↔目标↔试验 可追溯性闭环)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/sql/weld_plan_trace.sql` | 幂等 ALTER 三列 + FK:bre_target.plan_id、bre_trial.plan_id、bre_trial.target_id(均可空) |
|
||
| `backend/app/api/v1/module_bre/target/model.py` | `TargetModel.plan_id` + relationship |
|
||
| `backend/app/api/v1/module_bre/target/schema.py` | `TargetCreateSchema/TargetUpdateSchema.plan_id` 透传 |
|
||
| `backend/app/api/v1/module_bre/target/service.py` | get_list outerjoin 解析 `plan_name` + create 父校验(坏 plan_id 409)+ delete assert_no_children |
|
||
| `backend/app/api/v1/module_bre/trial/model.py` | `TrialModel.plan_id`/`target_id` + 双 relationship |
|
||
| `backend/app/api/v1/module_bre/trial/schema.py` | 双字段透传 |
|
||
| `backend/app/api/v1/module_bre/trial/service.py` | get_list 解析 `plan_name`+`target_name` + create 双父校验 + delete assert_no_children |
|
||
| `backend/app/api/v1/module_bre/plan/service.py` | 新 `trace(plan_id)`(目标链/试验链/软删过滤/totals)+ delete assert_no_children |
|
||
| `backend/app/api/v1/module_bre/plan/controller.py` | 新 `GET /bre/plan/trace/{id}` |
|
||
| `frontend/web/src/api/module_bre/plan.ts` | `PlanTrace` 类型 + `getPlanTrace` |
|
||
| `frontend/web/src/api/module_bre/target.ts` | `getTargetOptions` |
|
||
| `frontend/web/src/views/module_bre/target/index.vue` | 「所属计划」select + 表格/详情列 |
|
||
| `frontend/web/src/views/module_bre/trial/index.vue` | 「所属计划/目标」select + 表格/详情列 |
|
||
| `frontend/web/src/views/module_bre/plan/index.vue` | 「追溯」行操作弹窗(ElCollapse 目标链/试验链) |
|
||
| `Temp/claude/e2e_plan_trace_20260805.py` | 批6 探针(17 断言:目标链/试验链/totals/软删/孤目标/父校验/删除守卫/标签解析) |
|
||
| `Temp/claude/e2e_audit_20260805.py` | 残留检查限定 `entity_type=='bre_target'`(跨表撞 id 误报根治) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.27 版本行 + §8.38 台账 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.16 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | ㉖ 批6 可追溯性闭环补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 批7 统计引擎全量十模块 golden 复查·系谱键空间错位修复)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | 新增共享 helper `_tree_individual_keys`(int→`"t{id}"` 对齐系谱键空间)+ 四个调用点收口(`_genetic_corr_matrix`/`_smith_hazel_index` mtblup 分支/`run_genetic_corr`/`run_type_b_heredity`)+ `_DATA_VERSION` v2.28 |
|
||
| `backend/app/api/v1/module_bre/genotype_call/service.py` | `GENOTYPE_DATA_VERSION` v2.28 |
|
||
| `Temp/claude/e2e_rg_golden_20260805.py` | 批7 探针(ok=21 fail=0:type_b 分裂家系 golden + correlation 平衡 golden + 分裂家系 discriminator + str/int 键诊断;含 exit-code 通道修复 `fail==0`) |
|
||
| `Temp/claude/e2e_spatial_sparse_20260804.py` | 版本断言 v2.27→v2.28(×2) |
|
||
| `Temp/claude/e2e_statsflow_20260805.py` | 版本断言 v2.27→v2.28 |
|
||
| `Temp/claude/e2e_prediction_rigor_20260804.py` | 版本断言 v2.27→v2.28 |
|
||
| `Temp/claude/e2e_mendelian_persist_20260805.py` | 版本断言 v2.27→v2.28 |
|
||
| `Temp/claude/http_v228.py` | 批7 HTTP 核验(type-b-heredity 分裂家系 r_B>0.5/n_common=0 + genetic-corr/run 分裂家系 r_g>0.5 + 平衡 r_g>0.65) |
|
||
| `doc/桃育种系统模块扩展需求规格.md` | v2.28 版本行 + §8.39 台账 |
|
||
| `doc/桃育种系统统计引擎实施记录.md` | §18.17 落地 + 文件清单/备份/复跑 |
|
||
| `doc/桃育种系统规划对照总表.md` | ㉗ 批7 系谱键空间错位修复补注 |
|
||
|
||
### 新增/修改文件(2026-08-05 回归基建:统一回归 + 高风险模块 tc 套件,无后端代码改动)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `run_regression.py` | 统一回归驱动:顺序串跑 Temp/claude/e2e_*.py(排除 e2e_probe*)+ backend/scripts/test_bre_analysis_*_tc.py = 63 测试,每测试独立子进程 log 到 regression_logs/,EXIT 汇总;DPB_PYTHON 覆盖解释器;utf-8 reconfigure 防 GBK;过滤器 + --keep-logs |
|
||
| `backend/scripts/test_bre_analysis_ssgblup_tc.py` | 正式 tc 套件(ok=14):GBLUP/ssGBLUP H⁻¹ 拼接判别——非基因型株 GBLUP EBV=0 / ssGBLUP EBV≠0(算偏当正常输出的同款隐患判别) |
|
||
| `backend/scripts/test_bre_analysis_ocs_tc.py` | 正式 tc 套件(ok=23):OCS 投影梯度 golden(Σc/c≥0/λ 单调/c'Ac/λ=0 退化/409+422) |
|
||
| `backend/scripts/test_bre_analysis_mabc_tc.py` | 正式 tc 套件(ok=24):MABC 前景/背景恢复率/晋级/童期 C6/422+409 |
|
||
| `backend/scripts/test_bre_analysis_mendelian_tc.py` | 正式 tc 套件(ok=9):孟德尔 POST run 落库/隔离注册表/阈值 0.0 可逆/GET 零回归(URL 下划线 genotype_call + 启动残留预清理 _wipe + 隔离验证时序) |
|
||
| `Temp/claude/backup_test_rigor_20260805/` | 备份镜像(root/run_regression.py + backend/scripts 4 tc 套件最新修复版) |
|
||
|
||
### 新增/修改文件(2026-08-05 回归基建 2:分析模块 tc 补齐 + pytest 接入 + run_ci,无后端代码改动)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/test_bre_analysis_genetic_corr_tc.py` | 正式 tc 套件(ok=19):平衡 3 性状 r_g 判别 + 分裂家系 r_g(S1,S2)>0.5 且 n_common=0(独立种子 SEED_S=3) |
|
||
| `backend/scripts/test_bre_analysis_type_b_tc.py` | 正式 tc 套件(ok=18):Type-B 3 站点分裂家系 r_B>0.5 且 n_common=0(复刻 tY-first rng 序 → 0.990)+ 三 409 |
|
||
| `backend/scripts/test_bre_analysis_inbreeding_tc.py` | 正式 tc 套件(ok=44):近交衰退方向感知(衰退/无/上升)+ deep 系谱 F=0.125 + min_n insufficient + 422/409 |
|
||
| `backend/scripts/test_bre_analysis_trial_design_tc.py` | 正式 tc 套件(ok=25):增广(对照 block_no=None 不落库)+ α-格子(平方 λ≤1/非素数告警/一般贪心)+ block_no=rep*100+block DB 读回 + 四 409 |
|
||
| `backend/scripts/test_bre_analysis_stability_tc.py` | 正式 tc 套件(ok=16):AMMI/FW b 斜坡 + flag_stable + ASV rank + engine_version 落库 + year 维度 + 二 409 |
|
||
| `backend/tests/test_stat_analysis_tc.py` | pytest 包装层:9 套 tc @pytest.mark.pg + subprocess 串跑 + skipif 探测真实 PG16+Redis(protocol=2)+ env 显式构建(剥 conftest 污染、解析 .env.dev、TC_CI_* 覆盖) |
|
||
| `backend/pyproject.toml` | `[tool.pytest.ini_options]` 注册 `pg` marker(消 PytestUnknownMarkWarning) |
|
||
| `backend/tests/conftest.py` | 加 `collect_ignore_glob=["../scripts/test_*.py"]` 防 pytest 收集独立脚本污染 sqlite 环境 |
|
||
| `run_ci.py` | 本机 CI stage:step 0 探测 PG16+Redis(失败指引+exit≠0)→ step 1 `pytest -m pg` → step 2 EXIT=0「CI 全绿」,日志 Temp/claude/ci_logs/ |
|
||
| `Temp/claude/backup_analysis_tc2_20260805/` | 备份镜像(root/run_ci.py + backend/scripts 9 tc 套件 + backend/tests/test_stat_analysis_tc.py + pyproject/conftest diff) |
|
||
|
||
### 新增/修改文件(2026-08-05 O2–O4 统计方法学广度,v2.29)
|
||
|
||
| 文件 | 说明 |
|
||
|---|---|
|
||
| `backend/scripts/breeding_stats/genomic.py` | ENGINE_VERSION 1.4.0:`solve_rrblup`(岭回归逐标记 + marker effects + 对偶)+ `solve_bayesb`(BayesB Gibbs,确定性 seed 可复现)+ `kfold_cv_genomic` dosage/markers 分派 rrblup/bayesb |
|
||
| `backend/app/api/v1/module_bre/statistics/service.py` | `_values_by_tree_env` env_dim=stage 分支(`coalesce(obs.stage, TraitModel.stage)` 分组)+ `run_type_b_heredity` env_dim 校验扩 stage + `run_gblup` method 扩 rrblup/bayesb + seed 透传 + `run_cv` GS 分支 dosage/seed 透传 + `_smith_hazel_index` restricted 投影(Kempthorne-Nordskog 闭式解)/economic_weights + `selection_index` 透传 + `cv_detail` 补 `cv_result_id`(顺手修复)+ `_DATA_VERSION` v2.29 |
|
||
| `backend/app/api/v1/module_bre/statistics/schema.py` | TypeBIn.env_dim 描述扩 stage + GblupRunIn/CvRunIn method 描述扩 rrblup/bayesb + seed + SelectionIndexIn.method 描述扩 restricted + `restricted_traits`/`economic_weights` |
|
||
| `backend/app/api/v1/module_bre/statistics/controller.py` | run_gblup 透传 seed + selection_index 透传 restricted_traits/economic_weights |
|
||
| `backend/app/api/v1/module_bre/genotype_call/service.py` | `GENOTYPE_DATA_VERSION` v2.29 |
|
||
| `frontend/web/src/views/module_bre/statistics/index.vue` | Type-B env_dim 下拉加 stage + GBLUP/CV method radio 加 RRBLUP/BayesB + seed 输入 + 指数页 restricted 单选/restricted_traits 多选/每性状经济权重输入 + SI_RES 结果表与警示 |
|
||
| `frontend/web/src/api/module_bre/statistics.ts` | selectionIndex/runGblup/runCv method 类型扩 + restricted_traits/economic_weights/seed |
|
||
| `backend/scripts/test_bre_analysis_o234_tc.py` | 正式 tc 套件第 10 套(ok=41):O2 stage 幼成相关 / O3 rrblup+bayesb 落库与对偶可复现 / O4 restricted+economic |
|
||
| `backend/tests/test_stat_analysis_tc.py` | TC_SCRIPTS 注册 `("o234", "test_bre_analysis_o234_tc.py")`(9 → 10 套) |
|
||
| `Temp/claude/e2e_o234_20260805.py` | O2–O4 e2e 探针(19 断言,纯计算 golden + 真实 PG) |
|
||
| `Temp/claude/backup_o234_20260805/` | 备份镜像(后端 service/schema/controller/genomic + 前端 vue/ts + tc + e2e) |
|
||
|
||
### 备份(无 git,批量编辑前手动镜像)
|
||
|
||
- 2026-08-03 引擎改动 → `Temp/claude/backup_gxe_20260803/`
|
||
- 2026-08-04 方向改动(13 文件,按相对路径镜像)→ `Temp/claude/backup_direction_20260804/`
|
||
- 2026-08-04 规范文档 → `Temp/claude/backup_docs_20260804/` + `doc/桃育种系统模块扩展需求规格.v2.2.md`(旧版本快照)
|
||
- 2026-08-04 无性系级指数改动(controller/schema/service/statistics.ts/index.vue/e2e)→ `Temp/claude/backup_clone_index_20260804/`
|
||
- 2026-08-04 配合力交配设计改动(13 文件,按模块相对路径镜像)→ `Temp/claude/backup_combining_design_20260804/`
|
||
- 2026-08-04 统计严谨·MLOps 复现性改动(weld SQL×2 + statistics 三件套 + blup.py + rootstock 三件套 + 前端四文件 + 三探针)→ `Temp/claude/backup_rigor_20260804/`
|
||
- 2026-08-04 组合得失漏斗改动(`weld_combination_funnel.sql` + statistics service/controller + e2e)→ `Temp/claude/backup_combination_funnel_20260804/`
|
||
- 2026-08-04 分子育种改动(weld SQL + bre_menu.sql + module_bre 四模块五件套 + __init__.py + 前端四 api 四页面 + e2e)→ `Temp/claude/backup_molecular_20260804/`
|
||
- 2026-08-04 精修项四连发改动(DUS 模块六件套 + statistics 四件套 + blup.py + weld/种子/菜单 SQL×3 + 前端 dus/statistics 两页两 api + e2e_refine)→ `Temp/claude/backup_refine_20260804/`
|
||
- 2026-08-04 六项能力完善改动(weld_advanced.sql + statistics 四件套 + dus 六件套 + trait_observation 三件套 + mtblup/genomic/stability/fdist/blup 求解器 + 前端 statistics/dus/tree_evaluation 三页四 api(含 trait_observation.ts)+ 六探针 + 文档四件,37 文件)→ `Temp/claude/backup_advanced_20260804/`
|
||
- 2026-08-04 砧木×接穗随机互作改动(blup.py + statistics 三件套 + 前端 statistics.ts/index.vue + e2e_gxr)→ `Temp/claude/backup_gxr_20260804/`
|
||
- 2026-08-04 基因组选择实证严谨性改动(genomic.py + statistics 三件套 + 前端 statistics.ts/index.vue + e2e_gblup_cv + 文档三件)→ `Temp/claude/backup_gblup_cv_20260804/`
|
||
- 2026-08-04 现代桃育种领域覆盖改动(germplasm 三件套 + cross_combination 二件套 + bre_disease_chilling_traits.sql + 前端 germplasm/cross_combination 两页 + germplasm.ts + e2e_s_allele + 文档三件 + 规格快照 v2.13)→ `Temp/claude/backup_s_allele_traits_20260804/`
|
||
- 2026-08-04 GWAS/QTL/MAS 闭环改动(gwas.py + weld_gwas.sql + statistics 四件套 + bre_menu.sql + 前端 gwas.ts/index.vue + e2e_gwas + 文档三件 + 规格快照 v2.14)→ `Temp/claude/backup_gwas_20260804/`
|
||
- 2026-08-04 九缺口补齐改动(blup/gwas/genomic + statistics 四件套 + genotype_call + weld_mas_semantics.sql + 前端 statistics/gwas 两页两 ts + e2e×3 + 文档三件 + 规格快照 v2.15)→ `Temp/claude/backup_complete_20260804/`
|
||
- 2026-08-05 十二项真缺口补齐改动(批1 blup/mtblup/gwas 引擎 + statistics;批2 field_operation/observation/breeding_report/analysis_dataset 四模块五件套 + 前端四页四 ts;批3 audit/alert/brapi/sequence 模块 + number_gen + ap_scheduler + backup_job + pg_backup/pg_restore.sh + init_app + weld SQL 多枚 + 前端 alert 页/statistics;e2e×3 + 文档三件 + 规格快照 v2.16)→ `Temp/claude/backup_gaps3_20260804/`
|
||
- 2026-08-05 桃育种业务流全面完善改动(批A field_operation/observation/seed_lot/seed_treatment/tree/trait_observation + weld_busflow.sql + bre_yield_phenology_traits.sql;批B statistics service/controller/schema/model + bre_type_b_result;批C echarts.ts + statistics/observation/field_operation 三 ts + statistics/observation/field_operation/stage_phenotype/StageView 五 vue;e2e×2 + smoke + 文档三件 + 规格快照 v2.17)→ `Temp/claude/backup_busflow3_20260805/`
|
||
- 2026-08-05 世代闭环改动(selection_result/service.py 晋级落谱 + 探针)→ `Temp/claude/backup_pedigree_closure_20260805/`
|
||
- 2026-08-05 近交惩罚静默关闭修复改动(statistics/service.py 亲缘多源解析 + 探针)→ `Temp/claude/backup_kinship_20260805/`
|
||
- 2026-08-05 EBV 回退方法学修复改动(statistics/service.py 打分降权 + 探针)→ `Temp/claude/backup_ebv_20260805/`
|
||
- 2026-08-05 数据质量离群值方向语义修复改动(statistics/service.py 方向分流 + 前端 statistics/index.vue 双表 + A6 探针 + 文档三件 + 规格快照 v2.20)→ `Temp/claude/backup_dq_semantics_20260805/`
|
||
- 2026-08-05 ΔG 投影假设 + 工程健壮性打磨改动(statistics/service.py note 假设 + spatial 降级 + numpy 收敛向量化 + 前端 statistics/index.vue gain alert + spatial/A6 探针 + 文档三件 + 规格快照 v2.21)→ `Temp/claude/backup_dq_robust_20260805/`
|
||
- 2026-08-05 回归基建改动(run_regression.py + backend/scripts 4 tc 套件,无后端代码改动)→ `Temp/claude/backup_test_rigor_20260805/`
|
||
- 2026-08-05 A–F 六项缺口·批1 父本验证 + 近交衰退改动(pollination/tree/cross_combination service + tree schema + statistics 三件套 + 前端 statistics.ts/index.vue + e2e×2 + 文档三件 + 规格快照 v2.22)→ `Temp/claude/backup_parent_validation_20260805/`
|
||
- 2026-08-05 A–F 六项缺口·批2 GS 家系 CV + 试验设计深度改动(genomic.py + anova.py + statistics 三件套 + trial_study_entry model + weld_trial_study_entry.sql + 前端 statistics.ts/index.vue + e2e×2 + 文档三件 + 规格快照 v2.23)→ `Temp/claude/backup_gs_family_trial_design_20260805/`
|
||
- 2026-08-05 A–F 六项缺口·批3 OCS + MABC 改动(statistics service/controller/schema 三件套 `_candidate_ebv_map` 抽取 + ocs + mabc_progress + 前端 statistics.ts/index.vue OCS 运行区 + MABC tab + e2e×2 + 文档三件 + 规格快照 v2.24)→ `Temp/claude/backup_ocs_mabc_20260805/`
|
||
- 2026-08-05 近交衰退正确性修复改动(statistics/service.py 方向感知 + 深层系谱 + 前端 statistics/index.vue 提示文案 + e2e_inbreeding_depression 扩展 + 文档二件 规格/实施记录)→ `Temp/claude/backup_inbreeding_fix_20260805/`
|
||
- 2026-08-05 分子亲本验证 + 试验设计深度·批4 改动(genotype_call 二件套 `mendelian_check` + statistics 三件套 `trial_design` augmented/alpha 分派 + 前端 genotype_call/statistics 两页两 ts + e2e×2 + 文档三件 规格/实施记录/对照总表,14 文件按相对路径镜像)→ `Temp/claude/backup_mendelian_design_20260805/`
|
||
- 2026-08-05 批5 区组随机效应 + 孟德尔落库隔离 + 统计引擎数值校验改动(blup.py + statistics 四件套 + genotype_call 三件套 + tree/model.py + 前端 statistics/genotype_call 两页两 ts + 三探针 + 文档三件,18 文件按相对路径镜像)→ `Temp/claude/backup_block_mendelian_numerics_20260805/`
|
||
- 2026-08-05 批6 规划↔目标↔试验 可追溯性闭环改动(weld_plan_trace.sql + target 三件套 + trial 三件套 + plan 二件套 + 前端 plan/target/trial 三页三 ts + 新探针 e2e_plan_trace + 文档三件,按相对路径镜像)→ `Temp/claude/backup_plan_trace_20260805/`
|
||
- 2026-08-05 批7 系谱键空间错位修复改动(statistics/service.py `_tree_individual_keys` + 四调用点 + genotype_call/service.py 版本 + 新探针 e2e_rg_golden + http_v228 + 版本断言探针×4 + 文档三件,按相对路径镜像)→ `Temp/claude/backup_keyspace_20260805/`
|
||
|
||
### 复跑验证
|
||
|
||
```bash
|
||
# 后端(GBK 控制台需 UTF-8,worship() ASCII 画报会崩)
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python main.py run --env=dev
|
||
|
||
# 探针(真引擎 + spy 捕获 kwargs / 真引擎直跑)
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxe_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_direction_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_clone_index_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_combining_design_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_rootstock_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_combination_funnel_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_refine_20260804.py
|
||
|
||
# 砧木×接穗随机互作(G×R)探针(真引擎直跑,运行后自动清理):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py
|
||
|
||
# 基因组选择(GS)专用 k-fold CV 探针(真引擎直跑,运行后自动清理)+ GBLUP 回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
|
||
|
||
# GWAS/QTL/MAS 闭环探针(真引擎直跑 7 段断言,运行后自动清理)+ GBLUP/ssGBLUP 回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
|
||
|
||
# 九缺口补齐三探针(真引擎直跑,运行后自动清理):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
|
||
# 九缺口补齐:MAS 面板语义三列(幂等,可重跑):
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_mas_semantics.sql
|
||
|
||
# 组合得失漏斗视图(幂等,可重跑):
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_combination_funnel.sql
|
||
# 精修项三 SQL(幂等,可重跑;bre_dus_seed 依赖 bre_dus_descriptor 已由 create_all 建出):
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_refine.sql
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/bre_dus_seed.sql
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/bre_menu_refine.sql
|
||
# 六项能力完善:weld_advanced(幂等,2 表 + 2 列 + 1 jsonb;新表 bre_genetic_corr_result/bre_stability_result 由 create_all 建出):
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_advanced.sql
|
||
# GWAS/QTL/MAS:weld_gwas(幂等,5 新表 bre_gwas_result/bre_gwas_snp/bre_qtl/bre_mas_panel/bre_mas_panel_marker 兜底;正常已由 create_all 建出)+ 900214 菜单翻转:
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_gwas.sql
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/bre_menu.sql
|
||
# 六探针(真引擎直跑,运行后自动清理):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_stability.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_stage.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_mtblup.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_dus.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_mlops.py
|
||
# 十二项真缺口:批1/批2/批3 探针(真引擎直跑,运行后自动清理)+ 全量回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_refine_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
|
||
# 桃育种业务流全面完善:批A/批B 探针(真引擎直跑,运行后自动清理)+ 批C HTTP smoke + 全量回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_busflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/smoke_busflow_c_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_refine_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
|
||
# 世代闭环:晋级落谱探针(真引擎直跑 11 组断言,运行后自动清理)+ 晋级主线回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_pedigree_closure_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
|
||
# 近交惩罚静默关闭修复:亲缘多源解析探针(真引擎直跑 14 组断言,运行后自动清理)+ A6 亲缘回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
|
||
|
||
# EBV 回退方法学修复:direct 优先/子代测验降权/双侧去重探针(真引擎直跑 5 组断言,运行后自动清理)+ 亲缘/批次回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
|
||
# 数据质量离群值方向语义修复:A6 探针(真引擎直跑,运行后自动清理)+ 回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
|
||
# ΔG 投影假设 + 工程健壮性打磨:spatial 降级场景探针(真引擎直跑,运行后自动清理)+ A6 note 断言 + 回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
|
||
# A–F 六项缺口·批1 父本验证 + 近交衰退:双探针(真引擎直跑,运行后自动清理)+ 全量回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
|
||
# A–F 六项缺口·批2 GS 家系 CV + 试验设计深度:双探针(真引擎直跑,运行后自动清理)+ 全量回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_busflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
|
||
# A–F 六项缺口·批3 OCS + MABC:双探针(真引擎直跑,运行后自动清理)+ 全量回归(含 _candidate_ebv_map 抽取后 mating/audit 双核对):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_busflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_b8_seed_lot.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_audit_fix_20260805.py
|
||
|
||
# 近交衰退正确性修复(6 组断言:方向感知 asc 病指 + 深层系谱多世代 F)+ 全量回归(13 套):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
|
||
|
||
# A–F 六项缺口·批4 分子亲本验证 + 试验设计深度:双探针(真引擎直跑,运行后自动清理)+ 全量回归(rcbd 路径零变化 + 13 套):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_check_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_ext_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py
|
||
```
|
||
|
||
# 批5 区组随机效应 + 孟德尔落库隔离 + 统计引擎数值校验:三探针(真引擎直跑,运行后自动清理)+ 27 套全量回归(含 gxe/gxr/mendelian_check/trial_design 零变化):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ablup_block_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_persist_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_stats_numerics_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_check_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_ext_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxe_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
|
||
```
|
||
|
||
# 批6 规划↔目标↔试验 可追溯性闭环:新探针(真引擎直跑 17 断言,运行后自动清理)+ weld SQL(幂等,可重跑)+ 全量回归:
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_plan_trace_20260805.py
|
||
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_plan_trace.sql
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_plan_trace_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_audit_20260805.py
|
||
|
||
# 批7 统计引擎十模块 golden 复查·系谱键空间错位修复:新探针(真引擎直跑 21 断言,运行后自动清理)+ 回归(版本断言已同步 v2.28):
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_rg_golden_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_mtblup.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_persist_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
|
||
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_persist_20260805.py
|
||
```
|
||
|
||
> **科学正确性收口**:方向标注后,低优性状(裂果率/病害级别/酸度等 asc)在指数、EBV 排行、决策预览、轮次对比中一律按"越小越优"参与,与育种目标语义一致;Smith-Hazel 的 b 符号、加权 Z 的贡献方向均按 direction 归一,不再存在"高 EBV=优"的隐含假设。**可追溯性收口**:bre_plan 不再孤立——plan→target→cross_combination→tree(目标链)与 plan→trial→trial_study→tree(试验链)双链闭合,`GET /bre/plan/trace/{id}` 一查到底;三 FK 均可空,存量孤目标/独立试验不受影响,新数据挂链即可查(渐进式,不强制回填)。
|
||
|
||
# 18.21 前端 TAB 陈旧数据修复:KeepAlive 切回自动重拉真实数据(2026-08-05,前端框架级,无版本变更)
|
||
|
||
> 用户反馈:授粉管理、花粉档案等「第2、3个 TAB」页面,切换过来后列表仍是旧数据,点刷新才变真实数据。根因:`fa-page-content` 默认 KeepAlive 缓存页面,切换 workbar 标签时组件不重新 mounted → `onMounted` 不重跑 → 列表停留旧快照。框架级修复(覆盖全部 useTable 页面,而非逐页打补丁)。
|
||
|
||
**根因链(两层)**:① `hooks/core/useTable.ts` 的 `onActivated` 只置 `tableViewActive=true`(fetch 内 guard 防失活期拉数据),从不主动重拉;`onDeactivated` 又 `cancelRequest()`。KeepAlive 切回 → `data.value` 仍是旧快照。约 30 个 module_bre CRUD 页共用 useTable,仅 3 页有手动 onActivated(tree 的 `refreshData()`、pollination/pollen 的下拉重载),故框架层修一处全覆盖。② **跨实例去重键不含 API 身份**:`globalListNetworkInflight` 的 dedupeKey 仅由 `stableDedupeKeyFromParams(requestParams)` 生成(跳过 undefined 字段),而所有 module_bre 列表页默认参数形状相同(`{page_no:1, page_size:10}`)→ 硬刷新后多个 tab 并发挂载,各页 `onMounted` 并发发请求,**页面 A 复用页面 B 的 in-flight 响应**(字段与 prop 不匹配 → 列表只剩序号列有值,其它列空;这正是用户硬刷新后看到的"只有序号列")。点刷新(`refreshData`)时该 key 已无 in-flight,走自己的 HTTP → 正常。此 bug 既存,但激活重拉后并发概率骤增而被暴露。
|
||
|
||
**改动**:
|
||
1. **`frontend/web/src/hooks/core/useTable.ts`**:新增 `tableActivatedOnce` 标志;`onActivated` 首次(与 mounted 重合)跳过,之后每次恢复激活 → `debouncedGetDataByPage.cancel()` + `clearCache(CLEAR_CURRENT, "恢复激活刷新")` + `getData()`(强制 HTTP 重拉,in-flight 去重仍生效)。守卫 `(immediate || data.value.length > 0)` 保持 `immediate:false` 页面(cronjob 定时页)"不自动加载"语义不变。**另修去重键**:新增 `apiIdentity = apiFn.toString()`,`dedupeKey = \`${apiIdentity}::${stableDedupeKeyFromParams(requestParams)}\``——跨实例去重仅在**同一接口**间合并,不同页面的同形参数不再错配(`globalListNetworkInflight` Map 全局共享,两处 in-flight key 均带上接口身份)。
|
||
2. **`frontend/web/src/views/module_bre/statistics/index.vue`**:抽取 `refreshPageLists()`(onMounted 全部 15 个 load 调用),`onActivated` 经 `pageActivatedOnce` 守卫后续激活重载(统计页多数据区整体刷新)。
|
||
3. **`frontend/web/src/views/module_bre/pollination/index.vue`**:`onActivated` 重载 5 个下拉(cross_combination/plot/personnel/tree/pollen 选项),表格由框架处理。
|
||
4. **`frontend/web/src/views/module_bre/pollen/index.vue`**:`onActivated` 重载采集父本树下拉。
|
||
5. **`frontend/web/src/views/module_bre/tree/index.vue`**:移除冗余手动 `onActivated(() => refreshData())`(由 useTable 框架覆盖,避免双重重拉)。
|
||
|
||
**验证**:`vue-tsc` EXIT=0(无类型回归);vite dev(:5666,base /web)热更新模块均 200 + 关键字符串存在;后端 `/bre/pollination/list` 实测返回字段完整(combination_name/pollination_date 等有值,确认非后端问题);浏览器行为需硬刷新(Ctrl+Shift+R,重建 KeepAlive 缓存与 HMR 旧实例)后实跑确认。备份镜像 `Temp/claude/backup_tab_stale_20260805/`。
|
||
|
||
# 18.22 O1 花期数据消费补强:结构化花期区间 + 配对花期软警示 + 授粉窗口规划(2026-08-06,v2.30)
|
||
|
||
> 用户反馈 O1 花期字段(flowering_period 5 档字典)零消费属真实数据盲点,但定性为 **P1 数据消费补强 + 辅助信息**(非与 S-等位同量级的正确性硬防呆)。拍板三个落地档位:① 花期数据建模升级(结构化区间,前置);② `mating_recommend` 返回体加花期重叠软警示(重叠/错开/需采粉贮藏,**不硬阻断**);③ 授粉窗口规划消费 `bre_pollen`(新端点 `GET /bre/pollen/window-plan`)。花期建模新增列 → `_DATA_VERSION` v2.29 → **v2.30**。
|
||
|
||
**① 花期建模升级(germplasm 双 Date 列)**:`bre_germplasm` 新增 `bloom_start_date`/`bloom_end_date`(Date 可空,年际重复物候——比较/投影时取月日、忽略年份;`flowering_period` 5 档字典保留作粗粒度 fallback)。weld 幂等 SQL(`backend/sql/weld_flowering.sql`)+ 双处版本 bump。连锁全链:model.py / schema(Create+Update)/ service(export mapping_dict + import header_dict + fields 解析 + 模板 header_list)/ 前端 germplasm 表单两个 date-picker、表格列、详情项。**前端设计取舍**:useCrudForm 无提交前 transform hook → 弃 daterange(需 bloomStartRange↔两字段双向映射),改用**两个独立 date 字段**直绑 `bloom_start_date`/`bloom_end_date`(与 acquisition_date 同模式,零转换)。
|
||
|
||
**② mating_recommend 花期软警示**:新模块级 helper `_bloom_overlap(female, male)`(statistics/service.py,`_md()` 月日→年序日 1..366)——优先结构化区间(月日年际比较),缺区间 fallback 到 `_BLOOM_TIER_ORDER` 5 档字典序号(相邻/同档视为重叠)。四态返回 (status, msg):`overlap`「花期重叠,可同期授粉」/ `store`「父本先开花,需采粉贮藏至母本花期授粉」(me_d < fs_d)/ `offset`「母本先开花,父本花期在后,注意母本柱头可授期」(fe_d < ms_d)/ `unknown`「花期未知(缺结构化区间与档位)」。pairs 循环(female=gs[i], male=gs[j] 语义)在 `s_compat` 旁加 `bloom_status`/`bloom_msg`;非重叠三态追加进 flags[](前端红色 tag 自动渲染),overlap 不进 flags——**软警示不硬阻断**。前端 pairs 表加「花期」列(重叠=success tag / 需采粉贮藏·错开=warning tag / 未知=info tag)。
|
||
|
||
**③ 授粉窗口规划(window-plan)**:新端点 `GET /bre/pollen/window-plan?window_start=&window_end=`(controller + service.window_plan,纯计算不落库)。`_project_bloom(g, ref_year)` 把花期投影到窗口起始年:结构化区间按年际月日(桃花期 3-4 月单年窗口假设),缺区间 fallback `_BLOOM_TIER_SPAN`(5 档 → 代表区间,粗粒度标注)。花期种质给花粉覆盖三态 `covered`(整段有批次 `collect<=bs and expiry>=be`)/`partial`/`none`(无覆盖 → n_need_pollen + 提示需采粉贮藏或同期授粉);库存侧给批次窗口状态 `full`(全程覆盖)/`expiring`(窗口内到期)/`entering`(窗口内采集、有效期出窗)/`expired`(窗口前失效)/`not_started`(窗口后采集)。窗口反向 409。前端 pollen 页顶部「授粉窗口规划」卡片:daterange 默认本年度/次年花期(3-4 月在当年、否则次年 03-01~04-30)+ 生成按钮 + 缺粉 alert + 花期覆盖表 + 库存状态表;pollen.ts 加 `getWindowPlan` + `PollenWindowPlan`/`PollenBloomItem`/`PollenInventoryItem`/`PollenLotRef` 类型。
|
||
|
||
**验证**:`e2e_o1_bloom_20260805.py` 探针全过——① CreateSchema→CRUD 双 Date 列落库;② 6 种质 15 对(重叠/错开/需采粉贮藏三类 + 档位 fallback mid×very_early→store + 区间×档位混合对→unknown,flags 仅非重叠进警示);③ 窗口 A(03-05~04-08)花期覆盖三态 covered/partial/none + 档位投影种质、窗口 B(03-10~03-30)库存五态 full/expiring/entering/expired/not_started + 窗口反向 409。`vue-tsc` EXIT=0。全量回归 + `run_ci.py` EXIT=0 零回归。版本连锁:4 e2e 探针(statsflow/spatial_sparse×2/prediction_rigor/mendelian_persist)+ o234 tc 断言 v2.29→v2.30。备份镜像 `Temp/claude/backup_o1_bloom_20260805/`。
|