Files
dpb/doc/桃育种系统模块扩展需求规格.v2.13.md
T
34047007@qq.com b95053c52c init: 初始化 dpb 桃育种系统代码库
前后端 + 后端 FastAPI 全量源码、部署脚本与文档。
2026-08-06 00:17:49 +08:00

1155 lines
160 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 桃育种系统 · 模块扩展需求规格(V2 草案)
> 编制日期:2026-07-28
> 依据:通用育种软件功能清单(用户提供) + 国际成熟方案(BrAPI / BMS·Breedbase / RosBREED / MIAPPE / Crop Ontology / FAO-MCPD / Genesys + `doc\果树所\育种\yz.sql` 真实桃性状 + 现有 14 个 breeding 域
> 状态:**草案,待评审**。字段取值/枚举以「待确认」标注处需与业务方对齐后再落地(遵循"不确定不擅自动手"准则)。
## 版本历史
| 版本 | 日期 | 说明 |
|---|---|---|
| v1.0 | 2026-07-28 | 初稿+复审:14 域对标、新增 7 模块、§8 复审(9 遗漏)、EAV 定稿为混合固定列。BrAPI/MIAPPE/team/库存 待定 |
| v1.1 | 2026-07-28 | 决策落地:① 采纳**直接对齐 BrAPI API**(新增 BrAPI 只读适配层)② 采纳 **MIAPPE 合规****不建 team 模块**(仅数据隔离,不需要,留 RBAC+created_id)④ **库存延后**(暂用报表) |
| v1.2 | 2026-07-28 | 取值决策(用户授权"你来定"):敲定 stage/generation/group_type/design_type 四枚举(§9+ propagation 纳入一期(§3.8);trait 种子建议 yz.sql;字段表补 generation/germplasm_id |
| v1.3 | 2026-07-28 | §8 二次复审落地:① **MET 链路彻底修补**trial_study.block_count + planting.trial_study_id + tree.trial_study_id/block_no + plot.block_no),与库存 `seed_lot` 一并建模,形成 seed_lot→seedling→planting→tree→trial_study 选择强度链(§3.13/§4/§5)② §0 原则1 与混合模型对齐(修订措辞)③ observation/field_operation 改显式 FK(弃多态)④ 补 environment_condition / audit_log / selection_rule / prediction 字段规格(§3.9–§3.12)⑤ tree_evaluation 明确"按 pa_four 扩列"+ 统一性状值视图 ⑥ 补「选择阈值规则」+「批量表型导入」规划 ⑦ 文档计数/枚举对齐修正 |
| v1.4 | 2026-07-28 | 国际基准三轮复审(BrAPI/Breedbase/RosBREED/MIAPPE/Crop Ontology/FAO-MCPD/Genesys)落地:① 新增 `trial_study_entry`entry 清单+entry_numberMET 设计矩阵)② site 补 lat/long/elevation(空间 BLUP/MIAPPE)③ observation 加 `status` 校验态(数据质量)④ trait 加 `ontology_uri`Crop Ontology 对接)⑤ 明确 tree.trial_study_id/block_no 为**派生**(单写点=planting,防双真相漂移)⑥ germplasm 补护照描述符块(FAO-MCPD)⑦ 新增 `genotyping_dataset`+marker.panelGS 训练群体分组)⑧ selection_result 加 `rule_id`(决策闭环)⑨ 补 crossing block 父/母本树(pollination 挂 female/male_tree_id)⑩ experiment_factor / breeding_report / breeding_program 标记延后。详见 §8.6 |
| v1.6 | 2026-07-28 | 第五轮复审(v1.5 自洽+国际盲点)全部采纳:① tree_evaluation 加 trial_study_idA1 核心性状环境键)② planting 粒度=block 级 + entry 跨 block 多 plantingA2)③ 新增 planting_treatment 关联表(A3)④ seed_lot.used_count 明确粒数(A4)⑤ §4 补 tree_photo 行(A5)⑥ tree→germplasm 重复测量聚合 EBVA6)⑦ 国际补强:marker.assembly_version、genotype_call VCF/GP、trial_study.season、observation.validated_by/date/unit、trait.method_uri/scale_uri、planting.propagation_id、observationUnit level、kinship A 矩阵、selection_rule EBV 阈值、breeding_program 自由文本说明 ⑧ selection_result.trial_study_id、新表数据权限约束(并补齐 v1.5 因替换异常遗漏的 §3.14/treatment 行/used_count)。详见 §8.8 |
| v1.7 | 2026-07-28 | V2.11 方案书《统计分析决策支持》逐条对照评估落地(用户确认报告一期必须):① **`breeding_report` 确认进一期**(P2,年度 Word/PDF 报告实体+生成服务,不再仅只读端点,原 v1.4 延后项移除)② **`breeding_prediction_value` 值表前移 V1.1**(与 V1.1 统计引擎同期持久化 EBV,支撑年遗传趋势图/双轨选择/亲本单株决策;仅 GS 模型训练留 V2.0)③ `tree_evaluation``crop_load`(坐果量评级 1/2/3 协变量,降果实性状环境误差,专册 1.3)④ `breeding_trait``valid_min/valid_max`(自定义生物学合理阈值,数据质量校验/异常标记)⑤ 超期预警/通知列为工程项(cron + selection_rule,不阻塞数据模型)。详见 §8.9 |
| v1.8 | 2026-07-29 | 团队/课题组隔离收口(讨论定稿):**不建 team 模块,改用系统已有 `sys_dept` 承载"课题组"**,启用框架"本部门及子部门"数据范围实现**课题组间隔离**;breeding 业务表**不加 `owner_team` 字段**(隔离靠创建者 `dept_id` 推断,由 `Permission._permission_condition()` 自动注入)。边界:性状字典/选择规则/种质/基地地块/人员等**公共基础数据跨组共享**;育种流程(杂交→评价)与统计分析(育种值/指数/报告)**按课题组隔离**。落地为配置级(建 dept 节点+配角色 data_scope+用户归属),非代码,需确认真实课题组清单后执行。 |
| v1.9 | 2026-07-29 | **枚举归属决策(方案A 已定)**:性状的**量表选项/范围**单一真相内联在 `breeding_trait.scale_json`categorical 存 `options`、numeric 存 `min/max/step`),**不进 `sys_dict`**`sys_dict` 仅承载"实体状态/分类枚举"(§9 的 `breeding_stage`/`breeding_generation``tree.status``germplasm_type` 等,非被测变量)。与"生成器机制 A/B/C"是两回事,勿混。详见 §3.1 / §0 原则1。 |
| v2.0 | 2026-07-30 | **遗传评估数据模型架构决策锁定**:① 新增 **`breeding_clone` 独立系谱表**(§3.0clone_id/combination_id/母父本/planting_year/status**无砧木**),与 `germplasm`(亲本/种质档案)**分离**,聚合路径由 `tree.germplasm_id`→germplasm 级 EBV 改为 `tree.clone_id``breeding_clone` 级 EBV(§3.0/§4/§5 同步修订)② `breeding_trait``stage`juvenile/evaluation,与 `category` 正交)③ 新增 **`breeding_rootstock` 砧木字典**(§3.17,只挂 observation 层)④ 新增 **数据质量门禁**(§3.16:缺失标记/异常值/单位强校验/按(clone_id,地点,年份,性状名)去重)⑤ 显式锁定 **砧木建模铁律**(§5.x:记 observation 层 + BLUP 固定效应扣除 + 绝不进 A 矩阵)⑥ 新增 **间接早选**(§5.y)⑦ 实施路线最前插入 **第0阶段 数据治理**(占40%、前置)。均为决策锁定、方案态,待用户"做"后落地 |
| v2.1 | 2026-07-30 | **review 修订(R1R9**:① **R1** §4 tree 加 `clone_id`(FK→breeding_clone,定植必填,聚合锚点) ② **R2** 系谱升级为独立 `breeding_pedigree`(§3.18,个体覆盖 clone+germplasm,dam/sire 指回本表递归闭环)`breeding_clone.female/male_parent_id` 降冗余;`germplasm.pedigree` 自由文本移除 ③ **R3** `breeding_prediction_value``heritability`(h² 同批次落库)、个体锚点改 `clone_id`**R4** 新增模型健康监控(§5.z:h²连年突降/排名翻转告警) ⑤ **R5** 报告 §5.2 模块1 去掉种质内联表型/系谱 ⑥ **R6** 报告 R 引擎统一 subprocess 隔离(弃 rpy2) ⑦ **R7** 统一表名 `breeding_observation`**R8** GCA/SCA 定位为亲本选配辅助 ⑨ **R9** 混合模型加 `clone×year` 随机互作。仍方案态,待"做"落地 |
| v2.2 | 2026-07-30 | **深度复审 A–H 全量落地(用户逐条确认 + F1/F2 架构拍板)**,详见 §8.10:**A 组内部矛盾**——A1 `tree.clone_id` 改为「实生苗定植可空/参试无性系必填、入选晋升才建 clone」(删"定植必填/1树=1clone");A2 `produced_clone_id`=被扩繁原 clone(沿用不新建);A3 全文 `rootstock_id` 统一 FK→`breeding_rootstock`(删 FK→germplasm);A4 A 矩阵系谱以 `breeding_pedigree` 为唯一权威、combination 父母本仅作派生源。**B 组统计**——B1 `heritability` 由明细移主表 `breeding_prediction`;B2 术语正名**加性(狭义)遗传力**、落库取克隆均值 h²=V_clone/(V_clone+V_e/k̄)B3 补 sommer 基线公式;B4 双轨选择统一 clone 级判定。**C 组门禁**——C1 门禁作用于 `breeding_trait_observation` 长表;C2 加 `issue_status`;C3 门禁×状态机衔接。**D 组 clone 居中**——D1 `selection_result`+clone_idD2 `breeding_clone`+generationD3 `trial_study_entry`+clone_idD4 补 tree↔clone 状态流转矩阵。**F 组架构(本轮拍板)**——F1 **裁定走单一长表、废固定列、报表用视图 pivot**F2 保留两张长表职责正交(`breeding_trait_observation` 单株鉴定明细/喂 EBV`breeding_observation` 仅 plot/combination+物候/不喂 EBV),plot 级果实均值由**统计 VIEW 聚合、不双写**;统计管线用普通 **VIEW 保 fresh**、看板层才用 **MV**(MV 不得作 BLUP 输入);F3 门禁关键键实生苗阶段退化为 tree_id;F4 判重键含 tree_id(保 clonal replicates);F5 §5.2 公式补 rootstock 固定效应。**G/H**——G1 统一编号服务定义+clone_id 序号扩位;G2 鉴定类表禁物理删+UPDATE 强制 auditG3 method 文本+method_uri 受控合并;H1-H3 打磨。仍方案态,待"做"落地 |
| v2.3 | 2026-08-04 | **统计引擎两轮 P0 代码落地(自 v2.0 起首次从方案态推进到可运行,均 e2e 验证通过)**,详见 §8.11 / `桃育种系统统计引擎实施记录.md`:① **G×E 交互引擎**(§5.2 互作项落地)——`run_ablup``gxe=True` + `gxe_env=site/year`method=GXEBLUP),site→自动固定效应 `trial_study`、year→`year`,σ²gxe/gxe_ratio/n_cross_env 落 `breeding_prediction.note`,不可辨识门禁(无跨环境重复/单元内无重复)→409,同 clone 多株坍缩为基因型节点 `c{clone}`,异步 `StatisticsJobModel` job_type=GXE/ABLUP+SUCCESS/FAILED;② **性状方向标注**(§3.1/§5.9/§5.z 落地)——`breeding_trait``direction`(desc/asc)/`into_ebv`(1/0)/`default_h2`(先验),选择指数(zsum/smith_hazel/EBV 排行/决策预览/轮次对比按方向归一,低优性状(裂果率/病害级别/酸度)不再选反;`into_ebv='0'` 仅从选种候选剔除;`default_h2` 无实测 h² 时兜底;并修复两处结构性 bug(`ebv_ranking` 方向盲区→读时重排、`compare_predictions` 硬编码降序→方向感知) |
| v2.4 | 2026-08-04 | **桃田间刚需·花粉档案落地(§3.19 + §4 pollination 修订,e2e 验证通过)**:① 新增 **`breeding_pollen` 花粉档案表**(§3.19)——批次号/采集父本(树级 `male_tree_id`,混合/外地采集可空)/采集日期/采集方式/采集量/贮藏方式(4℃/-20℃/-80℃/液氮)/活力测定(方法+百分值+测定日期,TTC 染色率/离体萌发率)/有效期;**授粉窗口 = [采集日, 失效日] 派生**,不建独立计划表 ② §4 pollination 补 `pollen_lot_id`FK→bre_pollen,授粉所用花粉)+ **一期文档规划但遗漏的 `pollination_method`(授粉方式)**,窗口校验(授粉日期须落在批次 [采集日,失效日] 内,否则 409)落地在 pollination service`available_lots` 端点支撑"当前花期可用批次"下拉 ③ 菜单 900056(杂交配组)+按钮 E 段 900601-900608,前端花粉 CRUD 页 + 授粉表单集成批次选择 |
| v2.5 | 2026-08-04 | **决策正确性·选择指数无性系级聚合落地(§5.3 / §5.7,e2e 验证通过)**:桃无性繁殖,**选择指数单位由「树级」升为「无性系级」**——`selection_index` 新增 `aggregate` 参数(默认 `clone`),先按 `tree.clone_id` 把同系多株聚合成一个遗传实体(EBV 均值按**可靠性加权**:`Σ(ebv×rel)/Σ(rel)`,全 rel=0 回退简单均值),再在 clone 级算 zsum/Smith-Hazel 排名;**自株退化**(无 clone_id 的未晋升实生株 → 每株独立单元,不进聚合),保证实生苗阶段不塌缩;`apply_selection` 按**遗传实体**写决选——入选 clone 一条记录(`clone_id` 指向全系 + 溯源株 + reason「系内N株」),self 株逐株写,入选株命中选择规则晋级时晋升建 clone(幂等)。旧行为保留:`aggregate="tree"` 回退单株级。详见 §8.13 / `桃育种系统统计引擎实施记录.md` v1.2 |
| v2.6 | 2026-08-04 | **统计严谨·配合力交配设计落地(§5.3 / §5.5,e2e 验证通过)**:修复统计严谨缺陷——`combining.solve` 原只实现 Griffing 对称全双列,现按 `design_type` 分支(`full_diallel` 完全双列 / `partial_diallel` 部分双列 / `line_tester` line×tester NCII / `nciii` NCIII 测交);NCII/NCIII 走**双因素模型** `y=μ+l_i+t_j+(lt)_ij`line 母本 / tester 父本,各自 Σ=0 约束,SCA=互作=残差,自由度 df_line=n_l-1 / df_tester=n_t-1 / df_sca=残差),不再一律按全双列算错;`bre_cross_combination` / `bre_combining_ability``design_type``run_combining` 按设计过滤只纳入一致组合,GCA 标准误内嵌 `anova_json.gca_se`;角色重叠(同亲本既作 line 又作 tester)→ 409 拒绝,NCIII 门槛 tester 恰 2 个。详见 §8.14 / `桃育种系统统计引擎实施记录.md` v1.3 |
| v2.7 | 2026-08-04 | **统计严谨·预测完整性与 MLOps 复现性(七条复审逐条落地,e2e 验证通过)**,详见 §8.15 / `桃育种系统统计引擎实施记录.md` v1.4:① **Smith-Hazel 遗传相关改可靠性校正**Calo`r_g = r_EBV/√(rel_i·rel_j)` 钳制 [−1,1],替代裸 EBV 皮尔逊相关;真 MT-BLUP 记为引擎级后续项,§8.15 备注)② **PA 落库**——`bre_prediction_value``pa`=√reliability,预测准确度),批次 `bre_prediction.accuracy` 改填真 PA=√(均值可靠性),不再填误名的"均值" ③ **MLOps 溯源**——`bre_prediction``data_version`/`input_hash`(SHA256:表型+系谱确定性序列化)/`engine_version`,同数据重跑哈希一致、改观测必变(数据漂移可检测)④ **germplasm_id 填充**——`run_ablup` 写 EBV 行时填 `tree.germplasm_id`,亲本级 EBV 可查 ⑤ **砧木字典扩列**——`bre_rootstock``dwarf_class`(矮化/半矮化/乔化/柱状)/`compatibility`(砧穗亲和性强/中/弱)选配决策信息(BLUP 固定效应维持够用)⑥ **空间竞争协变量**——`run_ablup` 新增 `covariate="competition"`:同 (plot,block) 网格 Chebyshev 邻域株数作协变量(边缘株相邻少隐式捕捉边缘效应),缺 row/col 数据时显式报错;`bre_tree.row_no/col_no` 数据能力已在录入/导入/导出全链路就位 ⑧ **组合得失漏斗 v_combination_funnel**(同日追加,§8.16):按组合汇总 花→果→种→苗→定植→树→入选 六级派生指标(结实率/出苗率/选择强度),数据源全为既有表、普通 VIEW 保 fresh、只读端点可查,配合力第一手证据落地 |
| v2.8 | 2026-08-04 | **组合得失漏斗落地(§3.13 选择强度链的派生指标收口,e2e 验证通过)**:既有 `bre_pollination.flower_count/effective_count``bre_seed_lot.seed_count/germination_rate``bre_seedling.seedling_count``bre_planting.tree_count``bre_tree``bre_selection_result` 六级数据本已齐全,但**无任何按 `bre_cross_combination` 汇总的派生指标**——结实率/出苗率/选择强度未滚到组合层、配合力上下文吃不到(`run_combining` 只取组合表型均值)。本轮补普通视图 `v_combination_funnel`(花→果 结实率、种→苗 出苗率、树→入选 选择强度,缺环节组合比率列留 NULL)+ 只读端点 `GET /statistics/combination-funnel`。详见 §8.16 / `桃育种系统统计引擎实施记录.md` v1.4 |
| v2.9 | 2026-08-04 | **精修项四连发(用户核实四条缺口、拍板全部落地,e2e 验证通过)**,详见 §8.17 / `桃育种系统统计引擎实施记录.md`:① **DUS/品种保护「数据能力(三表)」**(§2 原 ⏳待建,按拍板档位落地)——`bre_dus_descriptor`UPOV TG/53 描述符模板)/`bre_dus_test`(测试记录)/`bre_dus_observation`(观测,UNIQUE(test,descriptor))三表五件套 + TG/53 桃描述符种子 15 条(trait_code→bre_trait LEFT JOIN 关联 8 条)+ Excel 导入导出/模板 + 菜单 900230 真实页与 G 段按钮 900800-900808;② **stage 感知**v2.0 ① `trait.stage` 终被消费)——`PredictionModel.stage` 落库,选择指数/决策预览按 juvenile/evaluation 过滤、跨阶段混用返回 `stage_warning`/`skipped_stage`;③ **模型外部验证**(可靠性原仅 PEV 法)——`blup.kfold_cv`(sire 家系分层留出避免乐观、逐折容错、留出 EBV 系谱预测)+ `bre_cv_result/fold` 落库 + 端点,**ABLUP/GXEBLUP 双支持**;④ **AI 伦理·分组偏差**——按 site EBV 公平性报告(site_summary deviation/flagged + rank_consistency Spearman + gxe_pattern),只读不建表 |
| v2.13 | 2026-08-04 | **现代桃育种领域覆盖·四方向核实落地三件(用户核实四缺口、拍板开始做,e2e 验证通过)**,详见 §8.21 / `桃育种系统统计引擎实施记录.md` §十四:**②③ 需冷量/需热量 + 抗病性状字典**——`bre_trait` 种子 5 条(细菌性穿孔病/褐腐病/白粉病 0-5 级病情指数 + 需冷量 h + 需热量 GDD,category「抗病性」「生态适应性」,全部 numeric+`into_ebv='1'`+`direction=asc` 进选种目标;统计引擎仅消费 numeric,故抗病不用 categorical 分级);**① S-等位基因(自交不亲和)交配兼容性**——`bre_germplasm.s_alleles`String32`Sf`=自交亲和型),`cross_combination` create/update 校验(任亲本含 `Sf`→放行;无 S 数据→跳过;共享 2 个 S 等位→409「配了不结」硬门禁;共享 1 个→`out.s_compat` 半兼容警示「约半数花粉不亲和」),前端 germplasm 录入 + 组合提交警示;**④ GWAS/QTL/MAS 闭环(900214 仍 `_coming_soon`)留待后续单独立项** |
| v2.12 | 2026-08-04 | **基因组选择(GS)实证严谨性·GBLUP/ssGBLUP 专用 k-fold 交叉验证(§8.20e2e 验证通过)**`genomic.kfold_cv_genomic`(G/H/Hinv 只建一次、逐折掩蔽留出表型,个体保留在关系矩阵、留出 GEBV 由 G⁻¹/H⁻¹ 交叉关系预测)——`run_cv``dataset_id`/`method`/`maf_min` 入参(method=KFCV/GBLUP·KFCV/ssGBLUP),候选=genotyped∩phenos**固定种子随机分层**(GS 同世代样本无家系树,区别于 ABLUP 的 sire 家系留出),单折失败容错不中断,mean/pooled pearson + RMSE + cv_accuracy 落 `bre_cv_result``_gather_gblup_inputs` 提取(run_gblup↔GS CV 复用取数,行为不变);`_build_h` 缺失基因型个体按 base 补入系谱(不再 raise);ENGINE_VERSION 1.1.0、_DATA_VERSION v2.11。SSR 多等位 dummy 编码(§8.20 ②)留待后续 |
| v2.11 | 2026-08-04 | **田间试验精度补强·砧木×接穗随机互作(G×R,rootstock 由固定哑变量升级为第三随机效应槽,e2e 验证通过)**,详见 §8.19 / `桃育种系统统计引擎实施记录.md` §十二:`run_ablup(gxr=True)` 走 G×R 分支(method=GXRBLUP、job_type=GXR),按 `(基因型,砧木)` 分组建 Z₂ 随机互作(克隆坍缩系谱与 G×E 共享),`rootstock` 强制从 fixed_effects 剥离防共线,不可辨识门禁(同基因型无跨砧木/单元内无重复/残差 df<1)→409,σ²gxr/gxr_ratio/n_cross_rootstock 落 note;求解器 `_solve_gxe``factor_label/factor_name` 参数(G×E 警告文案逐字节不变、G×R 显「砧木」),ENGINE_VERSION 1.2.0**Z₂ 单槽位 → G×E/G×R 必须互斥**(双开 409 + 前端互斥 watcher);前端 G×E tab 加 G×R 复选框、批次表互作方差列同显 σ²gxr |
| v2.10 | 2026-08-04 | **六项能力完善(用户核实六条缺口、逐项拍板「全部落地」,e2e 验证通过)**,详见 §8.18 / `桃育种系统统计引擎实施记录.md` §十一:① **MT-BLUP**——`mtblup.solve_bivariate` 成对双性状 REML(共享系谱 A/A⁻¹、y 堆叠 X/Z 块对角、Var(u)=G0⊗A、固定单性状方差仅对 ρ 黄金分割求极大精确 REML),`run_genetic_corr` 逐对 bivariate 组装 G0 + Higham 半正定投影,落 `bre_genetic_corr_result`job_type=GENCORR),`_smith_hazel_index``g_method="mtblup"`(单对不收敛回退 Calo + warning,G 非正定特征值截断)② **GBLUP/ssGBLUP**——`genomic.py`VanRaden G method1/2 + MAF 过滤 + blend 岭;`solve_gblup` 仅基因型株入模型;`solve_ssgblup` 单步法 H⁻¹=A⁻¹+[[0,0],[0,G⁻¹−A22⁻¹]]**V 块用 H 协方差、H⁻¹ 仅进 MME**),`run_gblup`(样本 source_type=tree 直连 / sample_name↔tree_no·品种名兜底,未映射跳过+warning,多等位标记跳过;`genotyped=sorted(dosage)` 对齐 G 行序)③ **DUS 特异性统计检验**——QN 单因素 ANOVA→LSDt_crit 由 `fdist.f_icdf` 二分反解 F(1,df) 开方)、PQ/QL 状态众数比较、**必测描述符**驱动建议,`POST/GET /bre/dus_test/distinctness/{test_id}``analysis_json`,参照默认同 trial_study 自动 + `reference_test_ids` 显式覆盖,conclusion 为 pending 时自动建议 ④ **AMMI/Finlay-Wilkinson 稳定性**——`stability.py`FW 环境指数回归 b/R²/se_b/flag_stable,完美拟合 se_b=0 时 b≈1 判稳;AMMI 残差 SVD→IPC/ASV/ecovalence),`run_stability(gxe_env=site/year)``bre_stability_result`,格子 <2×2 → 409 ⑤ **MLOps 重训+回滚**——`bre_prediction.is_active`(版本链:无 active 时首批 active),`GET /statistics/model/drift`(轻量 `_gather_digest_inputs` 重算输入哈希)+ `POST /statistics/model/retrain`(漂移才重训,新批次 `model_activate` 转移 active+ `POST /statistics/model/activate/{id}`(回滚原语),list 加 is_active ⑥ **BLUP stage 拆分**——`bre_trait_observation.stage`(观测级发育阶段,缺省继承 trait.stage),`run_ablup(stage)` 取数按 coalesce(obs.stage,trait.stage) 过滤 + model_name `_{stage}` 后缀 + PredictionModel.stage 落库,未指定但数据有分歧→note 警示 |
---
## 0. 设计原则(本规格的宪法)
1. **性状字典与测量值分离 + 统一长表存储(对标 BrAPI `ObservationVariable` + `Observation`**`trait` 是唯一的性状字典(代码/类型/单位/量表),**新增桃性状只加字典、不动核心表结构**;测量值一律走**长表 EAV**,分两张职责正交的表——① **单株鉴定明细**`breeding_trait_observation`(挂 `evaluation_id`tree 级,clone 级 EBV 取数主路径)② **物候时序 + plot/combination 级观测**`breeding_observation`。统计层经"统一性状值视图"(DB 普通 `VIEW`,按 `trait_code` pivot)归一供 BLUP 消费(§8.4)。**v2.2/F1 裁定:废弃初稿"核心性状固定列 + EAV 双轨"口径——`tree_evaluation` 已删固定列、全迁 `breeding_trait_observation` 长表;当初上固定列的收益=报表/SQL 聚合快,改由 DB 视图/物化视图 pivot 顶上,不回退固定列)**。这是与初稿最大的修正:字典一处定义、值全部长表、报表用视图。
2. **Program/Trial/Study 三层(对标 BrAPI**:把"多年多点试验"从 site/plot 里抽象出来,支持同一品系跨生态点、跨年同步试验(MET, Multi-Environment Trial)。
3. **桃语义而非大田语义**:清单里的「P/F1/F2 世代、拔节期/抽穗期、播种季节、随机区组/间比」是按一年生大田作物(玉米/小麦)写的,**对桃(多年生无性繁殖果树)必须语义替换**(见 §1)。
4. **砧木–接穗建模**:桃特有的「嫁接繁殖」维度,现有系统完全缺失,必须补齐。
5. **预留分子层**`marker`/`genotype_sample`/`genotype_call` 对齐 BrAPI `Sample`+`Calls`,未来接 GBS / PeachSNP170K 做基因组选择(GS)不改骨架。
6. **统计与决策是地基不是补丁**:上面的数据模型必须能让 V1.1 统计引擎(R `sommer`/`lme4` 做 ABLUP/EBV、选择指数)与 V3.0 AI 决策直接消费,不做"先堆数据再补分析"的短视设计。
7. **API 直接对齐 BrAPI(已采纳)**:保留现有 `/breeding/*`UI 业务接口)的同时,新增 **BrAPI 兼容只读适配层**`/brapi/v2/...`)。数据模型已按 BrAPI 实体设计,适配成本低,可无缝对接 Breedbase / Flapjack / 国际数据交换,避免未来重复造导入导出。
8. **MIAPPE 合规(已采纳)**:试验元数据按 MIAPPE 的 **Investigation(=target/Program) / Study(=trial_study) / ObservationUnit(=tree/plot) / ObservationVariable(=trait)** 对齐,作为数据共享/投稿的一致性基线。
---
## 1. 桃育种语义替换表(清单 → 桃)
| 清单原文(大田作物语境) | 桃系统应改为 | 落点 |
|---|---|---|
| P / F1 / F2 世代(选择阶段) | **选择阶段 `stage`**:实生苗 → 初选株 → 复选株 → 品系 → 区试品系 → 新品种(枚举见 §9 | germplasm/tree/cross/selection_result 的 `stage` |
| 遗传世代 | **遗传世代 `generation`**F1 / F2 / BC1 / BC2 / BC3(与 `cross_type` 联动;引入种质留空) | 权威 `cross_combination.generation``tree`/`germplasm` 冗余拷贝便于筛选 |
| 拔节期 / 抽穗期 | 桃物候:萌芽 / 开花(初花·盛花) / 坐果 / 果实发育 / 成熟 / 落叶 | `observation`(物候类变量) |
| 播种季节 | 桃用**嫁接 / 定植**(砧木 + 接穗),非播种 | planting.rootstock_id → **breeding_rootstock**A3 |
| 自交系 | 桃为**克隆(无性繁殖)**,入选株 = 待审定克隆,需砧木关联 | germplasm.is_rootstock(仅"可作砧木"标记)/ tree.rootstock_id → **breeding_rootstock**(A3,全文砧木 FK 统一指字典,不指 germplasm |
| 随机区组 / 间比试验 | 桃果园株数少,简化为 **区组 + 重复 + 对照**轻量设计 | trial.design_type |
| 材料编号 | accession_no(唯一 accession 编号) | germplasm.accession_no |
**stage / generation 枚举(v1.2 已定,详 §9**:依 RosBREED 桃无性选育流水线与现有 14 域敲定,作为 `sys_dict` 新增字典类型(`breeding_stage` / `breeding_generation`),落库英码、前端显中文。
---
## 2. 目标模块总览(现有 14 + 新增 13,部分为规划)
**A. 现有 14 域(保留 + 字段调整)**
germplasm / site / plot / target / cross_combination / pollination / seed_treatment / seedling / planting / tree / tree_evaluation / tree_photo / selection_result / personnel
**B. 新增模块(P0P2,含 v1.3 复审补入)**
| 模块 | 表名 | BrAPI 映射 | 优先级 |
|---|---|---|---|
| trait(性状字典) | breeding_trait | ObservationVariable | P0 地基 |
| observationplot/物候观测) | breeding_observation | Observation | P0 地基 |
| trait_observation(单株鉴定明细,**v2.2/F2 补登记** | breeding_trait_observation | Observation | P0 地基 |
| field_operation(农事操作) | breeding_field_operation | Observation(op_type) | P0 |
| trial(多年多点试验) | breeding_trial + breeding_trial_study + **breeding_trial_study_entry**(v1.4) | Trial / Study / Entry | P1 |
| group(分组/标签) | breeding_group + breeding_group_member | List | P1 |
| statistics(统计报表) | breeding_report(配置)+ 聚合端点 | — | P2 |
| propagation(克隆扩繁) | breeding_propagation | — | P1(§3.8 |
| seed_lot(种子批·库存) | breeding_seed_lot | — | P1(§3.13,与 MET 一并建模) |
| environment_condition(环境因子) | breeding_environment_condition | — | P1(§3.9G×E 地基) |
| audit_log(审计日志) | breeding_audit_log | — | P1(§3.10 |
| selection_rule(选择阈值规则) | breeding_selection_rule | — | P1(§3.11,决策地基) |
| treatment(试验因子/处理) | breeding_treatment | Treatment(BrAPI) | P1(§3.14,支撑 split_plot 等设计的因子主效应/互作估计) |
| planting_treatment(定植-处理关联) | breeding_planting_treatment | — | P1(§3.15treatment 多对多落地) |
| 分子基因型层 | breeding_marker(含 panel) / breeding_genotype_sample / breeding_genotype_call + **breeding_genotyping_dataset**(v1.4) | Sample / Calls / Marker / Dataset | V2.0(地基先建) |
| prediction(育种值) | breeding_prediction / breeding_prediction_value | — | **值表 V1.1EBV 持久化)/ GS 模型训练 V2.0(§3.12** |
> 注:原稿数"21"已过期,此处以清单为准;其中 seed_lot / environment_condition / audit_log / selection_rule 为 v1.3 复审补入一期,`prediction` 留 V2.0。
**重要简化(避免模块膨胀)**
- **物候期不单列模块** → 只是 `observation` 中「物候类变量」的观测。
- **系谱树不单列模块** → 靠 `cross_combination.parent_combination_id` 自链 + `germplasm.pedigree` 字符串 + 前端 D3 树图 + `/pedigree/{id}` 聚合端点。
---
## 3. 新模块字段规格
### 3.0 breeding_clone(入选克隆系谱表,P0 数据治理地基)
> 桃为无性繁殖,入选株 = 待审定克隆。本表是**遗传身份(clone)层**,与亲本/种质档案 `germplasm`(父母本来源)**分离**(v2.0 决策:亲本资源 vs 入选克隆分离)。砧木只挂在 observation 层,**本表无砧木字段**(建模铁律,§5.x)。嫁接扩繁株沿用原 clone_id,不新建。
> **v2.2/A1 修订)** clone ≠ 每株实生苗。杂种实生苗定植时**不建 clone**`tree.clone_id` 可空),仅当该单株**入选晋升**时由流程创建一条 `breeding_clone` 并回填 `tree.clone_id`;参试无性系(来自 `entry`)定植即有 clone。故本表行数 = 入选克隆数(数百级),而非定植实生苗数(数千级),避免 EBV 全收缩到单株均值。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int | PK | 自增主键 |
| clone_id | varchar(32) | UNIQUE NOT NULL | 组合码 + **单株序(≥4 位,容纳单组合数千株,G1)**,如 `JY-DJB-001-0007`;全局唯一可追溯。**由统一编号服务在入选晋升时生成(§8.9),非定植时**(A1) |
| combination_id | int | FK→breeding_cross_combination NOT NULL | 所属杂交组合 |
| female_parent_id | int | FK→breeding_germplasm | 母本(**冗余直查列**;权威系谱见 §3.18 `breeding_pedigree`,避免 A 矩阵递归断裂) |
| male_parent_id | int | FK→breeding_germplasm | 父本(**冗余直查列**;同上) |
| planting_year | int | NOT NULL | 定植年份 |
| generation | varchar(16) | | **v2.2/D2**:世代 F1/BC1/F2…;脚注:可由 `combination_id`→组合父母本派生,与 `tree.generation` 保持一致,冗余存此便于 clone 级筛选与系谱世代统计 |
| status | varchar(1) | NOT NULL DEFAULT '1' | clone 级决选状态:1入选/2初选/3重点/4保存/5淘汰(淘汰=状态变更非删除) |
| uuid / is_deleted / created_time / updated_time / deleted_time | — | 同框架契约 | 审计与软删 |
**聚合语义**:同一 clone 经嫁接扩繁产生多株 `tree`,其表型是同一基因型的重复观测;统计前按 `tree.clone_id` 聚合为该 clone 的重复测量,EBV 随机效应估在 `breeding_clone` 级(`clone_id`),`tree` 仅作重复测量单元。此点取代原 `tree.germplasm_id → germplasm 级 EBV` 的聚合口径(§4/§5 同步修订)。**(v2.2/A1** 实生苗入选前无 clone_id,其童期观测按 `tree_id` 聚合(门禁键此阶段退化为 tree_id,见 §3.16/F3);入选建 clone 后再切换到 clone 级聚合。
### 3.1 breeding_trait(性状字典,P0
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| trait_code | varchar(64) | UNIQUE, NOT NULL | 如 `brix``fruit_weight``bloom_date` |
| trait_name | varchar(128) | NOT NULL | 中文名:可溶性固形物、单果重… |
| category | varchar(32) | NOT NULL | fruit/flower/plant/disease/phenology/yield/quality/rootstock(业务类别) |
| stage | varchar(16) | NOT NULL | **v2.0**:性状分段 `juvenile`(童期)/ `evaluation`(评价段),与 `category` **正交并存、不混用**;童期采集→间接早选,评价段采集→clone 级 EBV |
| data_type | varchar(16) | NOT NULL | numeric / categorical / date / boolean |
| unit | varchar(32) | NOT NULL | g、%、°Brix、mm、date**v2.0**:导入/观测时**强校验**,值单位须匹配,不符**整行拒收**(数据质量门禁,§3.17) |
| method | varchar(256) | | 测定方法自由文本(如折射仪、游标卡尺) |
| method_uri | varchar(256) | | **v2.2/G3**:受控词表方法 URICrop Ontology / MIAPPE Method),与 `method` 自由文本并存互补——`method` 供人读、`method_uri` 供 BrAPI/国际仓储对接;可空(合并 §6 路线图曾提的 method_uri,消除双字段漂移) |
| scale_json | jsonb | | 量表/选项(categorical 时存选项数组;numeric 时存 min/max/step |
| ontology_uri | varchar(256) | | **v1.4**Crop Ontology / Trait Ontology / MIAPPE 受控词表 term URI(如 `CO_356:0000041`),供 BrAPI 适配层与国际合作仓储对接;可空 |
| valid_min | numeric(12,4) | | **v1.7**:生物学合理下限(自定义阈值),数据质量校验/异常值自动标记用;可空(专册 3.3.2 数据质量监控) |
| valid_max | numeric(12,4) | | **v1.7**:生物学合理上限,同上;可空 |
| direction | varchar(16) | NOT NULL DEFAULT 'desc' | **v2.3 已落地**:性状方向 `desc`=越大越好(默认)/ `asc`=越小越好(**低优性状**:裂果率、病害级别、酸度——若目标是低酸)。选择指数(zsum/smith_hazel)、EBV 排行、决策预览、轮次对比均按此翻转贡献符号/排序方向,杜绝"高 EBV=优"隐含假设把低优性状选反 |
| into_ebv | varchar(1) | NOT NULL DEFAULT '1' | **v2.3 已落地**:是否选种目标 `1`=进 EBV/指数/决策候选(默认)/ `0`=仅记录(**仅从选种相关候选剔除**——指数候选/EBV 排行/决策预览/ABLUP 下拉;describe/correlation/trait_values 不受影响) |
| default_h2 | double precision | | **v2.3 已落地**:先验遗传力 h²(桃经典先验,可在性状字典修改);指数无实测 h² 时兜底(zsum/smith_hazel 均兜底,两者皆无才 409 拒绝) |
> **valid_min/max 局限说明(v2.2/H1**:本字段为**全局单值**,但果重/糖度等的生物学合理区间随**成熟期/年份/砧木**变化,全局阈值可能误标或漏标。一期口径:**接受全局阈值 + 人工复核**(门禁本就对异常值走人工复核,见 §3.16),不强制按 stage 分档;后续如需精细化,可在 `scale_json` 内按 stage 追加分档区间,不改表结构。
| is_preset | bool | default false | 是否系统内置(种子数据) |
| remark | varchar(512) | | |
| created_time / updated_time / is_deleted | 标准 | | 来自 ModelMixin |
> **BrAPI 映射简化说明(v1.4**BrAPI `ObservationVariable = Trait + Method + Scale` 三元组,本系统将 method/scale **内联合并**进 `trait`(桃单作物、方法稳定,避免三表 join 复杂度)。适配层导出 BrAPI 时需按此三元组拆分;`ontology_uri` 提供受控词表引用,满足 MIAPPE/Crop Ontology 可引用性。
**种子数据来源**`doc\果树所\育种\yz.sql``pa_four`(~40 字段:单果重/果形/果核/可溶性固形物/成熟期/离粘核/风味…)与物候类变量,导入为 `is_preset=true` 的桃专用性状字典。
> **枚举归属决策(v1.92026-07-29,方案A 已定)**:性状的**量表选项/范围**是性状定义的一部分,单一真相内联在 `scale_json`categorical 存 `options` 数组、numeric 存 `min/max/step`),**不进 `sys_dict`**`sys_dict` 仅承载"实体状态/分类枚举"(如 §9 的 `breeding_stage`/`breeding_generation`、`tree.status`、`germplasm_type` 等,非被测变量)。二者语义不同——性状=ObservationVariable(有 method/unit/obs_year/重复测量);分类枚举=实体一次设定属性,无测定方法/单位——**不得混用**。BrAPI 导出时 `scale_json`→Scale 三元组,无需 join `sys_dict`。这一定位与"方便统计分析"无关:统计引擎只读 `data_type`+实测值,选项清单存哪不影响计算;A 的真正收益是元数据自包含、防双源漂移、BrAPI 干净导出。
### 3.2 breeding_observation(通用观测,P0
> 采用**显式可空外键**`tree_id` / `plot_id` / `combination_id`),**不采用** `(unit_type, unit_id)` 多态——多态会破坏引用完整性、无法真正联表、且令现有 `_build_conditions` 数据权限注入(依赖已知 FK 列)失效。三者至多一个非空。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| tree_id | int FK→breeding_tree | 可空 | 观测单元=单株 |
| plot_id | int FK→breeding_plot | 可空 | 观测单元=小区 |
| combination_id | int FK→breeding_cross_combination | 可空 | 观测单元=杂交组合(如组合级表型) |
| trait_id | int FK→breeding_trait | NOT NULL | 测了哪个性状 |
| value_numeric | numeric(12,4) | | data_type=numeric 时 |
| value_text | varchar(512) | | categorical / boolean 存此 |
| value_date | date | | data_type=date 时 |
| obs_year | int | | 观测年份(MET 聚合键) |
| obs_date | date | | 具体日期 |
| site_id | int FK→breeding_site | | 观测地点(冗余便于聚合;亦可由 tree→plot→site 推导) |
| person_id | int FK→breeding_personnel | | 观测人 |
| trial_study_id | int FK→breeding_trial_study | 可空 | 区分「试验观测」vs「果园日常观测」;试验观测可参与 BLUP |
| status | varchar(16) | default "draft" | **v1.4**:数据质量态 `draft`(草稿)/`validated`(已校验);批量导入/多人观测下隔离脏数据,统计前按 validated 筛选 |
| issue_status | varchar(16) | default "normal" | **v2.2/C2**:门禁质量标记 `normal`(正常)/`pending`(待补录)/`rejected`(拒收);与 `status` 配合驱动状态机(§3.16/C3),不新建 issue 表 |
| validated_by | int FK→breeding_personnel | | **v1.6**:校验人(status=validated 时记录) |
| validated_date | date | | **v1.6**:校验日期 |
| unit | varchar(32) | | **v1.6**:本次观测值单位(冗余自 trait.unit,便于核对与单位换算);批量导入时按 trait.unit 校验/换算 |
| remark | varchar(512) | | |
**索引**`(trait_id, obs_year)``(tree_id)``(plot_id)``(combination_id)``(trial_study_id)`
**语义(v2.2/F1+F2 重定职责)**:本表**仅承载 plot/combination 级观测 + 物候时序观测**(如花期/果实发育期时序、小区级/组合级群体表型),**不再承载 tree 级果实鉴定性状**——后者一律走 §3.2b `breeding_trait_observation`(挂 evaluation)。两表职责按"**是否喂 EBV**"正交切分:`breeding_trait_observation` 喂 EBV(clone 级取数主路径),`breeding_observation` **不喂 EBV**。**plot 级果实均值不在本表落值**,由统计 VIEW 从 `breeding_trait_observation` 聚合派生(§8.4),杜绝双写与重复计数。原"核心性状走 `tree_evaluation` 固定列"表述作废(F1,见 §4/§8.4)。**v1.6B8**:本系统 tree/plot/block 对应 BrAPI `observationLevels`plant/plot/block),观测单元层级即观测的 FK 类型(tree_id/plot_id/combination_id)。
### 3.2b breeding_trait_observation(单株鉴定明细长表,P0,v2.2 正式登记)
> **命名说明(v2.2/F2)**:本表已在代码落地(模块/URL/权限名 `trait_observation`,模型 `TraitObservationModel`**物理表名 `breeding_trait_observation`** 与全项目 `breeding_*` 前缀一致),此前文档漏登记("代码有、文档无"缺口)。此处补记**既有表**,非新建。
> **职责(F1+F2**:承载**单株(tree 级)每次鉴定的性状明细**——童期性状 + 评价段果实性状,是 clone 级 EBV 的**取数主路径**。与 §3.2 `breeding_observation`plot/combination + 物候)按"是否喂 EBV"正交:本表**喂 EBV**。取代初稿 `tree_evaluation` 固定列(F1)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int | PK | |
| evaluation_id | int | FK→breeding_tree_evaluation NOT NULL | 所属鉴定主记录(一次鉴定=一主记录+N 明细) |
| tree_id | int | FK→breeding_tree NOT NULL | 观测单元=单株(可经 evaluation 推导,冗余便于按株聚合/判重,F4) |
| trait_id | int | FK→breeding_trait NOT NULL | 测了哪个性状(`breeding_trait` 驱动长表) |
| value_numeric | numeric(12,4) | | data_type=numeric 时(统计 pivot 取此列) |
| value_text | varchar(512) | | categorical / boolean |
| value_date | date | | data_type=date 时 |
| category | varchar(32) | | 归属标签页(基本鉴定/果实外观/果皮/果实大小/果肉/果核/其它),驱动前端分组录入 |
| issue_status | varchar(16) | default "normal" | **v2.2/C2**:门禁标记 normal/pending/rejected(同 §3.2 |
| unit | varchar(32) | | 本次观测值单位(冗余自 trait.unit,导入校验用) |
| remark | varchar(512) | | |
| uuid / is_deleted / created_time / updated_time / deleted_time | — | 同框架契约 | **鉴定类表:禁物理删、UPDATE 强制 audit(§3.10/G2** |
**索引**`(evaluation_id)``(tree_id, trait_id)``(trait_id)`
**统一性状值视图**:统计管线由 DB **普通 VIEW**`trait_code` pivot 本表(+ 必要时 union `breeding_observation`)生成宽表供 BLUP,保证 fresh;看板/报表可另建 **物化视图 MV**(定时刷新),但 **MV 不得作为 BLUP 输入**(§8.4)。
### 3.3 breeding_field_operation(农事操作,P0
> 同样改显式 FK`tree_id` / `plot_id`),弃 `(unit_type, unit_id)` 多态,理由同 §3.2。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| op_type | varchar(32) | NOT NULL | 施肥/灌溉/植保/除草/修剪/病害防治/其他 |
| tree_id | int FK→breeding_tree | 可空 | 作用对象=单株 |
| plot_id | int FK→breeding_plot | 可空 | 作用对象=小区 |
| op_date | date | NOT NULL | 操作日期 |
| material | varchar(128) | | 药剂/肥料名 |
| dosage | varchar(64) | | 用量 |
| method | varchar(128) | | 方式(叶面/根施…) |
| operator_id | int FK→breeding_personnel | | 操作人 |
| site_id | int FK→breeding_site | | 定位 |
| remark | varchar(512) | | |
**索引**`(tree_id)``(plot_id)``(op_date)`
**BrAPI 映射修正**field_operation **不映射为 `/events`**BrAPI 无顶层 Event);改为映射到 `/observations`(带 `op_type`),或自定义只读端点(见 §8.2-C)。
### 3.4 breeding_trial + breeding_trial_study(多年多点试验,P1
**breeding_trial**
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| trial_code | varchar(64) UNIQUE | 试验编号 |
| trial_name | varchar(128) NOT NULL | |
| target_id | int FK→breeding_breeding_target | 关联育种目标 |
| design_type | varchar(32) | 取值见 §9rcbd/augmented/contrast/split_plot/unreplicated|
| description | varchar(512) | |
| years | varchar(64) | 跨年计划,如 2026-2028 |
| remark | varchar(512) | |
**breeding_trial_study**Trial×Location×Year
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| trial_id | int FK→breeding_trial | |
| site_id | int FK→breeding_site | 试验点 |
| year | int | 年份 |
| replicate_count | int | 重复次数(原 `replicate` |
| block_count | int | **区组数(v1.3 补)**;与 `tree.block_no` 对应,是 BLUP 的 block 随机效应来源 |
| design_type | varchar(32) | 取值见 §9.4(便于 study 级覆盖 trial 默认设计) |
| control_germplasm_id | int FK→breeding_germplasm | 对照品种 |
| layout_json | jsonb | 田间种植图(小区排布坐标) |
| season | varchar(32) | | **v1.6**:季节/播期分组(如 `2026_dry` 旱季),MIAPPE/BrAPI season 概念,关联 year 的细粒度环境聚合 |
| remark | varchar(512) | |
> **试验隶属链路(v1.3 彻底补全,原稿断裂)**:观测单元(tree)经两条显式 FK 挂到试验——
> - `breeding_planting.trial_study_id`(定植时把这批树挂到某 trial_study,运营钩子)
> - `breeding_tree.trial_study_id`(从 planting 同步,BLUP 直接消费)+ `breeding_tree.block_no`(该树所属区组/重复)
> - `breeding_plot.block_no`(小区级试验时;tree 未填 block_no 则继承 plot
>
> 这样任意 `tree_evaluation`/`observation` 记录 → tree → `trial_study`(environment=site×year) + `block_no` → 混合模型 `y = genotype + block + environment + G×E` 的 block 项不再缺失。布局图由前端可视化 + 轻量排布算法生成。
**breeding_trial_study_entry**(试验 entry 清单,v1.4 补,对标 BrAPI Study 的 entry / ObservationUnit
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| trial_study_id | int FK→breeding_trial_study | 所属试验 |
| germplasm_id | int FK→breeding_germplasm | 参试无性系/品系的**种质溯源**(保留,v2.2/D3 |
| clone_id | int FK→breeding_clone | **v2.2/D3**:参试落 **clone 级**(entry 直指遗传身份,与 BLUP/EBV 聚合层一致);germplasm_id 仅作种质溯源 |
| entry_number | int | **entry 编号**(该 study 内唯一;BrAPI `entryNumber`BLUP 设计矩阵聚合键) |
| planned_reps | int | 计划重复/区组数 |
| n_plants | int | 计划株数 |
| is_control | bool | 是否对照 entry |
| remark | varchar(512) | |
> **为何需要 entry 抽象(v1.4**v1.3 让 `tree` 直接带 `germplasm_id + trial_study_id + block_no`,假设一株=一个观测单元。但一个无性系在某 study 内常**重复多株/多区组**,且需"entry 编号"聚合设计效应。BrAPI 的 `ObservationUnit = germplasm × entryNumber × replicate × blockNumber × position`,本表即此 entry 层;`tree` 通过 `entry_id`(或冗余 `germplasm_id`)挂回,统计层按 `entry_number` 聚合后再估 genotype 效应。
>
> **⚠ 单写点纪律(v1.5 强化)**`tree.trial_study_id` / `tree.block_no` / `tree.entry_id` **均派生自 `planting`**(定植时 planting 一次性写入 `trial_study_id` / `block_no` / `entry_id`tree 创建时由 service 从所属 planting 复制并锁定;后续修改只能改 `planting` 并级联同步 tree)。严禁两处各自手填,否则 BLUP 输入静默错配。
> - **`tree.trial_study_id` 仅记「定植所属 study」**(来自 planting 的单次定植),多年生树跨年/跨点观测**不**改 tree 自身,而是落到 `observation.trial_study_id` + `obs_year`(观测级表达),统计按 observation 的 study 聚合,tree 只是观测单元。
> - **两类 tree 区分(v1.5**`planting.entry_id` 非空 ⇒ 这是**参试无性系**批次,定植时 `germplasm_id` 必须等于 `trial_study_entry.germplasm_id`(入试即定,禁待晋升);`planting.entry_id` 为空 ⇒ **杂种实生苗**批次,`germplasm_id` 待晋升流程写入(晋级纪律管)。单写点 + entry 有无即可区分两类 tree,无需新增类型字段。
> - 写树校验:`tree.trial_study_id = planting.trial_study_id`、`tree.entry_id = planting.entry_id`、`tree.germplasm_id` 与 entry 一致性按上述规则。
### 3.5 breeding_group + breeding_group_member(分组/标签,P1
**breeding_group**
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| group_name | varchar(128) NOT NULL | |
| group_type | varchar(32) | 取值见 §9project/family/category/temporary_set/custom|
| target_id | int FK | 关联育种目标(可选) |
| description | varchar(512) | |
**breeding_group_member**
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| group_id | int FK→breeding_group | |
| germplasm_id | int FK→breeding_germplasm | 或成员种质 |
| clone_id | int FK→breeding_clone | **v2.2/H3**:或成员克隆(入选群体/决选批以 clone 为成员,呼应 D 组 clone 居中);三者(germplasm/clone/tree)按分组用途择一 |
| tree_id | int FK→breeding_tree | 或成员单株 |
| note | varchar(256) | |
> group_type 取值已定(§9):project(育种项目) / family(家系·杂交组合群) / category(种质类别群) / temporary_set(临时选系集) / custom(自定义)。为避免与 `target`(育种目标) 语义重叠,不设 objective 维度。
> **family / category 冗余消减(v1.3**`group_type=family` 本质是"某 `cross_combination` 的后代集合",可由 `tree.combination_id` **动态推导**,不必存静态成员 → 建议 family 做成**虚拟分组(查询)**,不在 `group_member` 落成员;`group_type=category`(油桃/蟠桃/观赏桃)与 `germplasm.variety_type` 字典**重叠**,直接复用 `variety_type`,不在 group 里另起炉灶。故 `group_member` 主要服务于 project/temporary_set/custom 三类。
### 3.6 breeding_report(统计报表配置,P2
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| report_name | varchar(128) NOT NULL | 报表名 |
| report_type | varchar(32) | 育种进度/世代汇总/杂交组合统计/材料库存/MET分析 |
| query_json | jsonb | 报表查询参数(保存配置,便于复用) |
| created_by | varchar(64) | |
| output_format | varchar(16) | | **v1.7**:报告输出格式 `docx` / `pdf` / `view`(看板实时聚合);默认 `docx` |
> **v1.7 确认进一期(原 v1.4 标记延后)**:V2.11 方案书 3.3.1 要求「年度育种进展 Word/PDF 报告」。故一期提供**报告生成服务**(基于 `report_type` 模板 + `query_json` 渲染),支持 docx/pdf 导出,不再仅限于只读聚合端点;看板类走 `view` 实时聚合,归档类走 docx/pdf 落盘。
**配套**
- 报告生成服务:`POST /breeding/statistics/report/generate`(按配置渲染 docx/pdf,可由 cron 触发年度归档)
- 只读聚合端点:
- `GET /breeding/statistics/progress` 育种进度
- `GET /breeding/statistics/generation-summary` 世代汇总
- `GET /breeding/statistics/cross-stats` 杂交组合统计
- `GET /breeding/statistics/inventory` 材料库存
- `GET /breeding/statistics/met` 多年多点分析(钩子,V1.1 R 引擎)
### 3.7 分子基因型层(V2.0,地基先建)
**breeding_marker**(标记/位点)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| marker_name | varchar(64) UNIQUE | 如 SNP_Chr01_123456 |
| chromosome | varchar(16) | 染色体 |
| position | int | 物理位置 |
| marker_type | varchar(16) | SSR / SNP / InDel |
| panel | varchar(32) | **v1.4**:所属标记面板/芯片版本(如 `PeachSNP170K` / `GBSv1`),用于区分不同基因组集、GS 时需一致 |
| assembly_version | varchar(32) | | **v1.6**:参考基因组版本(如 `Peach_v2.0`/`Peach_v2.1`),GS 拼接须同版本坐标,不同版本不可混;对齐 BrAPI marker.referenceGenome |
| remark | varchar(512) | |
**breeding_genotyping_dataset**(基因分型数据集,v1.4 补,GS 训练/预测群体分组)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| dataset_name | varchar(128) NOT NULL | 如 "2026_Brix_GS_train" |
| platform | varchar(32) | GBS / PeachSNP170K / 测序 |
| panel | varchar(32) | 与 marker.panel 对应 |
| purpose | varchar(16) | train(训练群体)/ predict(预测群体)/ reference |
| run_date | date | 分型日期 |
| lab | varchar(128) | 检测单位 |
| remark | varchar(512) | |
> 关联:`genotype_sample.dataset_id` FK→genotyping_dataset(标记某样品属于哪个分型集)。GS 训练时按 dataset(purpose=train) 取 sample→call 矩阵,避免每次手工挑样品。
**breeding_genotype_sample**(基因型样品)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| dataset_id | int FK→breeding_genotyping_dataset | **v1.4**:所属分型数据集 |
| source_type | varchar(16) | germplasm / tree |
| source_id | int | 来源 id |
| sample_type | varchar(16) | DNA / leaf |
| sample_date | date | |
| method | varchar(64) | 测序/芯片(GBS / PeachSNP170K |
| lab | varchar(128) | 检测单位 |
| remark | varchar(512) | |
**breeding_genotype_call**(基因型调用)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| sample_id | int FK→breeding_genotype_sample | |
| marker_id | int FK→breeding_marker | |
| allele | varchar(32) | 基因型编码(AA/AT/TT 或 0/1/2);**v1.6**:遵循 VCF/GP 编码约定(Breedbase 走 VCF 导入),0/1/2 = 纯合ref/杂合/纯合alt |
| remark | varchar(256) | |
**索引**`(sample_id, marker_id)` 复合唯一。
### 3.8 breeding_propagation(克隆扩繁/苗圃,P1,已定纳入一期)
> 桃主繁殖方式为嫁接/芽接扩繁(非种子实生)。打通 **入选株(tree) → 克隆种质(germplasm) → 扩繁批次(propagation) → 新定植树(tree)** 闭环;现有 `seedling`/`seed_treatment` 仍管种子实生苗,二者互补。
**breeding_propagation**(扩繁批次)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| batch_code | varchar(64) UNIQUE | 扩繁批次号 |
| scion_source_type | varchar(16) | germplasm / tree(被扩繁的克隆来源) |
| scion_source_id | int | 来源 id(入选株或其对应种质) |
| produced_clone_id | int FK→breeding_clone | **v2.2/A2 澄清**:本次扩繁**所繁殖的原克隆**(嫁接扩繁沿用同一 clone,**不新建 clone**);产出的新 tree 直接 `tree.clone_id = produced_clone_id`。原"产出的克隆"措辞易误读为新建,特此澄清。取代原 `produced_germplasm_id`→germplasm |
| rootstock_id | int FK→breeding_rootstock | **v2.2/A3**:砧木字典(§3.17);不再 FK→germplasm。`germplasm.is_rootstock` 仅作"可作砧木"标记 |
| method | varchar(16) | 嫁接/芽接/扦插 |
| graft_date | date | 嫁接日期 |
| nursery_site_id | int FK→breeding_site | 苗圃地点 |
| operator_id | int FK→breeding_personnel | 操作人 |
| scion_count | int | 接穗/芽数 |
| grafted_count | int | 嫁接株数 |
| survival_count | int | 成活株数(后续登记) |
| destination | varchar(32) | 出圃/定植/入库 |
| remark | varchar(512) | |
> `survival_count` 与 `grafted_count` 可派生成活率;产出苗木经 `planting`(带 `rootstock_id`→breeding_rootstock)成为新 `tree`,新 tree 的 `clone_id` = `produced_clone_id`**沿用原 clone,不新建**A2),完成闭环(**v2.0clone 级晋升,取代原 germplasm 级**)。
### 3.9 breeding_environment_condition(环境因子,P1G×E 地基)
> 多年多点分析的核心是 G×E 互作。无 site×year 的环境协变量(需冷量/积温/降水),BLUP 只能粗估。本表提供每个试验点每年的环境背景。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| site_id | int FK→breeding_site | NOT NULL | 试验点 |
| year | int | NOT NULL | 年份 |
| chilling_hours | numeric(8,1) | | 需冷量(小时) |
| growing_degree_days | numeric(8,1) | | 积温(GDD |
| rainfall_mm | numeric(8,1) | | 降水量 |
| temp_avg | numeric(6,1) | | 年均温 |
| soil_moisture | numeric(6,1) | | 土壤墒情(可选) |
| source | varchar(32) | | 气象站/人工记录/遥感 |
| remark | varchar(512) | | |
**索引/唯一**`(site_id, year)` 唯一,确保每点每年一条。可复用 `yz.sql` 的"天气"字段做种子。
### 3.10 breeding_audit_log(审计日志,P1
> 晋级审批、全程可追溯需"谁/何时/改了什么"轨迹,现有仅 `updated_time` 粒度不足。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| entity_type | varchar(32) | 实体(tree/selection_result/cross_combination…) |
| entity_id | int | 实体 id |
| action | varchar(32) | create/update/delete/select/approve |
| field_name | varchar(64) | 变更字段(可空,批量时为 null) |
| old_value | varchar(512) | 旧值 |
| new_value | varchar(512) | 新值 |
| operator_id | int FK→breeding_personnel | 操作人 |
| created_time | 标准 | 时间戳 |
**索引**`(entity_type, entity_id)``(created_time)`。建议作为现有 14 域的**通用切面**(在 Service 写操作时统一落审计),而非逐表加列。
> **审计覆盖范围(v2.2/G2,落实操作手册"记录不可删只能改、改要留痕"铁律)**:
> - **鉴定类表**`breeding_tree_evaluation` / `breeding_trait_observation` / `breeding_observation`):**禁止物理删除**,且**禁用软删**`is_deleted` 不对外开放);淘汰/作废走**状态变更**`status`/`issue_status`)而非删除。
> - 上述表的**每次 UPDATE 必须写 `breeding_audit_log`**field_name/old_value/new_value 逐字段),由 Service 切面强制,不可绕过。
> - 其余业务表沿用框架软删;`selection_result`/`cross_combination`/`tree` 等关键决策表的 update/select/approve 一并纳入审计切面。
### 3.11 breeding_selection_rule(选择阈值规则,P1,决策地基)
> RosBREED 的 DNA-informed 选择靠**指数阈值**(如 Brix≥12 且单果重≥200g)自动 flagged。`selection_result` 只记晋级/淘汰,缺"标准"实体,决策支撑会退化为纯人工勾选。本表把"选择标准"显式建模。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| rule_name | varchar(128) | NOT NULL | 规则名(如"鲜食品系晋级线" |
| target_id | int FK→breeding_breeding_target | | 适用育种目标(可选) |
| stage | varchar(32) | | 适用选择阶段(§9.1,如 ap 复选) |
| conditions_json | jsonb | NOT NULL | 阈值条件数组,如 `[{"trait_code":"brix","op":">=","value":12},{"trait_code":"fruit_weight","op":">=","value":200}]` |
| logic | varchar(8) | default "and" | 多条件组合 and/or |
| action | varchar(16) | | flag(标记)/select(自动晋级)/eliminate(自动淘汰) |
| priority | int | | 规则优先级 |
| enabled | bool | default true | |
| remark | varchar(512) | | |
> 决策支撑(§5.4):前端按规则对 `tree_evaluation`/观测值求布尔,自动 flag/晋级;规则与 `trait` 字典通过 `trait_code` 关联,新增性状自动可被规则引用。
>
> **v2.3 已落地)方向感知**`conditions_json` 的 `op` 缺省按性状 `direction`desc→`>=`asc→`<=`);`rank_top_n` 按方向取**最优前 N**asc 取 EBV 最小前 Ndesc 取最大前 N);`into_ebv='0'` 性状不参与决策候选。**兼容性提醒**:既有规则对 asc 性状**显式写了** `>=` 的仍字面执行(可能选反),上线后人工复核。
### 3.12 breeding_prediction(育种值:值表 V1.1 持久化 / GS 模型训练 V2.0
> **v1.7 时序拆分(关键)**v1.6 曾把整张 `breeding_prediction` 标 V2.0,与分子层同期。但 V1.1 统计引擎(R `sommer`/`lme4` 做 ABLUP/EBLUP)会产出育种值(EBV),而「年遗传趋势图(专册 2.6.3)」「EBV 双轨选择(§5 B10)」「亲本/单株决策(专册 3.1/3.2)」都依赖 **EBV 持久化读取**——若不建值表,V1.1 一接入即断链。**v1.7 拆分**:
> - **值存储表 `breeding_prediction_value` 前移 V1.1**:与 V1.1 引擎同期建表并写入,持久化 EBV/预测值,供趋势图与决策读(**硬缺口①闭环**)。
> - **GS 模型训练(基因型→育种值)留 V2.0**:依赖分子层(§3.7 `genotype_call`);其产出的 GBLUP/EBV 同样写入同一 `breeding_prediction_value` 表。
**主表** `breeding_prediction`(模型/批次元数据):
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int PK | |
| model_name | varchar(128) | 模型名(如"2026_Brix_ABLUP" / "2027_Brix_GS" |
| trait_id | int FK→breeding_trait | 预测的性状 |
| method | varchar(32) | ABLUP(系谱) / gBLUP / rrBLUP / GBLUP / BayesV1.1 先填 ABLUPGS 类 V2.0 |
| accuracy | numeric(5,3) | 模型精度(交叉验证) |
| heritability | numeric(5,3) | **v2.2/B1+B2**:本次 BLUP × 该性状的**加性(狭义)遗传力 h²**(一次预测=一个 h²,故落**主表**而非明细)。落库口径取**克隆均值遗传力** h² = V_clone /V_clone + V_e/k̄),k̄=各 clone 平均重复株数;PA 上限 PA≤√h² 用此值。**注**:术语正名——ABLUP 产出的是加性/狭义 h²,非"广义遗传力"(后者含显性/上位,clonal 数据虽可估广义,但本系统选择决策用加性 h²) |
| train_n | int | 训练样本数 |
| predict_date | date | 预测日期 |
| note | varchar(512) | |
**明细** `breeding_prediction_value`(个体预测值,**V1.1 建表**):`prediction_id` / **`clone_id`(FK→breeding_clone,个体锚点,v2.1/R1 与 EBV 聚合层一致)** / `tree_id`(可选重复测量)/ `predicted_value` / `reliability` / `rank`EBV 排名)。**v2.2/B1** `heritability` 已上移主表 `breeding_prediction`(一次 BLUP × 一性状 = 一个 h²,不应在每条明细重复),明细仅存个体级 clone/value/reliability/rank。V1.1 引擎每次跑 BLUP 在主表落 h²、明细落各 clone 的 EBV,同批次持久化。
> **v2.3 已落地)rank 语义 + h² 兜底**`breeding_prediction_value.rank` 是**写时快照**——读时(EBV 排行/轮次对比)按性状当前 `direction` 重新推导优度序(`ebv_ranking` 读时重排、`compare_predictions` 方向感知),性状事后改方向**不需重跑批次**。主表 `heritability` 实测缺失时,指数/排行可用 `breeding_trait.default_h2` 先验兜底(两者皆无才拒绝)。
### 3.13 breeding_seed_lot(种子批·库存,P1,与 MET 一并建模)
> v1.1/§8.3 曾把库存"延后"。v1.3 复审:MET 与**选择强度**都依赖 "种子→播种→定植→入选" 链,故把 `seed_lot` 作为**批记录**提前进一期(仍非完整事务性出入库台账,后者延后)。与 §3.4 的 trial_study 链路共同拼出完整育种流程。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| combination_id | int FK→breeding_cross_combination | NOT NULL | 所属杂交组合 |
| lot_code | varchar(64) | UNIQUE, NOT NULL | 种子批号 |
| harvest_year | int | | 收获年份 |
| seed_count | int | | 收获粒数(选择强度源头) |
| used_count | int | default 0 | **v1.5/v1.6**:已从该批**取用的粒数**(在 seedling/播种环节按粒累加,非定植株数),由 planting/seedling 写操作维护;`remaining = seed_count - used_count` 派生「剩余可播种量」,选强链前段(获种→已用)可量化,不再依赖手工孤值 |
| germination_rate | numeric(5,2) | | 发芽率 %(活力) |
| storage_type | varchar(16) | | 种子库/离体/DNA |
| storage_location | varchar(128) | | 存放位置 |
| test_date | date | | 活力检测日期 |
| remark | varchar(512) | | |
**链接(选择强度链)**
- `breeding_seedling.seed_lot_id` FK→seed_lot(追溯幼苗来源批)
- `breeding_planting.seed_lot_id` FK→seed_lot(可选;种子来源定植)
- **`used_count` 维护(v1.5/v1.6**:每次从某 `seed_lot` 取种(建 seedling / planting 引用该 lot)时由 service 按**粒**累加 `used_count``remaining = seed_count - used_count` 实时可查,避免手工维护 `seed_count` 与实际消耗脱节(注意粒度:粒≠株,used_count 记粒数)。
> **选择强度贯通(v1.5/v1.6**`seed_lot.seed_count`(获种数)→ `seed_lot.used_count`(已用/播种粒数,派生 remaining)→ `COUNT(seedling WHERE seed_lot_id)`(成苗)→ `COUNT(tree WHERE planting.seed_lot_id)`(定植数)→ `COUNT(selection_result 入选)`(入选数)→ 各级**选择强度/选择率**可算,且 "每组合在某试验点种了多少" 与 MET 的 `trial_study` 直接挂钩。前段「获种→已用」因 `used_count` 派生而不再失真。
---
### 3.14 breeding_treatment(试验因子/处理,P1v1.5 提进一期)
> **背景**:§9.4 `design_type` 含 `split_plot`(砧木×接穗两因子)。若只记 design_type 而不结构化 factor/level,BLUP 无法估因子主效应与互作,设计等于白支持。BrAPI 有 `Treatment`(factor + level) 实体;MIAPPE 要求 `ExperimentalFactor`。本表把"试验处理"显式建模,使裂区/析因设计的统计效应可估。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| trial_study_id | int FK→breeding_trial_study | NOT NULL | 所属试验 |
| factor | varchar(32) | NOT NULL | 因子名(如 `rootstock` 砧木 / `scion` 接穗 / `fertilizer` 肥料) |
| level | varchar(32) | NOT NULL | 因子水平(如 `GF677` / `Maotao` / `N0` |
| description | varchar(256) | | 处理说明 |
| remark | varchar(512) | | |
**索引/唯一**`(trial_study_id, factor, level)` 唯一。统计层按 `treatment.factor×level` 估主效应与互作,与 `block` / `environment` 一并进入混合模型 `y = genotype + block + treatment + genotype×env(+空间)`
### 3.15 breeding_planting_treatment(定植-处理关联,P1v1.6 落地 A3)
> **背景(A3v1.6**:§3.14 的 `treatment` 需落到具体定植批次才能进统计。一个 block 级 `planting` 批次常同时接受一组处理(如 rootstock=GF677 + scion=Maotao),故建多对多关联表。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int PK | | |
| planting_id | int FK→breeding_planting | NOT NULL | 定植批次(block 级) |
| treatment_id | int FK→breeding_treatment | NOT NULL | 接受的处理(factor×level |
| remark | varchar(512) | | |
**索引/唯一**`(planting_id, treatment_id)` 唯一。统计层按 `planting→treatment` 把 factor×level 挂到该批次全部 tree,与 `block`/`environment` 一并进入混合模型。
---
### 3.16 数据质量门禁(quality gateP0,作用在 breeding_trait_observation / breeding_observation 入库前)
> **v2.2/C1** 门禁作用于长表 `breeding_trait_observation`(单株鉴定明细)与 `breeding_observation`plot/物候),**不再作用于已废弃的 `tree_evaluation` 固定列**F1);单位/阈值一律从 `breeding_trait` 对齐(valid_min/valid_max/unit)。
| 门禁项 | 规则 | 处置 |
|---|---|---|
| 缺失值标记 | 关键**单元键**缺失(**入选前实生苗=`tree_id`**;入选后=`clone_id`,F3)+ 年份 + 性状值 | 标记 `issue_status=pending`(待补录),**不进分析池** |
| 异常值 | 数值性状按 `trait.valid_min/valid_max` 越界 | 标记 `issue_status=pending`,人工复核(H1:全局阈值 + 人工) |
| 单位混用 | 值单位 ≠ `trait.unit` | **整行拒收** `issue_status=rejected`(§3.1 unit 强校验) |
| 重复记录 | 按 **`(tree_id, 年份, 性状, obs_date)`** 判重(**含 tree_idF4**) | 去重(保留最新 / 人工选择) |
> **(v2.2/F4)判重与重复测量的命门区分**:同一 clone 经扩繁的**多株 tree** 在同点同年的观测是**合法重复测量(clonal replicates**,正是 reliability 的来源,**绝不可当"重复记录"删**。故判重键必须**含 `tree_id`/株号**——只有"同一株、同年、同性状、同日期"多条才是真重复;clone 级多株是"重复测量"而非"重复记录"。原 v2.1 按 `(clone_id,地点,年份,性状)` 判重(会把 clonal replicates 删到只剩一条 → reliability 崩、自由度虚低)**作废**。
> **(v2.2/F3)实生苗阶段单元键退化**:入选晋升前实生苗无 clone_id,门禁单元键退化为 `tree_id`(童期观测按株入库),入选建 clone 后切换 clone_id;否则童期采集会被全部判"缺失键"打回。
> **(v2.2/C3)门禁 × 状态机衔接**:门禁拒收 → `issue_status=rejected` 且记录停留 `status=draft`;门禁标记异常/缺失 → `issue_status=pending`,须人工修正后方可置 `status=validated`**仅 `issue_status=normal` 且 `status=validated` 的记录进 BLUP 分析池**。
### 3.17 breeding_rootstock(砧木字典,P0 数据治理地基)
> 阶段0 建砧木字典(砧木名称/类型/来源),**只挂 observation 层**tree/planting 的 `rootstock_id`),与 `germplasm.is_rootstock`(亲本种质属性)**区分用途**`germplasm.is_rootstock` 标记"该种质可作砧木"`breeding_rootstock` 才是观测层实际使用的砧木清单。砧木**绝不进 A 矩阵**(建模铁律,§5.x)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int | PK | 自增主键 |
| code | varchar(32) | UNIQUE NOT NULL | 砧木编码 |
| name | varchar(64) | NOT NULL | 砧木名称(如毛桃/山桃/GF677…) |
| type | varchar(32) | | 砧木类型(乔化/矮化/本砧…) |
| source | varchar(128) | | 来源(自繁/引进) |
| remark | varchar(512) | | |
### 3.18 breeding_pedigree(独立系谱表,P0 数据治理地基,v2.1)
> **v2.1 修订(R2**:系谱从"clone 内联 female/male_parent_id + germplasm.pedigree 自由文本"升级为**独立系谱表**。原因:① clone 父本指向 germplasm,而 germplasm 父级是自由文本 → A 矩阵递归到父本级断裂;② 自选系作亲本时递归立刻崩。独立表让 `dam`/`sire` 也指向本表,递归闭环。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int | PK | 自增主键 |
| individual_type | varchar(16) | NOT NULL | `clone` / `germplasm`(个体类型,两类共用本表) |
| individual_id | int | NOT NULL | 指向 breeding_clone.id 或 breeding_germplasm.id(由 individual_type 决定) |
| dam_id | int | FK→breeding_pedigree.id | 母本(指向本表,递归闭环;引进种可为 NULL) |
| sire_id | int | FK→breeding_pedigree.id | 父本(指向本表;引进种可为 NULL) |
| rel_type | varchar(16) | | 关系类型(biological / 可选) |
| combination_id | int | FK→breeding_cross_combination 可空 | 来源杂交组合(clone 型时有意义) |
| remark | varchar(512) | | |
> `breeding_clone.female_parent_id/male_parent_id` 降为**冗余直查列**(§3.0),权威系谱以本表为准;`germplasm.pedigree`(自由文本)**移除**,改由本表承载(§4 germplasm 行同步修订)。
> **v2.2/A4)A 矩阵系谱唯一权威**:构造遗传关系 A 矩阵的系谱**以本表 `breeding_pedigree`dam_id/sire_id 递归闭环)为唯一权威**`cross_combination` 的父/母本仅作 clone 系谱行的**自动派生源**(新建 clone 时据组合父母本自动生成本表一行),**不作为 A 矩阵的独立系谱来源**,避免"combination 父母本"与"pedigree dam/sire"双源不一致。§5.8 同步修订。
### 3.19 breeding_pollen(花粉档案,P0 田间刚需,v2.4 落地)
> **(v2.4 落地)** 用户田间刚需:桃花期仅 3–7 天,父本花粉是杂交季命脉;原 `breeding_pollination` 有花朵数/坐果数/去雄/套袋,但**无花粉采集/贮藏/活力/授粉窗口**——明年复盘"这批坐果为什么低"毫无抓手。V2.11 方案书(document.xml:3682-3718)要求父本间花粉效力比较(同一母本×不同父本坐果率对比 + 花粉活力不足诊断),结构化活力数据是统计引擎依赖,不只是文档字段。
>
> **架构决策(v2.4 用户确认)**:① **父本锚点=树级 `male_tree_id`**FK→breeding_tree,与 pollination.male_tree_id 一致;混合/外地采集时为空 + `source_type` 区分)② **活力=单值+方法**`viability_method`[ttc/germination] + `viability_pct` + `viability_test_date`,不建子表)③ **窗口=派生有效期+校验**`collect_date` + `expiry_date`,窗口=[采集日,失效日] 由 pollination service 校验,不建独立授粉计划表)。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | int | PK | 自增主键 |
| lot_code | varchar(64) | NOT NULL UNIQUE | 花粉批次号(如 PL-2026-0001 |
| male_tree_id | int | FK→breeding_tree 可空 | 采集父本树(**树级锚点**;混合/外地采集可空) |
| source_type | varchar(16) | NOT NULL default 'tree' | 来源类型 `tree`父本树 / `mixed`混合花粉 / `external`外地采集 |
| source_desc | varchar(128) | 可空 | 来源说明(混合配比/外地品种) |
| collect_date | date | 可空 | 花粉采集日期 |
| collect_method | varchar(32) | 可空 | 采集方式(采花取粉/振动收集/网袋挂置…) |
| quantity | varchar(32) | 可空 | 采集量(如 50g / 花药数) |
| storage_method | varchar(16) | NOT NULL default 'fridge' | 贮藏方式 `fridge`4℃ / `minus20` / `minus80` / `liquid_n2`液氮 |
| viability_method | varchar(16) | 可空 | 活力测定方法 `ttc`(TTC染色率) / `germination`(离体萌发率%) |
| viability_pct | double precision | 可空 | 花粉活力 % |
| viability_test_date | date | 可空 | 活力测定日期 |
| expiry_date | date | 可空 | 有效期/失效日期(授粉窗口上界) |
| remark | text | | |
> **授粉窗口(派生,不建独立计划表)**:窗口 = `[collect_date, expiry_date]`。`breeding_pollination` 保存/更新时若选定了 `pollen_lot_id` 且批次两日齐备,校验**授粉日期须落在窗口内**,否则 409(错误信息含批次号与窗口区间)。`/bre/pollen/available_lots?date_on=` 端点返回指定日期(缺省今天)窗口内可用批次,供授粉表单下拉("当前花期能用的花粉")与父本效力复盘取数。
> **统计链路**:父本效力分析 = 同一 `female_tree_id` 下按 `pollen_lot_id`/`male_tree_id` 分组的坐果率(`effective_count`/`flower_count`)对比;花粉活力不足诊断 = `viability_pct` 阈值筛查。结构化活力字段(非仅文档)保证该分析可落 SQL。
## 4. 现有模块字段调整(非新增模块)
| 模块 | 新增字段 | 说明 |
|---|---|---|
| germplasm | accession_no(varchar UNIQUE)、stage(varchar 选择阶段)、generation(varchar 遗传世代,可空)、storage_type(varchar 田间/离体/种子/DNA)、is_rootstock(bool)、rootstock_id(int FK 自关联)、**护照块(v1.4,FAO-MCPD): institute_code(varchar 保存单位)、country_origin(varchar 起源国)、collection_site(varchar 采集地)、acquisition_date(date 引种日期)、biological_status(varchar 生物状态:wild/landrace/breeding_line)、breeding_program(varchar 所属育种计划,v1.6 暂自由文本,后续可升级 FK breeding_program 顶层)** | 种质档案补全 + 桃特有维度 + **国际种质资源护照(Genesys/FAO 对齐)**;**系谱不再内联**(v2.1:移除 `pedigree` 自由文本,改由 §3.18 `breeding_pedigree` 独立表承载,避免 A 矩阵递归断裂) |
| cross_combination | cross_type(varchar 杂交/自交/开放)、parent_combination_id(int 自链 FK)、reason(varchar 选配理由)、stage | 系谱链 + 选配理由 |
| pollination | bagging_date(date 套袋)、emasculation_date(date 去雄)、**female_tree_id(int FK→breeding_tree,可空)、male_tree_id(int FK→breeding_tree,可空)(v1.4,杂交圃父/母本树指定)**、**pollination_method(varchar(32) 授粉方式:人工点授/喷粉/涂抹…,v2.4 补一期文档规划但遗漏)、pollen_lot_id(int FK→breeding_pollen,可空,v2.4 授粉所用花粉批次,窗口校验见 §3.19)** | 田间杂交登记补全 + **控制杂交父/母本树追溯(crossing block** + **花粉批次溯源(父本效力分析:同母本×不同父本坐果率对比 + 花粉活力不足诊断)** |
| seedling | seed_lot_id(int FK→breeding_seed_lot) | 追溯幼苗来源批(选择强度链,§3.13) |
| planting | rootstock_id(int FK→breeding_rootstockv2.2/A3)、**entry_id(int FK→breeding_trial_study_entry,可空,v1.5 单写点补 entry)**、**trial_study_id(int FK→breeding_trial_study,可空,单写点)**、**block_no(int,该批树所属区组,单写点)**、**seed_lot_id(int FK→breeding_seed_lot,可空)**、**propagation_id(int FK→breeding_propagation,可空,v1.6 来源双路径)** | **粒度=block 级批次(v1.6 明确:同一 entry 跨多 block 须建多个 planting**;砧木–接穗建模 + **试验隶属(MET 链路唯一写入口;entry_id 非空=参试无性系批次,germplasm_id 入试即定;为空=杂种实生苗批次,germplasm_id 待晋升)** + 库存链接(seed_lot.used_count 派生剩余)+ 来源双路径(种子批/扩繁批二选一) |
| tree | **clone_id(int FK→breeding_clone**可空**;杂种实生苗定植可空、入选晋升时建 clone 回填,参试无性系定植必填,v2.2/A1 取代原"定植必填/1树=1clone";扩繁后 1 clone↔N tree,§3.0 聚合锚点)**、stage(varchar 选择阶段)、generation(varchar 遗传世代,冗余自 combination)、rootstock_id(int FK→breeding_rootstockv2.2/A3)、**germplasm_id(int FK→breeding_germplasm,晋升时回填、定植时留空,禁手填;v2.0:定植即定 clonegermplasm 仅当 clone 晋升为种质时写入)**、**entry_id(int FK→breeding_trial_study_entry,可空,v1.5 派生自 planting,区分两类 tree)**、**trial_study_id(int FK→breeding_trial_study,可空,v1.5 仅记「定植所属 study」,派生自 planting;跨年/跨点观测走 observation.trial_study_id+obs_year)**、**block_no(int,派生自 plantingBLUP block 效应来源)** | **clone 聚合锚点(R1 修正:tree 必带 clone_idEBV 经 tree.clone_id 聚合到 breeding_clone,否则链路断)** + 阶段/世代标记 + 克隆晋升链路(4.x 全流程 + GS 拼接依赖)+ **MET 观测单元归属(派生,单写点=planting;两类 tree 以 entry_id 有无区分)** |
| site | soil_type(varchar 土壤类型)、**latitude(numeric 坐标)、longitude(numeric)、elevation(int 海拔)(v1.4,空间 BLUP/MIAPPE 环境描述)** | 试验地块补全 + **地理定位** |
| selection_result | **clone_id(int FK→breeding_clonev2.2/D1,决选落 clone 级)**、对齐 stage 晋级流转(建议加 from_stage/to_stage + approved_by)、**rule_id(int FK→breeding_selection_rule,可空,v1.4,记录触发晋级的规则,决策闭环)**、tree_id(保留作溯源) | 晋级审批流 + **选择决策溯源(决选粒度=clone,tree_id 溯源到具体单株)** |
| tree_evaluation | **(v2.2/F1:已删果实性状固定列,改为"一次鉴定主记录",性状明细全落 §3.2b `breeding_trait_observation`** trial_study_id(int FK→breeding_trial_study,可空,环境键)、evaluate_date(调查时间)、breeding_personnel_id(评价人)、overall_score(总评)、**crop_load(varchar 坐果量评级 1/2/3,可空,作果实性状协变量降环境误差——**作鉴定主记录字段,每次鉴定一值**)** | 鉴定主记录 + 环境键 + **负载量协变量(专册 1.3:坐果量评级吸收单株负载造成的生理/环境误差,提升 EBV 与选择指数精度)** |
**tree_evaluation 定位(v2.2/F1 裁定:单一长表,废弃固定列)**`tree_evaluation` **已删除所有果实性状固定列**,降为**一次鉴定的主记录**tree_id + evaluate_date + 评价人 + overall_score + crop_load 等每次鉴定级字段),性状明细**全部迁往 §3.2b `breeding_trait_observation` 长表**`breeding_trait` 字典驱动)。原 v1.3「按 `pa_four` 扩 ~30–40 固定列」口径**作废**——已落地代码(2026-07-29)删固定列、统计 service 改从 `breeding_trait_observation` pivot 取数。**报表/SQL 聚合的补偿**:由 DB 视图(统计用普通 VIEW / 看板用 MV)按 `trait_code` pivot 顶上(§8.4),不回退固定列。*原则回归:§0「性状与观测分离」恢复为「字典定义 + 值全部长表」,不再是「固定列 + EAV 双轨」。*
> **v1.6 补(A1/ v2.2 修订**`tree_evaluation`(鉴定主记录)加 `trial_study_id`(可空,按该年 `observation.trial_study_id` 推导或直填),使该次鉴定的所有性状明细(经 evaluation_id 关联的 `breeding_trait_observation`)都继承环境键,纳入 MET 环境效应估计(原"固定列层漏环境键"的裂痕在长表下由主记录统一承载)。
**统一性状值视图(v1.3 补 / v2.2 F1 重定义,统计层关键)**:性状值一律经 `trait_id``trait` 字典关联(长表天然带键,无固定列漂移问题)。在统计/GS 层定义**统一性状值视图 `v_trait_value`**DB **普通 VIEW**),把 `breeding_trait_observation`(单株鉴定明细,喂 EBV)+ 必要时 union `breeding_observation`plot/物候)按 `(unit_key, trait_code, obs_year)` pivot 归一为宽/长表,供 V1.1 BLUP 与 V3.0 决策消费——**普通 VIEW 保证 fresh,不会有过期数据污染 EBV**。看板/报表另建**物化视图 MV**(定时刷新换性能),**MV 不得作为 BLUP 输入**。种子初始化只需把 `pa_four` 写入 `trait` 字典(`is_core=true`),不再向任何固定列写值;新增核心性状只加字典行,不改表结构。
> **v1.6 补(A6/ v2.0 修订**:视图/引擎须把 `tree_evaluation`/`observation` 的观测按 `tree.clone_id`**v2.0:由 `tree.germplasm_id` 改为 `tree.clone_id`→`breeding_clone`**,详见 §3.0)聚合为 clone 的**重复测量**(同一 clone 经扩繁多株 tree 是重复而非独立个体),EBV 随机效应估在 `breeding_clone` 级(`clone_id`),tree 作重复;否则 V1.1 会误把每株当独立个体高估自由度。
---
## 5. 统计分析与决策地基(关键要求)
用户明确要求"统计分析与决策,需要基础能够支持"。数据模型须满足:
1. **任意性状可聚合**:统一性状值视图(§4 末尾,v2.2/F1 由 `breeding_trait_observation` + `breeding_observation` 长表 pivot)使「按性状×年份×地点×阶段」切片聚合无需改表——这是 ABLUP/EBV 与选择指数的输入。
2. **MET 结构就绪(v1.3v1.5 补全)**`tree.trial_study_id`**v1.5 仅记「定植所属 study」**,派生自 planting+ `tree.block_no`(区组随机效应)+ `trial_study.block_count` + **`trial_study_entry`entry_number 设计矩阵聚合键)** + **`treatment`factor×levelv1.5 提进一期,支撑 split_plot 等因子效应)** 提供完整试验设计维度;跨年/跨点观测经 `observation.trial_study_id + obs_year` 表达(树自身不跨 study)。`site` 经纬度/海拔支持 **空间 BLUPsommer 空间项)**。V1.1 混合模型 `y = rootstock + site + year + block + treatment + environment + genotype(clone) + clone×year(随机互作) + G×E(+空间)` 各效应项齐备(**v2.2/F5`rootstock` 作固定效应显式入模,与 §5.x 铁律一致,否则 EBV 被砧木注水**;**v2.1/R9:桃多年生、同 clone 跨年观测是重复测量,须含 `clone×year` 随机互作,否则单年运气被当遗传进展**),可输出 clone 级 EBV。
> **sommer 基线公式(v2.2/B3,供 R 脚本落地)**`mmer(y ~ rootstock + site + year + block, random = ~ vsr(clone, Gu=Amat) + vsr(clone:year), rcov = ~ units, data=...)`,其中 `clone` 走 A 矩阵(`Amat` 由 §3.18 `breeding_pedigree` 构造),`rootstock/site/year/block` 为固定效应扣除系统偏差。lme4 退化版:`lmer(y ~ rootstock + site + year + block + (1|clone) + (1|clone:year))`(无 A 矩阵时)。
>
> > **v2.3 已落地)G×E 交互引擎**`run_ablup` 已支持 `gxe=True` + `gxe_env=site/year``method=GXEBLUP`);site→自动固定效应 `trial_study`、year→自动固定效应 `year`;σ²gxe/gxe_ratio/n_cross_env 落 `breeding_prediction.note` JSON**不可辨识门禁**(无跨环境重复 / 单元内无重复)→409「G×E 不可辨识」;同 clone 多株**坍缩为基因型节点 `c{clone}`**(EBV 一致,重复测量聚合);异步 `StatisticsJobModel` job_type=GXE/ABLUP + SUCCESS/FAILED。落地台账见 §8.11 与 `桃育种系统统计引擎实施记录.md`。
3. **选择指数可计算**:统一性状值视图(表型) + `genotype_call`(基因型) → 多维选择指数(RosBREED DNA-informed 思路),按 `stage` 分层筛选;`selection_rule`(§3.11)把阈值显式化,支持自动 flag/晋级。**(v2.5 落地:指数单位=无性系级)**——桃无性繁殖、一个 clone 多株遗传同质,先按 §5.7 的 `clone_id` 聚合成遗传实体再排名(EBV 均值**按可靠性加权**,同一优系不会因"只中 1 株"被拆散漏选),未晋升 clone 的实生株退化单株参与;`selection_result` 按遗传实体写(clone 级决选 + 溯源株)。
4. **选择强度可算(v1.3 补)**`seed_lot.seed_count`→成苗→定植→入选 四级计数贯通(§3.13),育种效率/选择压力可量化,且与 MET 的"每组合在某点种了多少"挂钩。
5. **决策支撑**`selection_result`(晋级/淘汰) + `stage` 流转 + EBV 排名 + `selection_rule` 自动标记 → 前端决策视图(哪些株晋级/淘汰、依据 EBV 与哪条规则)。
6. **溯源闭环**`tree→combination→父/母本 germplasm` + `observation/field_operation/pollination` 全 FK → 任意品系反向追溯(需求 7.1)。
7. **重复测量聚合(v1.6A6 / v2.0 修订)**:同一 clone 经扩繁产生多株 tree,其表型是同一基因型的重复观测;统计前按 `tree.clone_id``breeding_clone` 聚合为 clone 重复(**v2.0:取代原 `tree.germplasm_id`→germplasm 级聚合**),EBV 随机效应估在 `breeding_clone` 级(`clone_id`),避免自由度虚高。
8. **系谱 A 矩阵(v1.6B9 / v2.0 明确 / v2.2 A4 修订)**:除基因组 G 矩阵(来自 `genotype_call`)外,BLUP 可并入系谱 A 矩阵;A 矩阵系谱**以 §3.18 `breeding_pedigree`dam_id/sire_id 递归闭环)为唯一权威**v2.2/A4),供 `sommer` 递归构造;`cross_combination` 的父/母本仅作 clone 系谱行的**自动派生源**(建 clone 时据组合父母本自动生成 pedigree 行),不作独立系谱来源,避免双源不一致。`breeding_clone.female/male_parent_id` 仅为冗余直查列。**砧木(`breeding_rootstock`)绝不进 A 矩阵**(建模铁律,§5.x)——砧木改表型不改遗传身份。
9. **EBV 驱动选择(v1.6B10 / v2.2 B4 修订)**`selection_rule`(§3.11)的 `conditions_json` 除引用 `trait_code`(表型阈值)外,应允许引用 `prediction_value`(EBV 排名阈值),实现 RosBREED「表型 + EBV」双轨选择。**v2.2/B4)双轨统一在 clone 级判定**:表型侧先按 `tree.clone_id` 聚合到 clone 均值,再与 clone 级 EBV 按同一规则比较,避免"表型按株、EBV 按 clone"粒度错配。
10. **负载量协变量(v1.7,硬缺口②)**`tree_evaluation.crop_load`(坐果量评级 1/2/3)作为果实性状混合模型协变量,吸收单株负载造成的环境/生理误差(专册 1.3),提升 EBV/选择指数精度;V1.1 引擎须支持该协变量项。
11. **超期预警/通知(v1.7,软缺口⑤,工程项)**:专册 3.3.2「树 N 年未决策预警」由定时任务(cron)扫描 `selection_result`/`tree.stage` 实现,结合 `selection_rule` 触发通知;不阻塞一期数据模型,属前端/调度工程项。
### 5.x 砧木建模铁律(遗传评估不可动摇规则,v2.0 2026-07-30 锁定)
> 适用于所有落地:数据字典、R 脚本(sommer/lme4fixed 公式、observation 层字段、质量门禁。
1. **记录层**:砧木只记在 observation 层(`tree`/`planting``rootstock_id``breeding_rootstock` 字典,§3.17);`breeding_clone` 系谱层**无砧木**。
2. **A 矩阵(遗传随机关系)**:**绝不进**——砧木改表型不改遗传身份,进 A 矩阵会污染 clone 的 EBV。
3. **BLUP 固定效应**:砧木**必须进**,与 `地点 / 年份 / 定植批次` 并列扣除系统偏差;否则残差被污染、clone 的 EBV 被砧木注水。
> 关键澄清:"不进 A 矩阵" ≠ "不进模型"——砧木不进随机遗传关系,但**必须进固定效应**。这一字之差直接决定 EBV 是否被砧木注水,是建模正确性的命门。
### 5.y 间接早选(indirect early selectionv2.0
| 分期 | 内容 | 阶段 |
|---|---|---|
| 童期采集 | `trait.stage=juvenile` 性状采集(tree 视角,2–3 年) | **一期必做** |
| r_G 早选模型 | 基于遗传相关 r_G 的早选(童期性状预测评价段性状) | 排**二期** |
| 一期过渡 | 用历史"晋级/淘汰"标签训练**监督分类器(过渡)** | 一期 |
### 5.z 模型健康监控(v2.1R4
> "模型还准不准"的命门。每次 BLUP 重跑后扫描并与上一轮对比:
> - **h² 连年突降**:某性状 h² 较上一轮跌幅超阈值 → 告警(疑似数据质量/环境突变)。
> - **clone EBV 排名大幅翻转**:排名 delta / 排序相关性骤降 → 告警(疑似录入错误或模型设定漂移)。
> - 输出进现有告警/定时任务通道(§5 第11点),与"树 N 年未决策"并列。
>
> **(v2.3 已落地)方向感知**:轮次对比 `compare_predictions` 已按性状当前 `direction` 排序(asc 时 rank 1 = 最低 EBV 优);h²/相关/翻转位移量对反转不变量不变,仅展示 rank 列不再把最差株显示为第 1。
---
## 6. 实施路线(建议)
| 阶段 | 内容 |
|---|---|
| **第0阶段 数据治理(占40%、前置,v2.0/v2.1/v2.2** | 盘点5年历史数据 + **breeding_clone 系谱表(§3.0** + **breeding_pedigree 独立系谱表(§3.18,A 矩阵唯一权威)** + **breeding_rootstock 砧木字典(§3.17** + **trait_observation 单株鉴定明细长表(§3.2b,v2.2 补登记既有表)** + `trait``stage`(§3.1+ 字段规范 + **数据质量门禁(§3.16**garbage in garbage out,决定后续 EBV 可信度 |
| 地基(先做) | trait(含 ontology_uri) + observation(含 status) + **trait_observation 单株鉴定明细长表(§3.2b,v2.2 补登记既有表)** + 现有模块 stage/rootstock/accession_no/pedigree 字段;数据权限/options 沿用现有生成器 |
| P0 | field_operation |
| P1 | trial(+study+**study_entry**,§3.4)、**treatment(试验因子/处理,§3.14,v1.5 提进一期)**、**planting_treatment(§3.15,v1.6)**、group(+member,§3.5)、propagation(克隆扩繁,§3.8)、seed_lot(种子批,§3.13,**v1.5/v1.6 used_count 派生剩余**)、environment_condition(环境因子,§3.9)、audit_log(审计,§3.10)、selection_rule(选择阈值,§3.11,**v1.6 支持 EBV 阈值**)、**site 坐标 + germplasm 护照块 + pollination 父/母本树 + selection_result.rule_id(v1.4)+trial_study_id(v1.6) + planting.entry_id(v1.5)+propagation_id(v1.6)+block级粒度 + tree 两类区分 + tree_evaluation.trial_study_id(v1.6) + tree_evaluation.crop_load(v1.7) + tree_photo.observation_id(v1.6)(§4 字段调整)** + trial_study.season(v1.6) + marker.assembly_version(v1.6) + trait.method_uri/scale_uri(v1.6) + observation.validated_by/date/unit(v1.6) + kinship A矩阵(v1.6) |
| P2 | statistics 聚合端点(含 selection_rule 驱动的自动 flag/晋级预览) |
| **延后(v1.4 标记,v1.7 调整)** | **experiment_factorMIAPPE 受控试验因子,先用 field_operation 近似)、breeding_program 顶层(BrAPI Programtarget 暂代)** |
| **批量表型导入(v1.3 补,规划)** | `observation` 是 EAV(性状×单元×值),主数据入口是**成千上万条观测的批量进表**(设备/ sheet 导出),与现有"一行一实体"行式导入机制不同,需单列导入通道(含 trait_code 校验、单位换算、单元解析 tree_id/plot_id |
| 字典类型扩展 | breeding_dict.sql 增 breeding_stage/breeding_generation/breeding_group_type/breeding_design_type 四类(英码+中文),接入下拉与 Excel 导入翻译(DictLabelResolver) |
| V2.0 | marker + genotype_sample + genotype_call(地基先建表,分析后置)+ **GS 模型训练**(§3.12,值表已 V1.1 前移) |
| V1.1 | R 统计引擎接入统一性状值视图 + trial 做 BLUP/EBV |
| V3.0 | AI 决策(Agno + DeepSeek)消费 EBV/选择指数 |
| BrAPI 适配层 | 只读 `/brapi/v2/*` 端点(germplasm/crosses/trials/studies/observations/observationvariables/lists/samples/markers/calls/programs**field_operation 映射为 `/observations`(带 op_type) 而非 `/events`**),对接 Breedbase/Flapjack/国际交换(§0 原则 7 |
**工程约定(生成器机制待拍板)**:新模块用**系统内置代码生成器**`module_generator/gencode`DB-first,产物落 `app/plugin/`,自动建菜单)还是**续用自定义 `_gen_*.py`**(落 `app/api/v1/module_breeding/`,与现有 14 域一致)仍待用户定 A/B/C(见记忆「建表/生成器坑」)。无论哪条,改字段后跑 `deploy.bat migrate``fix_breeding_columns.py`)再重启后端。
---
## 7. 待确认项(收口)
v1.7–v1.8 已闭环统计/决策地基与团队隔离;**v1.9 已收口"枚举归属 A/B"(性状量表选项→`scale_json`、不进 `sys_dict`,详见 §3.1 / §0 原则1)**。剩余**唯一未拍板项 = 生成器机制 A/B/C**(注意:此 A/B/C 与"枚举归属 A/B"是两回事,勿混):
1. **生成器机制 A/B/C(唯一未拍板)**:新模块落 `app/plugin/`(内置 gencode 式)/ 续用自定义 `_gen_*.py`(与老 14 一致)/ 全迁 plugin 式。其余规格(含 v1.7 全部字段、v1.9 枚举归属)均已锁定,实施时据此生成即可。
> 文档进入"v1.9 枚举归属定稿版"。除生成器 A/B/C 外,待用户明确"做/搞吧"后实施,不先行编码。
---
## 8. 复审补充:遗漏与替代思路(2026-07-28 复审)
> 本节为第一稿(§0–§7)的批判性复审结论,针对"还有哪些遗漏 / 不同思路"自省。改变范围的项标注「待拍板」。
### 8.1 原稿遗漏的关键项
1. **`generation`(遗传世代)与 `selection_stage`(选择阶段)混为一谈**:桃虽以无性选择为主,但回交转育(BC1/BC2)、自交分离(F2)仍是真实遗传世代,与"选到第几轮"是两回事。建议拆字段:`generation`F1/BC1/BC2…,跟 `cross_type` 联动)+ `selection_stage`(实生苗/初选株/复选株/品系/区试/新品种)。
2. **缺"树→种质"晋升链路(克隆生命周期)**:入选株应晋升为 clone/accessiongermplasm)被命名扩繁。需 `tree.germplasm_id`,否则基因型(测在 germplasm)与表型(测在 tree)无法在 GS 中拼接。
3. **原清单 1.4「按团队权限隔离」→ 改用 `sys_dept` 承载课题组隔离(v1.8 定稿)**:经讨论,team 仍**不建独立模块、不加 `owner_team` 字段**;但启用 FastApiAdmin 框架**已有**的"部门(dept)数据范围"能力承载课题组隔离——把"课题组"建模为 `sys_dept` 节点,给角色配"本部门及子部门"数据范围,`Permission._permission_condition()` 即按创建者所在部门自动隔离,breeding 表零改动。
**隔离边界(关键业务决策)**
| 数据域 | 隔离策略 | 理由 |
|---|---|---|
| 性状字典、选择规则 | **跨组共享** | 全所统一观测标准与选择阈值 |
| 种质资源、系谱 | **跨组共享** | 所级资源库,亲本须被各课题组选配 |
| 试验基地、地块、育种人员 | **按课题组隔离** | 各组自有基地/地块与人员花名册 |
| 育种流程(杂交→评价) | **按课题组隔离** | 各组私有作业数据 |
| 统计分析(数据集/计算/育种值/指数/报告) | **按课题组隔离** | 各组独立遗传评估与决策 |
**局限**:隔离靠"创建者部门"推断(谁建的归哪组);若要"跨组协作同一条数据"需升级显式 `owner_team` + 多对多协作,留待单独立项。
**范围说明(2026-07-29 澄清)**:当前实际仅「桃育种课题组」在用,多课题组为**未来扩展**预留。隔离机制**先就位**——建 `sys_dept` 课题组节点 + 给角色配"本部门及子部门"数据范围即可,无需改任何 breeding 代码;无多组时所有用户同属一组,效果等同无隔离,不影响现有使用。未来新增课题组只需加 dept 节点并迁移用户 `dept_id`,即可自然隔离。
**落地(配置级、非代码,需先确认真实课题组清单)**:① `sys_dept` 建课题组节点 ② 用户 `dept_id` 归属 ③ 育种员等角色配数据范围"本部门及子部门"ADMIN/SUPER_ADMIN 看全部)④ 验证普通用户仅见本组数据。
4. **"材料库存"被弱化成纯报表**:库存是事务性的(种子批/ lot、在圃株数、离体/DNA 管数、活力)。应加 `germplasm_stock`/`seed_lot` 表(数量、批次、位置、活力、出入库),报表只是视图。【待拍板】
5. **缺环境/气象数据(G×E 统计地基)**:多年多点分析核心是基因型×环境互作,无环境协变量(site×year 的需冷量/积温/降雨)BLUP 只能粗估。建议加 `environment_condition`site×year),可复用 `yz.sql` 的"天气"字段。
6. **分子层缺"预测模型"表(GS 反馈环断裂)**:RosBREED 是闭环(表型+基因型→训练模型→输出 EBV→指导下轮选配)。需 `breeding_prediction`(模型/性状/精度 accuracy/预测日期/被预测个体)。
7. **克隆繁殖/苗圃 → 已定纳入一期(§3.8)**:现有 `seedling`/`seed_treatment` 仅种子实生苗;桃入选后主要靠嫁接/芽接扩繁,补 `breeding_propagation`(接穗来源→成活→出圃),打通 入选株→克隆种质→扩繁→新定植树 闭环。
8. **统一修改日志/审计缺失**:晋级审批、全程可追溯需"谁/何时/改了什么"轨迹,现有仅 `updated_time`。建议轻量 `breeding_audit_log`(或接系统操作日志)。
9. **小遗漏**`tree_photo` 应可关联 `observation`(某次测量的果实照片,为 CV/AI 预留);`observation` 应可挂 `trial_study_id`(区分试验观测 vs 果园日常观测);编号生成策略未定义(`accession_no`/`combination_code`/`tree_no`/`trial_code` 需统一自动编号服务)。
### 8.2 替代思路与推荐
- **A. EAV 纯通用 vs 混合固定列 → ~~推荐混合固定列~~(v2.2/F1 已推翻,改为单一长表,详 §8.4)**。~~理由:桃果实质性状稳定且高频、报表是核心需求、现有 tree_evaluation 已在工作。~~ **v2.2 更新**:代码 2026-07-29 已删 `tree_evaluation` 固定列、全迁 `breeding_trait_observation` 长表,故最终裁定走单一长表;原"报表性能"顾虑改由 DB 视图 pivot(统计 VIEW / 看板 MV)解决,不再保留固定列。
- **B. 分组 vs 标签 → 建议并行**:`group`(正式项目组/品系群)+ 自由 `tag`(多对多,如"抗褐腐""高Brix""区试备选")。
- **C. 直接对齐 BrAPI API → 已采纳(见 §0 原则 7)**:不仅"铺路",而是正式承诺实现 BrAPI 兼容只读适配层。建议首批暴露端点(映射我们的模块):
- `/brapi/v2/germplasm``/brapi/v2/germplasm/{id}/pedigree` ← germplasm + cross_combination 系谱链
- `/brapi/v2/programs` ← target`/brapi/v2/crosses` ← cross_combination
- `/brapi/v2/trials``/brapi/v2/studies` ← trial / trial_study
- `/brapi/v2/observationvariables` ← trait`/brapi/v2/observations` ← observation
- `/brapi/v2/lists` ← group`/brapi/v2/observations`(带 op_type) ← field_operation(注:BrAPI 无顶层 Event,不映射 `/events`
- `/brapi/v2/samples``/brapi/v2/markers``/brapi/v2/calls` ← 分子层
- 适配层为**只读适配器**(读我们现有表,映射成 BrAPI JSON),不重复实现写操作;UI 仍走 `/breeding/*`
- **D. MIAPPE 合规 → 已采纳(见 §0 原则 8**Investigation=target、Study=trial_study、ObservationUnit=tree/plot、Variable=trait 对齐;作为数据导出/共享到国际仓储时的一致性检查基线。
### 8.3 复审后模块清单(原 21 模块基础上)
- 新增(一期):`environment_condition`site×year 环境因子,G×E 统计地基,§3.9)、`propagation`(克隆扩繁/苗圃,§3.8)、`breeding_audit_log`(审计,§3.10)、`breeding_selection_rule`(选择阈值,§3.11)、`breeding_seed_lot`(种子批/库存链,§3.13,v1.3 从延后**提前进一期**与 MET 一并建模);`breeding_prediction`(GS 模型/育种值,V2.0 与分子层同期,§3.12);`breeding_trial_study_entry`(试验 entry 清单,v1.4,MET 设计矩阵);`breeding_genotyping_dataset`(分型数据集,v1.4,GS 训练群体)。
- **字段强化(v1.4**`trait.ontology_uri`Crop Ontology 对接);`observation.status`(数据质量);`site` 经纬度/海拔(空间 BLUP);`germplasm` 护照块(FAO-MCPD);`pollination` 父/母本树(crossing block);`selection_result.rule_id`(决策闭环);`tree.entry_id`entry 聚合);`marker.panel`(芯片版本);`genotype_sample.dataset_id`
- **不建 `team` 模块**(v1.8 定稿):团队隔离由 `sys_dept` + 角色数据范围实现,breeding 表不加 `owner_team` 字段;公共基础数据跨组共享、育种流程与统计按组隔离(见 §8.1 第 3 点)。
- **仍延后(v1.4 标记)**:完整事务性出入库台账(`germplasm_stock` 等,`seed_lot` 已精简进一期);`experiment_factor`(MIAPPE 受控试验因子,先用 field_operation 近似);`breeding_report` 配置表(先用只读端点);`breeding_program` 顶层(BrAPI Programtarget 暂代)。
- 字段细化:`tree.germplasm_id` + `generation``tree.trial_study_id` + `block_no`**派生自 planting,单写点纪律**v1.4);`planting.trial_study_id` + `block_no` + `seed_lot_id``observation.trial_study_id` + 显式 FKv1.3);`tree_photo.observation_id`;统一编号生成服务。
- 物候期仍走 `observation`(时序,非固定列);系谱树仍靠 `cross_combination.parent_combination_id` 自链 + 前端树图。
### 8.4 长表决策详述(对应 §4 tree_evaluationv2.2/F1 改写)
**结论:单一长表(废弃"混合固定列")。** v1.0v2.1 曾定"混合固定列(Hybrid",但代码 2026-07-29 已删 `tree_evaluation` 固定列、全迁长表,统计 service 改从长表 pivot 取数;文档据此裁定改为单一长表:
- **单株鉴定明细层 = `breeding_trait_observation`**(挂 `evaluation_id`,tree 级):承载童期 + 评价段的所有单株性状(含原 `pa_four` 的 ~40 个核心果实/农艺性状),是 clone 级 EBV 的取数主路径,**喂 EBV**。
- **plot/物候层 = `breeding_observation`**:仅承载 plot/combination 级观测 + 物候期时序,**不喂 EBV**。
- **两表按"是否喂 EBV"正交切分**plot 级果实均值**不落表**,由统计视图从 `breeding_trait_observation` 聚合派生(§3.2/§3.2b),杜绝双写。
- **报表/SQL 聚合补偿(原固定列的唯一收益)**:由 DB 视图 pivot 顶上——**统计管线用普通 `VIEW`(实时 pivot、保 fresh、喂 BLUP****看板/报表用物化视图 `MV`(定时刷新换性能),但 MV 不得作 BLUP 输入**,避免过期数据污染 EBV/reliability。
- **防双源规则**:同一性状值只存一处(tree 级果实性状→`breeding_trait_observation`;物候/plot→`breeding_observation`),禁两表重复记录;`trait.is_core` 仅作"是否纳入统计核心指标"标志,**不再决定"存固定列还是 EAV"**。
- **代价**:报表需经视图 pivot(一次性建视图,非每次改表);换来"新增性状零表结构变更"与代码/文档一致。原"新增核心性状需 migrate 改表"的代价消除。
### 8.5 二次复审(v1.32026-07-28)— §8 遗留项处置
针对 §8.1–§8.3 的遗留与本人深度复盘,本轮一次性落档,要点:
| # | 议题(源自 §8 / 复盘) | v1.3 处置 |
|---|---|---|
| 1 | **MET 链路断裂(最致命)** | 彻底补全:`trial_study.block_count` + `planting.trial_study_id` + `tree.trial_study_id`/`block_no` + `plot.block_no`(§3.4/§4)。block 随机效应不再缺失,混合模型可估 |
| 2 | **库存与选择强度** | `seed_lot` 从"延后"提前进一期(§3.13),与 MET 拼出 seed_lot→seedling→planting→tree→trial_study 选择强度链;完整 ledger 仍延后 |
| 3 | **§0 原则1 与混合模型自相矛盾** | 已修订 §0 原则1 措辞,与 §4/§8.4 一致(字典一处定义、值可固定可扩展) |
| 4 | **observation/field_operation 多态反模式** | 改显式可空 FKtree_id/plot_id/combination_id),保引用完整 + 数据权限 `_build_conditions` 可用(§3.2/§3.3 |
| 5 | **三模块只有名字无规格** | 已补 `environment_condition`(§3.9)、`audit_log`(§3.10)、`prediction`(§3.12);并额外补 `selection_rule`(§3.11) |
| 6 | **tree_evaluation "保留"误述** | 改为"按 pa_four 扩 ~40 列",并补**统一性状值视图**消除 trait↔固定列双源漂移(§4) |
| 7 | **选择阈值规则缺失** | 新增 `breeding_selection_rule`(§3.11),决策支撑可自动化 |
| 8 | **批量表型导入未规划** | 已单列规划(§6),EAV 主数据入口区别于行式导入 |
| 9 | **tree_photo.observation_id 未落地** | 已纳入 §4 字段调整(todo 与正文对齐) |
| 10 | **group family/category 冗余** | family 改虚拟分组(由 combination_id 推导)、category 复用 `variety_type`(§3.5 |
| 11 | **BrAPI `/events` 不标准** | field_operation 改映射 `/observations`(op_type)(§3.3/§8.2-C |
| 12 | **文档计数过期** | §2 改为显式清单,不再钉"21" |
| 13 | **生成器机制** | 标注为待拍板 A/B/C(§6 工程约定),不再默认续用 `_gen_*.py` |
> 本轮为**纯文档定稿**,未触碰任何代码。待用户就 §7 minor 项(尤其生成器 A/B/C)确认后即可实施。
### 8.6 三轮复审(v1.42026-07-28)— 国际基准(BrAPI/Breedbase/RosBREED/MIAPPE/Crop Ontology/FAO-MCPD/Genesys
对照国际先进做法再扫一遍,把"正经育种程序该有、v1.3 仍缺"的落档:
| # | 议题(国际基准) | v1.4 处置 |
|---|---|---|
| 1 | **缺试验 entry 清单 / entry_number**BrAPI ObservationUnit = germplasm×entryNumber×rep×block | 新增 `breeding_trial_study_entry`(§3.4),`tree.entry_id` 挂回,BLUP 设计矩阵按 entry 聚合 |
| 2 | **缺 site 地理坐标**(空间 BLUP / MIAPPE 环境 / 积温插值) | `site``latitude/longitude/elevation`(§4 |
| 3 | **缺观测校验态**Breedbase 数据质量) | `observation.status`draft/validated)(§3.2),统计前按 validated 筛 |
| 4 | **trait 缺本体引用**Crop Ontology / MIAPPE 受控词表) | `trait.ontology_uri`(§3.1);注明 method/scale 内联简化、BrAPI 适配层拆分三元组 |
| 5 | **tree↔planting 双写漂移风险**(v1.3 隐患) | 明确**单写点=planting**`tree.trial_study_id/block_no` 为**派生**service 写树校验一致(§3.4 注) |
| 6 | **germplasm 缺护照描述符**FAO-MCPD / Genesys | germplasm 补 `institute_code/country_origin/collection_site/acquisition_date/biological_status/breeding_program`(§4 |
| 7 | **缺 genotyping_dataset**GS 训练群体分组) | 新增 `breeding_genotyping_dataset`(§3.7),`genotype_sample.dataset_id``marker.panel`(芯片版本) |
| 8 | **selection_result 未关联规则**RosBREED 决策闭环) | `selection_result.rule_id`(§4 |
| 9 | **缺 crossing block 父/母本树**(桃控制杂交) | `pollination.female_tree_id/male_tree_id`(§4 |
| 10 | **受控试验因子未结构化**MIAPPE ExperimentalFactor | 标记延后,先用 `field_operation` 近似(§6 |
| 11 | **breeding_report 配置表过早** | 标记延后,先用只读端点(§6) |
| 12 | **target 映射 BrAPI Program 略偏** | 标记延后,target 暂代 Program,后续可加 `breeding_program` 顶层(§6 |
| 13 | **tree.germplasm_id 多路径派生漂移** | 明确 `germplasm_id` 非空且由晋升流程写入、禁手填(§4) |
> 本轮为**纯文档定稿(v1.4)**,未触碰任何代码。文档进入"国际基准对齐版",待 §7 minor(尤其生成器 A/B/C)确认后实施。
### 8.7 四轮复审(v1.52026-07-28)— 用户拍板的 v1.4 自洽修复
用户就第四轮复审(§8 末尾 16 点)拍板:只要合理全部采纳以下 5 点,并生成新版:
| # | 议题(v1.4 自洽/国际盲点) | v1.5 处置 |
|---|---|---|
| 1 | `planting` 单写点却无 entry`tree.entry_id` 无法派生 | `planting``entry_id`(§3.4/§4);`tree.entry_id`/`block_no`/`trial_study_id` 全派生自 planting |
| 2 | 多年生 `tree` 与单值 `trial_study_id` 冲突(跨年观测归属丢失) | `tree.trial_study_id` **仅记「定植所属 study」**;跨年/跨点观测改由 `observation.trial_study_id + obs_year` 表达,不引入中间表,保单写点纪律 |
| 3 | 试验树 `germplasm_id` 时序张力(入试即需已知 vs 晋升才写) | 区分两类 tree:`planting.entry_id` 非空 ⇒ 参试无性系(`germplasm_id` 入试即定 = `entry.germplasm_id`);为空 ⇒ 杂种实生苗(待晋升)。以 entry 有无区分,无需新类型字段 |
| 4 | `split_plot` 设计已支持但 `experiment_factor/treatment` 延后 | `breeding_treatment`(factor+level) **提进一期(§3.14**,混合模型增 `treatment` 项,可估因子主效应与互作 |
| 5 | `seed_lot` 非事务致「获种数」源头不可靠 | `seed_lot``used_count`,派生 `remaining = seed_count - used_count`,选强链前段(获种→已用)可量化 |
> 本轮为**纯文档定稿(v1.5)**,未触碰任何代码。文档进入「v1.5 自洽修复版」,待 §7 minor(尤其生成器 A/B/C)确认后实施。
### 8.8 五轮复审(v1.62026-07-28)— 用户拍板"全部采纳"第五轮复审
用户就第五轮复审拍板"全部采纳",落档 v1.6(同时补齐 v1.5 因替换异常遗漏的 §3.14/treatment 行/used_count):
| # | 议题 | v1.6 处置 |
|---|---|---|
| A1 | 核心性状固定列(tree_evaluation)缺 trial_study_id 环境键 | tree_evaluation 加 `trial_study_id`(按年 observation 推导/直填),使核心性状纳入 MET 环境效应(修复 v1.5 裂痕) |
| A2 | planting 粒度未定义 | 明确 planting=block 级批次;同 entry 跨多 block 建多 planting |
| A3 | treatment 关联字段未落地 | 新增 `breeding_planting_treatment`(§3.15planting×treatment 多对多) |
| A4 | seed_lot.used_count 单位未定义 | 明确=已从该批取用**粒数**(播种环节按粒累加,非定植株数) |
| A5 | tree_photo.observation_id 文档自述已改但 §4 无行 | §4 补 `tree_photo` 行(observation_id |
| A6 | EBV 估 germplasm 级但 tree↔germplasm 重复测量未建模 | 明确 tree_evaluation/observation 按 `tree.germplasm_id` 聚合为 clone 重复,EBV 随机效应在 germplasm |
| B1 | marker 缺 assembly_version | marker 加 `assembly_version` |
| B2 | 基因型编码标准 | genotype_call.allele 声明 VCF/GP 编码(0/1/2=纯合ref/杂合/纯合alt |
| B3 | season 概念 | trial_study 加 `season` |
| B4 | observation 缺审核人/时间 | observation 加 `validated_by`/`validated_date` |
| B5 | 单位校验+批量换算 | observation 加 `unit`(冗余自 trait),导入服务做换算 |
| B6 | method/scale 受控词表 URI | trait 加 `method_uri`/`scale_uri` |
| B7 | planting 来源双路径 | planting 加 `propagation_id`(种子批/扩繁批二选一) |
| B8 | observationUnit level | 文档标注 tree/plot/block 对应 BrAPI observationLevels |
| B9 | kinship/A 矩阵 | §5 补系谱 A 矩阵(pedigree 解析) |
| B10 | selection_rule 支持 EBV | conditions_json 允许引用 prediction_valueEBV 阈值) |
| B11 | breeding_program 自由文本说明 | 文档标注 germplasm.breeding_program 暂自由文本、后续可升级 FK |
| C1 | selection_result 跨年晋级关联 | selection_result 加 `trial_study_id`(可空) |
| C2 | 新表数据权限接入 | 文档约束新模块须用 CRUDBase 自动注入数据权限 |
> 本轮为**纯文档(v1.6)**,未触碰任何代码。此后 v1.7(统计决策闭环)、v1.8(团队隔离收口)均为纯文档演进,未触碰任何 breeding 业务表/接口/代码。文档进入「v1.8 团队隔离定稿版」,待生成器 A/B/C 拍板后实施。
### 8.9 V2.11 方案书统计/决策支撑对照(v1.72026-07-28
用户要求评估《桃育种数字化项目方案书_V2.11》中「统计分析与决策支持」(专册 2.1–2.8 方法 / 3.13.4 决策)能否被 v1.6 支撑。结论:**方法面全部可支撑**(数据地基 / MET 维度 / 统计引擎接口齐备);发现 3 硬 + 2 软缺口,v1.7 全部闭环:
| # | 缺口 | v1.7 处置 | 类型 |
|---|---|---|---|
| ① | EBV 持久化时序冲突(值表标 V2.0,但趋势图 / 双轨选择 / 亲本单株决策需读持久化 EBV) | `breeding_prediction_value` 值表前移 V1.1,与统计引擎同期写入;GS 模型训练留 V2.0 | 硬 |
| ② | 负载量协变量未建模(专册 1.3 要求坐果量评级降果实性状环境误差) | `tree_evaluation.crop_load`(评级 1/2/3)作混合模型协变量 | 硬 |
| ③ | `breeding_report` 延后(专册 3.3.1 年度 Word/PDF 报告) | 用户确认一期必须:进 P2,补 `output_format` + 报告生成服务(docx/pdf 导出) | 硬/软(用户拍板"必须" |
| ④ | 数据质量自定义生物学阈值无落点 | `breeding_trait.valid_min/valid_max` 承载合理范围,供异常标记 | 软 |
| ⑤ | 超期预警/通知机制(专册 3.3.2 树 N 年未决策预警) | 列为工程项:cron + `selection_rule`/`selection_result` 触发通知,不阻塞数据模型 | 软 |
> 本次为**纯文档(v1.7)**,未触碰任何代码。文档进入「v1.7 统计/决策闭环版」,仅余生成器 A/B/C 待拍板。
---
### 8.10 深度复审 AH 全量落地(v2.2,2026-07-30,用户逐条确认 + F1/F2 拍板)
**变更索引**(每项均已在正文对应 § 落字):
| 编号 | 问题 | 裁决 | 落点 |
|---|---|---|---|
| A1 | `tree.clone_id` 定植必填与"clone=入选克隆"矛盾 | 实生苗定植可空、入选晋升才建 clone 回填;参试无性系必填 | §3.0/§4 tree |
| A2 | `produced_clone_id` 命名易读作"新建克隆" | 澄清=被扩繁原 clone、沿用不新建 | §3.8 |
| A3 | `rootstock_id` FK 三处打架 | 全文统一 FK→`breeding_rootstock`germplasm.is_rootstock 仅标记 | §1/§3.8/§4/§5.x |
| A4 | A 矩阵系谱来源双源 | 以 `breeding_pedigree` 为唯一权威,combination 仅派生源 | §3.18/§5.8 |
| B1 | h² 落在明细每行 | 上移主表 `breeding_prediction`(一次 BLUP×一性状=一 h²) | §3.12 |
| B2 | "广义遗传力"误称 | 正名加性(狭义) h²,落库取克隆均值 h²=V_clone/(V_clone+V_e/k̄) | §3.12 |
| B3 | 缺 sommer 基线公式 | 补 `mmer(y~rootstock+site+year+block, random=~vsr(clone,Gu=A)+vsr(clone:year))` | §5.2 |
| B4 | 双轨选择粒度错配 | 统一 clone 级判定(表型先聚合到 clone 均值) | §5.9 |
| C1 | 门禁作用于固定列 | 改作用于 `breeding_trait_observation` 长表 | §3.16 |
| C2 | 缺质量标记字段 | 加 `issue_status`normal/pending/rejected),不新建表 | §3.2/§3.2b |
| C3 | 门禁与状态机脱节 | 拒收→rejected+draft;异常→pendingnormal+validated 才进池 | §3.16 |
| D1 | selection_result 无 clone 级 | 加 `clone_id`tree_id 留溯源) | §4 |
| D2 | clone 无世代 | 加 `generation`(可由 combination 派生) | §3.0 |
| D3 | entry 未落 clone | `trial_study_entry``clone_id` | §3.4 |
| D4 | tree↔clone 状态流转缺矩阵 | 补状态流转矩阵(下) | §8.10 |
| F1 | 固定列 vs 长表三方打架 | **裁定单一长表、废固定列、报表用视图** | §0/§3.2/§4/§8.4 |
| F2 | 两长表命名/职责重叠 | 保留两张、按"是否喂 EBV"正交;补登记 `breeding_trait_observation` | §2/§3.2/§3.2b |
| F3 | 门禁键含 clone_id 拒收实生苗 | 实生苗阶段单元键退化为 tree_id | §3.16 |
| F4 | 判重键删合法 clonal replicates | 判重键含 tree_id | §3.16 |
| F5 | §5.2 公式漏 rootstock | 公式补 rootstock 固定效应 | §5.2 |
| G1 | 编号服务未定义 + 序号位宽不足 | 定义统一编号服务(下)、clone 序号≥4 位 | §3.0/§8.10 |
| G2 | 手册"不可删只留痕"落点缺 | 鉴定类表禁物理删+UPDATE 强制 audit | §3.10 |
| G3 | method 文本 vs method_uri 受控 | 合并声明两字段并存 | §3.1 |
| H1 | valid_min/max 全局单值 | 接受全局+人工复核,可 scale_json 分档 | §3.1 |
| H2 | environment 与 site/year 共线 | environment=具体气象协变量,非再建 site×year 层 | §5.2/§3.9 |
| H3 | group_member 挂 tree/clone 未定 | 加 clone_id 成员 | §3.5 |
**G1 · 统一编号生成服务(定义)**:集中式编号服务按前缀 + 顺序号生成,全局唯一、可追溯,并发下加行锁/序列保证不重号:
- `accession_no`(种质):`GP-{组来源}-{6位序}``combination_no`(组合):`CC-{年}-{4位序}``tree_no`(单株):`{combination_no}-{4位株序}`(定植时生成);`clone_id`(克隆):`{combination_no}-{≥4位单株序}`(**入选晋升时**由服务生成,非定植时,A1);`trial_code``TR-{年}-{3位序}`
- clone 序号扩至 **≥4 位**(容纳单组合数千株,解决原 3 位=999 上限,G1)。
**D4 · tree ↔ clone 状态流转矩阵**
| 阶段 | tree.status | 是否建 clone | breeding_clone.status | selection_result | 说明 |
|---|---|---|---|---|---|
| 定植(杂种实生苗) | 入选(默认) | 否(clone_id 空) | — | — | 童期观测按 tree_id 聚合 |
| 初选晋升 | 初选 | **是(建 clone、回填 clone_id** | 入选/初选 | 写一行(clone_id+tree_id | 门禁键切 clone_id、启用 A 矩阵 |
| 复选/重点 | 重点 | 沿用 | 重点 | 追加流转 | clone 级 EBV 多年重复 |
| 保存 | 保存 | 沿用 | 保存 | 追加 | 资源保留 |
| 淘汰 | 淘汰 | 沿用(状态变更非删除) | 淘汰 | 追加淘汰记录 | **禁物理删/软删,G2** |
| 参试无性系(entry 批) | 入选 | 定植即有 clone | 入选 | — | 定植即 clone 级 |
**F2 · 命名对照(消除"代码有、文档无"**:模块/URL/权限 = `trait_observation`;模型类 = `TraitObservationModel`**物理表 = `breeding_trait_observation`**(与全项目 `breeding_*` 前缀一致)。文档指物理表用后者,指模块用前者。
---
### 8.11 统计引擎两轮 P0 代码落地台账(v2.32026-08-03/04,代码级)
> 本规格自 v2.0 起为**方案态**(待"做"落地)。2026-08-03/04 将其中两条统计地基从方案推进到**代码落地 + e2e 验证**。本节为落地台账摘要,完整明细(含文件清单/备份/复跑命令)见 `桃育种系统统计引擎实施记录.md`。
**① G×E 交互引擎(2026-08-03**——对应 §5.2「G×E」互作项落地:
| 规格点 | 落地 |
|---|---|
| G×E 随机互作 | `run_ablup(gxe=True, gxe_env=site/year)``method=GXEBLUP``gxe=False` 回归纯 ABLUP |
| 环境维度 | `site`→自动固定效应 `trial_study``year`→自动固定效应 `year`(调用方可显式追加 `fixed_effects` |
| 交互量 | σ²gxe / gxe_ratio / n_cross_env 落 `breeding_prediction.note` JSON |
| 可辨识性门禁 | 无跨环境重复 / 单元内无重复 → 409「G×E 不可辨识:…」 |
| 克隆坍缩 | 同 clone 多株坍缩为基因型节点 `c{clone}`record_map 全映射),同 clone EBV 一致 |
| 异步任务 | `StatisticsJobModel` job_type=GXE/ABLUPSUCCESS/FAILED + error_msg(门禁失败亦落) |
| 验证 | `e2e_gxe_20260803.py` 5 场景全过(spy 捕获 fixed/record_map kwargs |
**② 性状方向标注(2026-08-04**——对应 §3.1 / §5.9 / §5.z 落地:
| 规格点 | 落地 |
|---|---|
| 三字段 | `breeding_trait.direction/into_ebv/default_h2`(幂等 ALTER `weld_trait_direction.sql` + 种子 43 行 ON CONFLICT 含新列) |
| 指数翻转 | zsum 对 asc 性状 z 取负、smith_hazel 对 asc 元素 a 取负 → 统一"越大越优",低优性状不选反 |
| into_ebv | `'0'` 从指数候选/EBV 排行/决策预览/ABLUP 下拉剔除(`extra.dropped` 提示);describe/correlation/trait_values 不受影响 |
| default_h2 兜底 | 指数无实测 h² 用先验兜底(zsum/smith_hazel 均兜底,两者皆无才 409 |
| 排行方向 | `run_ablup` 写时按方向排序;`ebv_ranking` **读时重排**(结构性 bug 修复);`clone_ranking` 方向感知 |
| 轮次对比 | `compare_predictions` 方向感知(结构性 bug 修复) |
| 前端 | statistics `selTraits` 解耦(与 describe/correlation 共享列表分离)+ trait 表单三字段 + selection_rule 说明 |
| 验证 | `e2e_direction_20260804.py` 7 组全过(4 性状 × 4 批次 × 12 株 EBV 基线) |
---
### 8.12 花粉档案落地台账(v2.42026-08-04,代码级)
> 用户田间刚需:桃花期仅 3–7 天,父本花粉是杂交季命脉,原授粉表无花粉采集/贮藏/活力/窗口,复盘坐果率无抓手。本轮新增 `breeding_pollen`(§3.19+ 授粉表 `pollen_lot_id`/`pollination_method`e2e 验证通过。完整明细见 `桃育种系统统计引擎实施记录.md`。
| 规格点 | 落地 |
|---|---|
| 新表 `breeding_pollen` | `weld_pollen.sql` 幂等 DDLCREATE TABLE IF NOT EXISTS + 索引 + COMMENT+ 模型注册(create_all 经 import 链拾取) |
| 父本锚点 | 树级 `male_tree_id` FK→bre_tree SET NULL(可空;`source_type`=tree/mixed/external 区分来源) |
| 活力建模 | 单值+方法:`viability_method`(ttc/germination)+`viability_pct`+`viability_test_date`,不建子表 |
| 授粉窗口 | 派生有效期:窗口=[collect_date,expiry_date]pollination create/update 校验授粉日期在窗口内否则 409;`/bre/pollen/available_lots` 返回当前窗口内批次 |
| 授粉表补字段 | `pollen_lot_id` FK→bre_pollen SET NULL + `pollination_method`(一期文档规划但遗漏,授粉方式) |
| 去重/FK | 批次号唯一预检(409「已存在」);父本树不存在→409(`assert_parents_exist` 自动跳过空值) |
| 菜单/权限 | 900056 花粉档案(杂交配组 900030 下)+ 按钮 E 段 900601-900608;角色关联含新段 |
| 前端 | `pollen` CRUD 页(贮藏/活力下拉、采集/测定/有效期日期)+ 授粉表单集成批次选择(窗口提示)+ stage_cross 第三标签 |
| 验证 | `e2e_pollen_20260804.py`create/去重/FK/list/detail/options/available_lots/窗口内授粉/窗口外 409/update/delete 全过;`vue-tsc` 通过 |
---
### 8.13 选择指数·无性系级聚合落地台账(v2.5,2026-08-04,代码级)
> **决策正确性 P0.3**:桃无性繁殖,选择指数按"树级"算指数会把**同一优系多株拆成独立条目**——可能只选中其中 1 株而漏掉该系其他株,也不利"系级决选"。本轮把指数单位升为**无性系级**(§5.3/§5.7 落地),e2e 验证通过。完整明细见 `桃育种系统统计引擎实施记录.md` v1.2。
| 规格点 | 落地 |
|---|---|
| `aggregate` 参数 | `selection_index` 新增 `aggregate`(默认 `clone``tree`=旧单株级行为保留) |
| clone 聚合单元 | `_clone_units`:按 `tree.clone_id` 分桶成遗传实体;EBV 均值**可靠性加权** `Σ(ebv×rel)/Σ(rel)`,全 rel=0 回退简单均值;表型均值走简单均值 |
| 自株退化 | 无 clone_id 的未晋升实生株 → 单元 key=`-tree_id`(每株独立,不进聚合),实生苗阶段不塌缩 |
| 排名单位 | zsum / Smith-Hazel 均在 clone 单元上算(方向感知沿用 v2.3:统一越大越优) |
| `apply_selection` 粒度 | 按遗传实体写决选:入选 clone 一条 `selection_result``clone_id` 指向全系 + `tree_id` 溯源一株 + reason「系内N株」);self 株逐株写 |
| 晋升建 clone | 入选 self 株命中规则 stage → `_promote_tree_to_clone` 幂等晋升建 clone`tree.clone_id` 回填) |
| 前端 | statistics 工具栏「聚合:无性系级/单株级」radio + 结果表 clone 列(clone_code/n_trees/涉及单株);API 类型补 `aggregate` |
| 验证 | `e2e_clone_index_20260804.py` 6 组全过(聚合单元/可靠加权排名翻转/tree 兼容/方向翻转/smith_hazel clone/apply 写入粒度+晋升) |
### 8.14 配合力交配设计落地台账(v2.6,2026-08-04,代码级)
> **统计严谨 P0.4**`combining.solve` 原只实现 Griffing 对称全双列(model A),但 `run_combining` / `bre_combining_ability` 无 `design_type`——用 line×testerNCII)设计时 GCA/SCA 算法与 ANOVA 自由度都与全双列不同,此前一律按全双列算**会算错**。本轮加 `design_type` 并按设计分支。完整明细见 `桃育种系统统计引擎实施记录.md` v1.3。
| 规格点 | 落地 |
|---|---|
| `design_type` 取值 | `bre_cross_combination` + `bre_combining_ability``design_type``full_diallel`(默认)/`partial_diallel`/`line_tester`/`nciii`;硬编码校验(同 `selection_index.method`,非 sys_dict),create/update 接受 code 或中文标签并归一化,非法值 409 |
| 求解器分支 | `combining.solve(rows, design_type)``full_diallel`/`partial_diallel` → Griffing 对称全双列 `y=μ+g_i+g_j+s_ij`(Σg=0,最小二乘 BLUE);`line_tester`/`nciii`**NCII 双因素模型** `y=μ+l_i+t_j+(lt)_ij`parent1=line 母本、parent2=tester 父本,分别 Σl=0/Σt=0SCA=line×tester 互作=残差);NCIII 同模型但门槛 tester 恰 2 个 |
| 可辨识性 | tester 列从索引 `1+n_l` 起 → **显式列选择**(非连续切片);基线列切出后吸收剩余列 |
| 顺序 ANOVA | SS_lineintercept→line)→ SS_tester(→tester)→ SS_sca(残差);df_line=n_l-1、df_tester=n_t-1、df_sca=n-1-两 df;输出 `design`/`roles`/`df_line`/`df_tester`/`df_sca` |
| 门禁 | 同亲本既作 line 又作 tester(角色重叠)→ 任务 FAILED + CustomException「角色重叠」;NCIII tester≠2 → 拒绝 |
| `gca_se` 持久化 | GCA 标准误内嵌 `anova_json["gca_se"]`(避免 DB 迁移,gca_json/sca_json 形状稳定);前端 GCA 表加 SE 列 |
| 运行过滤 | `run_combining` 按设计过滤:只纳入 `design_type` 一致(或未标注按 `full_diallel`)的组合,杜绝全双列组合混入 line×tester 运行 |
| 前端 | statistics 运行对话框加交配设计 radio;配合力批次表加「设计」列;详情 ANOVA 按设计分支显示(NCII/NCIII → line/tester/互作 F 与 p;双列 → GCA F);cross_combination 表单/表格/详情/搜索全量支持 `design_type` |
| 验证 | `e2e_combining_design_20260804.py` 5 组全过(NCII 2×2 精确解 gca{l:-2,+2,t:-1,+1} + df 1/1/1 + gca_se 内嵌 + full_diallel 组合被过滤;NCIII 分支;角色重叠 gatecreate/update 校验含中文标签归一化;commit 后跨会话持久化)+ `vue-tsc` |
### 8.15 统计严谨·预测完整性与 MLOps 复现性落地台账(v2.72026-08-04,代码级)
> **七条复审逐条核实为真缺陷后全部落地**(用户逐条确认"逐条来",优先级:便宜且值得马上补 ②④ → 中期 ③⑤ → 需新能力 ①⑥)。完整明细见 `桃育种系统统计引擎实施记录.md` v1.4。
>
> **遗留(已记账,不动引擎)**:真 **MT-BLUP** 多性状 G 需全新多变量 REML 求解器(Kronecker 积 G/R + 方差分量迭代,数值收敛风险大),本轮用 **Calo 可靠性校正**(业界回退的严格改进版)先顶上——`r_g = r_EBV/√(rel_i·rel_j)`,直接消费 ② 落库的 reliability,无新求解器;`extra.g_corr`/`g_note` 落 `bre_selection_index.result_json` 可审计。
| 规格点 | 落地 |
|---|---|
| ② PA 落库 | `bre_prediction_value``pa double precision`=√reliability,预测准确度);批次 `bre_prediction.accuracy` 改填**真 PA = √(均值可靠性)**(原误填"均值的平方根量纲不符",注释正名),`numeric(5,3)` 3 位小数 |
| ③ MLOps 溯源 | `bre_prediction``data_version varchar(32)``_DATA_VERSION="v2.7"`/ `input_hash varchar(64)`SHA256`{tree_id}:{均值表型}` + `{个体}\|dam\|sire` 确定性序列化)/ `engine_version varchar(32)``blup.ENGINE_VERSION="1.0.0"`);**同数据重跑哈希一致、改 1 条观测哈希必变**(数据漂移可检测),e2e 断言 |
| ④ germplasm_id 填充 | `run_ablup` 写 EBV 行填 `tree.germplasm_id`(晋升回填的种质,非手填);亲本级 EBV 查询可用(e2e:按 gA 查得 2 条);无种质株保持 NULL(合规) |
| ⑤ 砧木字典扩列 | `bre_rootstock``dwarf_class varchar(32)`(矮化/半矮化/乔化/柱状/其他)+ `compatibility varchar(16)`(砧穗亲和性强/中/弱)——选配决策信息;`weld_rootstock.sql` 幂等 ALTER;模型/schema/service(导出/导入/模板下拉)全链路 + 前端 表单/表格/详情/搜索 |
| ① Smith-Hazel 遗传相关 | `_smith_hazel_index` G 矩阵非对角改 **Calo 校正**`r_g = r_EBV/√(rel_i·rel_j)`(rel 取配对树该性状均值),钳制 [−1,1],可靠性缺失/近零 → 0(保守);`extra["g_corr"]`(性状对)+ `extra["g_note"]` 落结果 JSON |
| ⑥ 空间竞争协变量 | `run_ablup` 新增 `covariate="competition"`:同 **(plot_id, block_no)** 网格内 Chebyshev 距离 1(8 邻域,不含自身)株数作协变量——相邻越多竞争越强、边缘株相邻少隐式捕捉边缘效应;G×E 分支同步支持;**全无 row/col → 显式 CustomException**(数据需求判定);`bre_tree.row_no/col_no` 数据能力已全链路就位(模型/前端录入/表格/详情/导入导出) |
| 前端 | 指数批次表加 `germplasm_id`/`pa` 列;ABLUP 运行对话框协变量改**单选**(无 / crop_load / competition);rootstock 页面全量扩列 |
| 验证 | `e2e_prediction_rigor_20260804.py`(②③④:PA=√rel 逐条 + 批次真 PA + 溯源三字段 + 哈希复现/漂移 + germplasm 级查询 + ebv_ranking 透出 + 跨会话持久化)`e2e_rootstock_20260804.py`(⑤ CRUD/搜索/导出/模板/DB 直查)`e2e_corr_spatial_20260804.py`(① Calo 值独立重算一致 + ⑥ EBV 差分消费验证 + 无坐标报错)+ `vue-tsc` 全过 |
### 8.16 组合得失漏斗 v_combination_funnel 落地台账(v2.82026-08-04,代码级)
> **用户主张**(逐条复审第 8 条,最贴业务):数据其实捕获齐全了——`bre_pollination.flower_count/effective_count`(花→果)、`bre_seed_lot.seed_count/germination_rate`(种→苗)、`bre_seedling.seedling_count`(出苗)——但**没有任何按 `bre_cross_combination` 汇总的派生指标**:结实率、出苗率、选择强度没有滚到组合层,配合力第一手证据(组合得失链路)字段在但没合成进配合力上下文。**核实属实**:全库 grep 结实率/出苗率/选择强度/funnel 无实现;唯一"选择强度链"是 `seed_lot.used_count` 机械累加(seedling/planting 按出苗/定植回写,账本非派生指标);`run_combining` 的 rows 只取 `func.avg(value_numeric)` 组合均值(`service.py:708-748`)、`combining.solve` 只认 `combo/parent1/parent2/value`。**用户拍板范围:补一个 combination_funnel 视图/派生表即可,数据已齐、风险极低。**
| 规格点 | 落地 |
|---|---|
| 六级链路 | 花 `bre_pollination`(Σflower_count/Σeffective_count)→ 果 → 种 `bre_seed_lot`(Σseed_count/AVG germination_rate)→ 苗 `bre_seedling`(Σseedling_count/strong_seedling_count)→ 定植 `bre_planting`(Σtree_count)→ 树 `bre_tree`(非软删 COUNT)→ 入选 `bre_selection_result`(非软删 COUNT |
| 派生指标 | **结实率** `fruit_set_rate` = Σeff/Σflower×100**出苗率** `emergence_rate` = Σseedling/Σseed×100**选择强度** `selection_rate` = 入选数/树数×100(逐级各留原始计数可复查);缺环节组合比率列留 NULL(LEFT JOIN 正确性) |
| 视图 | `v_combination_funnel``weld_combination_funnel.sql` 幂等 DROP IF EXISTS + CREATE OR REPLACE,普通 VIEW 保 freshF2 决策:统计管线用普通 VIEW,不用 MV),`bre_cross_combination` 主表 LEFT JOIN 六源、按组合一行;create_all 只建 ORM 表,视图经 psql 应用 |
| 端点 | `GET /statistics/combination-funnel``module_bre:statistics:query` 权限)→ `StatisticsService.combination_funnel()` 查视图返回 `{rows, n}`Numeric→int/float 归一);视图未就绪时 CustomException 提示先应用 SQL |
| 消费 | 配合力上下文第一手证据落地:查某一组合可得 花→果→种→苗→定植→树→入选 全程漏斗,解释 GCA/SCA 差异时按组合得失对照(如低 GCA 组合是否因出苗率低样本崩缩) |
| 验证 | `e2e_combination_funnel_20260804.py`:全六级组合 150 花/50 果→结实率 33.33%、100 种/80 苗→出苗率 80%、55 定植/3 树/2 入选→选择强度 66.67%,精确断言;仅授粉组合 fruit_set=50%、其余全 NULLcommit 后跨会话读同值。**注**:首跑清理阶段 FK 崩(helper flush 前取 `.id` 拿到 None),修 flush 顺序后全过 |
### 8.17 精修项四连发落地台账:DUS 数据能力 + stage 感知 + k-fold CV + 公平性报告(v2.92026-08-04,代码级)
> 用户核实四条精修缺口、全部拍板「落地」(并保留版本):① **DUS/品种保护**——无模块、无 UPOV TG/53 描述符模板(§2 总表 ⏳待建),按拍板档位**数据能力(三表)**;② **stage 感知**——`trait.stage`v2.0 ①定义)未被 BLUP/选择指数/决策消费,童期/成株混用无警示;③ **模型外部验证**——可靠性仅 PEV 法,补 k-fold CV**ABLUP + GXEBLUP 双支持**);④ **AI 伦理·分组偏差**——G×E 引擎已覆盖互作,补按 site 的系统性 EBV 偏差/公平性报告。完整明细见 `桃育种系统统计引擎实施记录.md` §九。
| 规格点 | 落地 |
|---|---|
| ① DUS 三表 | `bre_dus_descriptor`(描述符模板:descriptor_no 唯一 UPOV TG/53 特性号、trait_id→bre_trait **可空**=自由描述符、trait_code 快照、expression_type QN/PQ/QL、method、example_varieties 标准品种、test_stage、required/ `bre_dus_test`(测试记录:test_name 唯一、germplasm_id→申请品种、trial_study_id→测试点、tester/test_date/status(planning/testing/completed/report)/conclusion(pending/distinct/not_distinct)/report_path/ `bre_dus_observation`(观测:dus_test_id/dus_descriptor_id 双 FK、value_numeric/value_text/expression_note、UNIQUE(test,descriptor));create_all 建新表(非既有 DDL);五件套模块 `module_bre/dus/` 注册 `/bre/dus_test/*`descriptor 9 端点含 Excel 导入导出+模板下载,test 9observation 6 |
| ① TG/53 种子 | `sql/bre_dus_seed.sql`UPOV TG/53 桃描述符 15 条(树性/树势/叶形/花型/花期/果形/果皮底色/着色程度/茸毛/果肉色/离核性/成熟期/风味/平均单果重/可溶性固形物),`trait_code → bre_trait LEFT JOIN` 解析 trait_id**8 条关联**),`ON CONFLICT(descriptor_no) DO NOTHING` 幂等;descriptor 导入导出/模板中文头(关联性状编码 → trait_id) |
| ① 菜单 | `sql/bre_menu_refine.sql`900230 component 切真实页 `module_bre/dus/index`**G 段按钮 900800-900808**perm `module_bre:dus_test:*`,含导入/下载模板)+ SUPER_ADMIN/ADMIN 角色关联 |
| ② stage 感知 | `_trait_meta_map` 读入 `trait.stage`(缺省 evaluation);`PredictionModel.stage` 落库(`sql/weld_refine.sql` 补列)+ 预测批次表展示;`selection_index``stage` 入参——传 juvenile/evaluation 只纳入该阶段性状(异阶段写入 `skipped_stage`,同阶段无性状→409 带剔除清单)、不传且横跨两阶段返回 `stage_warning`(童期/成株清单 + 复核提示);`decision_preview` 同样——传 stage 时异阶段规则条件跳过(matched=None)、不传且规则引用性状横跨两阶段返回 `stage_warning` |
| ③ k-fold CV | 求解器 `blup.kfold_cv`:按 **sire 家系分层留出**(同家系不进训练/测试双折避免乐观,无父本个体自成一系),每折训练子集重估方差组分 → 留出个体 EBV 由系谱预测(个体保留在 A 矩阵、仅掩蔽表型)→ pearson+RMSE;单折失败(train<2 / G×E 结构不可辨识)记 None+warning 不中断;返回 mean/pooled pearson/RMSE、cv_accuracy(=mean_pearson)、h2。端点 `POST /bre/statistics/cv/run`trait_id/code/year/fixed/covariate/**gxe/gxe_env**/k 2~10ABLUP 与 GXEBLUP 同入口)→ 落 `bre_cv_result`method=KFCV/ABLUP|KFCV/GXE,溯源 data_version/input_hash/engine_version 复用)+ `bre_cv_fold` 明细;`GET /bre/statistics/cv`(批次)+ `GET /bre/statistics/cv/{id}`(含折明细) |
| ④ 公平性报告 | `GET /bre/statistics/fairness?prediction_id=&group_by=site&threshold_sd=`(只读不建表):`site_summary` 每 site n_trees/n_groups/n_individuals/EBV 分布(mean/sd/min/max/mean_reliability/**deviation=site_meangrand_mean**、`flagged=\|deviation\|>threshold_sd×grand_sd``rank_consistency` site 内组合均值 EBV 排名 vs 全体组合排名、共享组合 ≥2 时手写 Spearman;`gxe_pattern` 组合×site 单元均值(n≥2)暴露跨 site 排名翻转 |
| 前端 | `dus.ts` 3 组 API + `dus/index.vue` 三 tab(描述符模板/DUS 测试/观测录入)CRUD 页;`statistics.ts` 加 runCv/listCv/cvDetail/fairnessReport + 类型;`statistics/index.vue` 加「交叉验证」tab(性状+k+gxe 开关+批次+折明细)与「公平性报告」tabprediction+threshold_sd+site 偏差表+一致性表)、指数/决策对话框加 stage 三态下拉 + `stage_warning` ElAlert`vue-tsc` 通过 |
| 验证 | `e2e_refine_20260804.py` 4 组全过:DUS 三表 CRUD + TG/53 种子命中 + FK/唯一键/子表阻断/软删 409 全路径;stageselection_index 无过滤警示 + 过滤只含该阶段 + decision_preview 异阶段跳过 + ABLUP stage 落库);CVABLUP k=3 sire 家系留出折 pearson=0 为设计预期 + GXE k=2 跨 site + 幂等重跑新批次 + 溯源/任务状态);fairness2 site 9 株 site_summary 2 行 deviation 异号 + rank_consistency spearman + gxe_pattern);后端 openapi 确认 DUS/CV/fairness 路由注册,清理自动执行 |
---
### 8.18 六项能力完善落地台账:MT-BLUP + GBLUP/ssGBLUP + DUS 特异性检验 + AMMI/FW 稳定性 + MLOps 重训回滚 + BLUP stage 拆分(v2.102026-08-04,代码级)
> 用户两轮复核核实六条能力缺口、逐项拍板「全部落地」:① **MT-BLUP**——Smith-Hazel 的 G 非对角仍用 Calo 校正 EBV 相关近似,拍板**成对双性状 BLUP**(非全多变量 REML);② **GBLUP/ssGBLUP**——分子层只有数据能力(四模块 CRUD + VCF + 指纹),无 VanRaden G / 基因组选择引擎,item 明确两者都做;③ **DUS 特异性统计检验**——`conclusion` 纯人工、无判定端点,拍板**参照=同 trial_study 自动 + 可显式指定**;④ **AMMI/Finlay-Wilkinson 稳定性**——G×E 已估 σ²gxe,无跨环境稳定性排名;⑤ **MLOps 自动重训 + 版本回滚**——拍板**漂移检测端点 + 手动触发**,不注册 cron;⑥ **BLUP stage 拆分**——run_ablup 只打标签不按 stage 取数。完整明细见 `桃育种系统统计引擎实施记录.md` §十一。
| 规格点 | 落地 |
|---|---|
| ① MT-BLUP | 求解器 `mtblup.solve_bivariate`ENGINE_VERSION=1.0.0):共享系谱复用 `blup._order_pedigree/_build_ainv` 建 A/A⁻¹,y=[y1;y2] 堆叠 X/Z 块对角,Var(u)=G0⊗AG0=[[Va1,ρ√(Va1Va2)],[·,Va2]])、Var(e)=diag(Ve1,Ve2)⊗I**降维策略**Va/Ve 取自各性状单性状 REML,仅对 ρ∈[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。Service `run_genetic_corr(trait_ids,year)`:两两 bivariate,对角=单性状 h²·P_ii、非对角=r_g·√(G_ii·G_jj) 组装 G0Higham 特征值截断投影半正定;落 `bre_genetic_corr_result`matrix/sigma_a/heritability/pairs_json/n_common + 溯源三字段)+ job_type=GENCORR`_smith_hazel_index``g_method="calo"\|"mtblup"`selection_index 透传)——mtblup 逐对跑 bivariate,单对不收敛回退 Calo+warning,≥3 性状三角不等式违反时特征值截断,`extra["g_source"]` 落库可审计 |
| ② GBLUP/ssGBLUP | 求解器 `genomic.py`ENGINE_VERSION=1.0.0):`build_g_matrix`dosage 0/1/2 样本×标记,缺格按列均值 2p 填充,MAF 过滤,VanRaden **method1** G=ZZ'/2Σp(1-p)diag≈1/ **method2** G=ZDZ'D=1/[2p(1-p)]),blend 岭 G_w=(1−ω)G+ω·mean(diag)G·I 保证可逆);`solve_gblup`(仅基因型个体入模型,MME 用 G⁻¹ 替代 A⁻¹,σ²a 用 `_golden_max` profile 仿 blup.solve);`solve_ssgblup`**单步法** H⁻¹=A⁻¹+[[0,0],[0,G⁻¹−A22⁻¹]]Aguilar et al. 2010),A22=A[genotyped,genotyped] 稠密子阵 np.linalg.inv(病态加 ridge),**V 块必须用 H 协方差**——Aguilar 块公式构造完整 HH=A+[[A12·A22⁻¹·D·A22⁻¹·A21, A12·A22⁻¹·D],[D·A22⁻¹·A21, D]]D=GA22),MME 系数矩阵用 H⁻¹、REML 似然 V=ZH[z,z]Z'+R;修复前 V 块误用 H⁻¹ 致似然失构),基因型+非基因型个体都出 EBV。Service `run_gblup(dataset_id,trait_id,trait_code,year,method,maf_min)`:取数 sample×marker pivot 剂量("0/0"→0/"0/1"→1/"1/1"→2,多等位跳过),样本→个体映射 source_type='tree' 直连 + sample_name↔tree_no/品种名名称兜底,未映射→跳过+warning 清单(note 落库);`genotyped=sorted(dosage)` 对齐 build_g_matrix 内部行序(修复前映射树零有效调用会错位 EBV);落 PredictionModelmethod=GBLUP/ssGBLUP,含溯源三字段)+ EBV 行 + job_type=GBLUP |
| ③ DUS 特异性 | 求解器 `dus.distinctness`(复用 fdist):QN `LSD = t_crit(α,df)·√(MSE·(1/n_cand+1/n_ref))`(df=总观测−参照组数;t_crit 由新增 `fdist.f_icdf` 二分反解 F(1,df) 再开方);PQ/QL 表达状态众数比较(候选众数 ∉ 参照众数集 → distinct);逐描述符 {statistic,critical,distinct},总体建议=≥1 个 **required** 描述符 distinct → distinct,否则 not_distinct,数据不足→pending(不判)。端点 `POST /bre/dus_test/distinctness/{test_id}`body {reference_test_ids?**默认同 trial_study 其他非软删 test 自动参照**,可显式覆盖;alpha=0.01})——取候选+参照观测+描述符,跑判定**落 `analysis_json`**(逐描述符表+建议+参照集+alpha),`conclusion` 为 pending 时自动填建议(人工可改);`GET /bre/dus_test/distinctness/{test_id}` 读已存分析;DusTestOutSchema 加 analysis_json |
| ④ 稳定性 | 求解器 `stability.py`ENGINE_VERSION=1.0.0):`finlay_wilkinson` 每基因型对**环境指数**(该环境全基因型均值)回归 b/截距/R²/se_b/dev_ms`flag_stable=\|b1\|≤2·se_b`(**完美拟合残差≈0 时 se_b 无信息量 → b≈1(≤1e-6)判稳**,修复前浮点 b 永不精确=1 误判不稳);`ammi` 两因素 μ+g+e 分解→残差 SVDnp.linalg.svd)→IPC 得分/ASVPurchase 2000IPC1 按 SS 比例缩放合成)/Wricke ecovalence/ipc_variancerank 按 ASV 升序。Service `run_stability(trait_id,trait_code,gxe_env=site/year,year,methods)`:两向表 genotype=clone(缺则 combination,再退 tree)× env=site(trial_study_id)/year(evaluate_year),每格多株均值;格子 <2×2 → 409;落 `bre_stability_result`detail_json+溯源三字段)+ job_type=STABILITY |
| ⑤ MLOps | weld `bre_prediction.is_active boolean default false`run_ablup/GXE/GBLUP 落库:同 trait 无 active → 本批 active,否则 false**版本链语义**)。`GET /statistics/model/drift?prediction_id=`——从批次 job params_json 取 (trait_id,year,gxe,gxe_env) → 轻量 `_gather_digest_inputs`(仅组装进 `_input_digest` 的 phenos+pedigree,规避全量抽取)重算当前哈希 → {changed,current_hash,stored_hash,data_version}`POST /statistics/model/retrain?prediction_id=`——**漂移才重训**run_ablup(同 params) 建新批次并 `model_activate(new_id)` 转移 active(修复前新批次默认 inactive 卡在旧批次下)→ {retrained,old_id,new_id,new_hash},无漂移 → {retrained:false,reason}`POST /statistics/model/activate/{id}`——trait 内标 active(回滚原语);list_predictions/PredictionOut 加 is_active |
| ⑥ stage 拆分 | weld `bre_trait_observation.stage varchar(16)`(观测级发育阶段,缺省继承 trait.stage);TraitObservationModel+schemacreate/update/out+ 前端观测表单 stage 下拉(juvenile/evaluation);`run_ablup(stage)` + RunStatsIn.stage:给定 → 取数 `where(coalesce(obs.stage,trait.stage)==stage)`model_name 加 `_{stage}` 后缀 + PredictionModel.stage=生效 stage;未给定但数据 obs.stage 与 trait.stage 出现分歧 → note 警示(不阻断);GXE 分支同步应用 |
| 端点汇总 | `POST/GET /bre/statistics/genetic-corr(/run/{cid})``POST /bre/statistics/gblup/run` + `GET /bre/statistics/gblup/datasets`(批次/EBV 复用 list_predictions 按 method 过滤 + ebv_ranking)、`POST/GET /bre/statistics/stability(/run/{sid})``GET /bre/statistics/model/drift` + `POST /bre/statistics/model/retrain` + `POST /bre/statistics/model/activate/{prediction_id}``POST/GET /bre/dus_test/distinctness/{test_id}`、selection_index 请求体加 `g_method` |
| 前端 | `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 表)三 tabABLUP 运行对话框加 stage 三态(全部/童期/成株),Smith-Hazel 对话框加 g 矩阵来源 radioCalo/MT-BLUP),预测批次表加「当前版本」标签+漂移检测/自动重训/设为当前版本按钮;`dus/index.vue` DUS 测试行加「特异性判定」按钮→对话框(alpha+参照默认同点+逐描述符结果表+建议)→「应用判定」写 conclusion;`vue-tsc` 通过 |
| 验证 | `e2e_advanced_{stability,stage,mtblup,gblup,dus,mlops}.py` 6 组全过:stabilityFW b=2.0/1.0/0.0 flag=F/T/F、AMMI 9 格 IPC1≥IPC2 rank 升序、year 维度、非法 methods 409、list/detail);stagejuvenile/evaluation 各只含对应观测树、不传含全部+note 警示、非法 stage 409);mtblupr_g>0.3 对称、σa 对角>0、h²∈(0,1)、n_common=4、Smith-Hazel g_method=mtblup g_source 落库);gblupGBLUP 5 EBV 非基因型株=0 + ssGBLUP 非零 + solve_ssgblup V 块用 H、G method1 diag_mean≈1、样本 4 直连+1 名称兜底+1 多等位+1 未映射 warning、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→幂等 false→activate 回滚);后端重启后 openapi 确认 6 组新端点 + 2 新表(bre_genetic_corr_result/bre_stability_resultcreate_allweld_advanced.sql 幂等;清理自动执行 |
---
### 8.19 田间试验精度补强·砧木×接穗随机互作落地台账(v2.11,2026-08-04,代码级)
> 用户核实两条田间试验设计精度缺口——无 R 侧空间协方差(行-列 AR1×AR1)、无 scion×rootstockG×R)随机互作(rootstock 当前仅固定哑变量);拍板**先做 G×R 随机互作**(空间协方差留待补 row/column 字段后再议)。核心洞察:G×E 分支 `_solve_gxe` 的 Z₂ 已按 `(基因型,因子水平)` 分组配 `I·σ²` 交互、**因子无关**,G×R 直接复用;但 Z₂ **单槽位 → G×E/G×R 必须互斥**。完整明细见 `桃育种系统统计引擎实施记录.md` §十二。
| 规格点 | 落地 |
|---|---|
| 求解器 | `blup._solve_gxe``factor_label="G×E"/factor_name="环境"` 可选参数(仅喂警告文案:未收敛「{factor_label} 似然面可能极平/边界最优」、方差归零「{factor_label} 方差分量收敛到 0(数据不支持基因型×{factor_name}互作)」),默认值保 G×E 文案逐字节不变;公开 `solve()` 透传两参;MME/REML/输出键全不变;ENGINE_VERSION 1.1.0→**1.2.0** |
| 服务端 G×R | `RunStatsIn`+`run_ablup``gxr: bool`;互斥门禁 `gxe and gxr` → 409(共用 Z₂ 槽,文案「G×E 与 G×R 互作共用同一随机效应槽(Z₂)」);job_type=`GXR`、params 落 gxr;克隆坍缩系谱 `gxe_pedigree` 上移为 G×E/G×R 共享(纯构建、ABLUP 不执行);`elif gxr:` 镜像 G×E site 分支——按 `phenotypes.items()``rootstock_map[f"t{tid}"]`**字符串键**)构建 `rec_gxr[rid]=(grp,rs)``rec_map`/`rec_fixed`/`rec_cov``rootstock` 强制从 `fixed_effects` 剥离防共线;门禁三件套镜像(`n_cross_rootstock`=同基因型跨砧木数==0 / max cell_counts<2 / residual_df<1 →「G×R 不可辨识」409p_est 不再计入 rootstock);求解传 `gxe=rec_gxr, 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/n_cross_rootstock/n_genotypes/warning/skipped/stage_note`;EBV 写入共用段个体集按 gxr 选 `gxr_tree_ids``_DATA_VERSION` v2.9→**v2.10** |
| 前端 | `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``vue-tsc` 通过 |
| 验证 | `e2e_gxr_20260804.py` 4 组全过:① 2 基因型×2 砧木×2 株强交叉互作(clone1×R1 高/R2 低、clone2 相反)→ method=GXRBLUP、job_type=GXR、σ²gxr=74.8>0、n_cross_rootstock=2、n_genotypes=2、8 EBV 行;② 同基因型仅跨单砧木 →「G×R 不可辨识」409;③ `gxe=True,gxr=True` →「Z₂」互斥 409;④ `fixed_effects=["rootstock"]` 同开 → rootstock 被剥离、不共线、正常出 σ²gxr;后端重启后 openapi 确认 `gxr` 入参;清理自动执行 |
### 8.20 基因组选择(GS)实证严谨性·GBLUP/ssGBLUP 专用 k-fold 交叉验证落地台账(v2.122026-08-04,代码级)
> 用户核实 GS 两条实证缺口:① **GS 缺自身交叉验证**——`run_cv`/`kfold_cv`blup.py)是 A 矩阵系谱预测(ABLUP/GXE),GBLUP 落库的 `accuracy=√mean(reliability)` 是**理论准确度**(PEV 推导),模型误设(G 算错/标记编码错/遗传力先验偏)时 PEV 可靠性依然漂亮、真实预测能力却崩了,只有掩蔽留出「GEBV vs 表型 r」能测出来;② **SSR panel 难构 VanRaden G**——`_dosage_from_gt` 只吃 0/1/2SSR 片段编码(`168/174`)/多等位被丢弃。用户拍板**先做 GS k-fold(①)**SSR dummy 编码(②)留待后续。核心洞察:`_profile_solve` 已支持「仅观测子集进模型、**全部个体**出 EBV」——非观测个体 Z 行全 0、经 G⁻¹/H⁻¹ 交叉关系预测,所以掩蔽留出 = 传训练子集 phenos → 全个体 GEBV → 取留出个体与观测表型相关。完整明细见 `桃育种系统统计引擎实施记录.md` §十三。
| 规格点 | 落地 |
|---|---|
| 求解器 | `genomic.py`:① 抽取 **`_build_h(pedigree, genotyped, G, ridge, extra_base)`**solve_ssgblup 的 base/non_base→`_order_pedigree`→A/Ainv→Hinv→H 构建,Aguilar 2010)——**缺失基因型个体按 base 补入系谱**(原 raise ValueError 改补入,无表型基因型树不再崩,与 phenos 兜底一致);② 新增 **`kfold_cv_genomic(phenos, G, genotyped, k, seed, method, pedigree)`**——`method=gblup`individuals=genotypedG 行序)、relmat_inv=G⁻¹(奇异回退 pinv)、zmat_full=G`method=ssgblup``_build_h` → individuals=order、relmat_inv=H⁻¹、zmat_full=Hcand=genotyped∩phenos`len(cand)<2` → 空 folds + warning**折划分固定种子随机分层**round-robin,GS 同世代样本无系谱家系树,区别于 ABLUP 的 sire 家系留出,文档明示);逐折掩蔽留出:train_phenos=phenostest_set → `_profile_solve(ZGZ_train, X, y_train, relmat_inv, n, z_train)` → 全 EBV → 留出个体 GEBV vs 表型 `blup._pearson`+RMSE,单折失败 error 记 warning 不中断;输出 dict 与 blup.kfold_cv **逐键对齐**k/n_total/n_individuals/folds/mean/pooled_pearson/pooled_rmse/cv_accuracy/h2/warning);**G/H/Hinv 只建一次、逐折只换 z_train 子阵**ENGINE_VERSION 1.0.0→**1.1.0** |
| 服务端 | ① **`_gather_gblup_inputs(dataset_id, maf_min)` 提取**run_gblup 的 dataset→samples→call_rows→markers→sample→tree 映射→dosage→`build_g_matrix`→genotyped 装配提成 helper,返回 `(dosage, marker_order, genotyped, G, g_meta, unmapped)`,run_gblup 改调、行为逐字节不变);② **`run_cv``dataset_id/method/maf_min` 入参**params_json 同步落库)——公共表型/系谱装配后 `if dataset_id:` GS 分支(与 `elif gxe:`/`else:` 互斥,G×E 与 GS 双开 GS 优先):`kfold_cv_genomic` + method 名 **`KFCV/GBLUP`**/**`KFCV/ssGBLUP`**method varchar(16) 放得下);input_hash=sha256(`_input_digest(pedigree, phenos)`+`\n`+geno_str)(镜像 run_gblup 3360-3366);engine_version 按分支(GS 用 `genomic.ENGINE_VERSION`ABLUP/GXE 用 blup);③ schema `CvRunIn` + controller 透传 `dataset_id/method/maf_min``_DATA_VERSION` v2.10→**v2.11** |
| 前端 | CV tab 加 **mode radioABLUP/GS**:GS 模式显示基因型数据集下拉(复用已加载 `gbDatasets`+ method radioGBLUP/ssGBLUP+ MAF≥ 输入,**隐藏 G×E 控件**、辅助文案分支「掩蔽留出 GEBV vs 表型 pearson(实证预测能力,固定种子随机分层)」;`submitCv` 按 mode 组装 payloadGS 传 dataset_id/method/maf_min);`CvRunPayload` 加三个可选字段;`vue-tsc` 通过 |
| 验证 | `e2e_gblup_cv_20260804.py` 3 组全过:① 5 家系×3 全同胞=15 株、10 标记(MK0/MK1 为 QTL 效应 2.0,表型=12+2·dose(MK0)+2·dose(MK1)+低噪)→ `run_cv(dataset_id, method=gblup, k=5)`method=`KFCV/GBLUP`、cv_accuracy=0.794>0.3、==mean_pearson、n_total/n_individuals=15/15、input_hash 64hex、engine=1.1.0、5 折 n_train/n_test≥1、CvFoldModel 5 行;② `method=ssgblup``KFCV/ssGBLUP`、cv_accuracy=0.794>0.3;③ 门禁:无映射样本数据集 → `CustomException`「基因型样本均无法映射到单株」;回归 `e2e_advanced_gblup.py` 复跑全过(`_gather_gblup_inputs` 提取无行为变化);后端重启 openapi 确认 `CvRunIn.dataset_id/method/maf_min`;清理自动执行 |
### 8.21 现代桃育种领域覆盖·S-等位基因交配兼容性 + 抗病/需冷量性状字典落地台账(v2.13,2026-08-04,代码级)
> 用户核实现代桃育种四方向覆盖缺口,拍板开始做(按建议次序先落地 ②③ 小活、① 中活;④ GWAS/QTL/MAS 最大留待单独立项):
> - **① S-等位基因(自交不亲和)交配兼容性**——桃是配子体型自交不亲和(S-RNase),配组合时 S 基因型决定能否坐果;`bre_pollination` 有花粉批但无 S-allele 追踪与兼容性校验——"配了不结"的硬需求。
> - **② 需冷量/需热量**——低需冷量桃适应暖区是核心育种目标;`bre_germplasm.chilling_requirement`(属性)+ `bre_environment_condition.chilling_hours/GDD`(环境侧)已有,**选种性状侧(bre_trait)缺失**。
> - **③ 抗病性状**——细菌性穿孔病/褐腐病/白粉病减药育种关键;`bre_germplasm.disease_resistance` 仅自由文本,**bre_trait 字典一条都没有**。
> - **④ MAS/QTL/GWAS 闭环**——已有 GS 预测层,但缺发现层(GWAS/QTL 定位→MAS);900214 仍 `_coming_soon`,留待单独立项。
> 完整明细见 `桃育种系统统计引擎实施记录.md` §十四。
| 规格点 | 落地 |
|---|---|
| ②③ 性状字典 | `backend/sql/bre_disease_chilling_traits.sql`(幂等 ON CONFLICT)种子 **5 条**`disease_shot_hole` 细菌性穿孔病 / `disease_brown_rot` 褐腐病 / `disease_powdery_mildew` 白粉病(category「抗病性」,0-5 级病情指数 0=免疫…5=高感,`valid_min=0/valid_max=5`+ `chilling_requirement` 需冷量(h0-3000+ `heat_requirement` 需热量(GDD0-10000)(category「生态适应性」)。全部 `data_type='numeric'` + `into_ebv='1'` + `direction='asc'`(低值优:低需冷/低需热/低病情指数抗病)+ `default_h2`(需冷 0.5/需热 0.4/抗病 0.3+ `stage='evaluation'` + `method` 测定说明——**统计引擎 `_trait_meta_map` 仅消费 numeric,故不用 categorical 分级**;前端 trait 页 category 自由文本自动显示、0 改动 |
| ① S-allele 建模 | `bre_germplasm.s_alleles``String(32)`model+schema Create/Update/Out+ALTER TABLE+COMMENT,如 `S1/S3``Sf`=自交亲和型)——`bre_germplasm.sql` 补列;germplasm 前端表单/导出列加 S-等位基因输入 |
| ① 兼容校验 | `cross_combination/service.py``_parse_s_alleles`(分隔符 `/ , ;` 归一化小写集合)+ `_s_compat_check`**任一亲本含 `sf`→full 放行**;共享 2 个→`none`;共享 1 个→`half`;无 S 数据→`unknown` 跳过)+ `_check_s_compat`(读亲本 s_alleles`none``CustomException` 409「S-等位基因完全不相容(共享 …),该组合无法坐果」,`half`→返回警示文案);`create`/`update` 在亲本断言后调用,`CrossCombinationOutSchema.s_compat`(可选派生字段)落警示;**自交(同亲本共享 2 等位)自然被 409 拦截** |
| 前端 | germplasm 表单加 S-等位基因输入(type inputplaceholder 提示 Sf);cross_combination 组合提交包装 createApi/updateApi——响应含 `s_compat``msg.warning` 展示(409 由统一错误处理自动提示);`germplasm.ts` `GermplasmForm/GermplasmTable``s_alleles?``vue-tsc` EXIT=0 |
| 验证 | `Temp/claude/e2e_s_allele_20260804.py` 6 组全过:纯函数 8 例(S1/S3×S1/S3→none、×S2/S4→full、×S1/S2→half、含 Sf→full、大小写/混合分隔→none、缺数据→unknown+ service 层 create(共享 S1/S3→409「不相容」;共享 S1→`s_compat` 半兼容;0 共享→无警示;Sf 放行;缺 S 跳过);DB 核验 bre_trait 5 条 numeric+asc+into_ebv=1 落库;openapi 核验 `BreedingGermplasm{Create/Update/Out}.s_alleles` + `CrossCombinationOut.s_compat`;清理自动执行 |
---
## 9. 已决策取值汇总(v1.2,本人敲定)
> 下列枚举由本人依据 RosBREED 桃无性选育流水线 + 现有 14 域敲定(用户授权"你来定")。全部作为 `sys_dict` 新增字典类型,落库英码、前端显中文,并接入 Excel 导入翻译(DictLabelResolver)。
### 9.1 breeding_stage(选择阶段)
| code | 中文 | 主要适用实体 | 说明 |
|---|---|---|---|
| germplasm | 种质资源 | germplasm | 基础材料/引入种 |
| parent | 亲本 | germplasm | 用于杂交的亲本 |
| seedling | 实生苗/群体植株 | tree | 杂交实生群体、未入选 |
| sp | 初选株 | tree | Single Plant,田间初选 |
| ap | 复选株 | tree | Advanced,跨年跨点复选 |
| line | 品系 | germplasm | 克隆扩繁、系统观察 |
| regional_trial | 区试品系 | germplasm | 区域试验 |
| released | 新品种/审定 | germplasm | 命名/登记/审定 |
> tree 用 seedling/sp/apgermplasm 用 germplasm/parent/line/regional_trial/released`selection_result` 记录 from_stage→to_stage 晋级流转。
### 9.2 breeding_generation(遗传世代)
| code | 中文 | 说明 |
|---|---|---|
| F1 | 杂交集 | 首次杂交产生的分离群体(桃主要选种群体) |
| F2 | 自交/互交分离世代 | F1 自交或 F1×F1 |
| BC1 | 回交 1 代 | 导入性状(如抗病)回交 |
| BC2 | 回交 2 代 | |
| BC3 | 回交 3 代 | |
> 引入种质/地方品种 `generation` 留空。权威存 `cross_combination.generation`(与 `cross_type` 联动:回交→BCn,自交→F2),`tree`/`germplasm` 冗余拷贝便于筛选。
### 9.3 breeding_group_type(分组维度)
| code | 中文 | 说明 |
|---|---|---|
| project | 育种项目 | 正式项目集合 |
| family | 家系/杂交组合群 | 同 cross_combination 的后代集合 |
| category | 种质类别群 | 油桃/蟠桃/观赏桃等类别 |
| temporary_set | 临时选系集 | 临时任务选系集 |
| custom | 自定义 | 用户自由定义 |
> 不设 objective 维度(与 `target` 育种目标语义重叠)。
### 9.4 breeding_design_type(试验设计)
| code | 中文 | 说明 |
|---|---|---|
| rcbd | 随机区组 | 高级 trial 常用,区组+重复+对照 |
| augmented | 增广设计 | 多品系少重复+对照重复,**早期选种最适用** |
| contrast | 对比试验 | 少量材料与对照比较 |
| split_plot | 裂区设计 | 砧木×接穗等两因子 |
| unreplicated | 观察圃/简约 | 无重复,初步观察 |
### 9.5 propagation 纳入一期(§3.8
打通 入选株(tree) → 克隆种质(germplasm) → 扩繁批次(propagation) → 新定植树(tree) 闭环。
### 9.6 字典落地
`breeding_dict.sql` 增补 `breeding_stage`/`breeding_generation`/`breeding_group_type`/`breeding_design_type` 四类(英码+中文),并接入对应 service 的 Excel 导入翻译(DictLabelResolver)与前端下拉。
---
**定稿状态(v2.22026-07-30**:历经 v1.0→…→v1.9 + **v2.0 架构决策锁定** + **v2.1 review 修订(R1R9** + **v2.2 深度复审 A–H 全量落地(含 F1/F2 架构拍板:单一长表 + 两长表职责正交 + 统计 VIEW/看板 MVA1 clone 建于入选 / A3 砧木 FK 统一字典 / A4 pedigree 唯一权威 / B1-B4 统计口径 / C1-C3 门禁重构 / D1-D4 clone 居中 / F3-F5 门禁与公式修正 / G1-G3 编号·审计·method / H1-H3 打磨,详见 §8.10**。所有模块、字段、枚举、建模铁律、互操作映射均已规格化。**仍为决策锁定、方案态**:除生成器 A/B/C 外,待用户明确"做/搞吧"后据此实施,不先行编码。