446 lines
24 KiB
Python
446 lines
24 KiB
Python
"""育种统计 数据模型(一期 2 个最基础:ABLUP·EBV + 配合力 GCA/SCA)"""
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import (
|
||
JSON,
|
||
Boolean,
|
||
Date,
|
||
DateTime,
|
||
Float,
|
||
ForeignKey,
|
||
Index,
|
||
Integer,
|
||
Numeric,
|
||
String,
|
||
Text,
|
||
)
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.core.base_model import MappedBase, ModelMixin, UserMixin
|
||
|
||
|
||
class PredictionModel(ModelMixin, UserMixin, MappedBase):
|
||
"""育种值模型/批次元数据(§3.12)。"""
|
||
|
||
__tablename__ = "bre_prediction"
|
||
|
||
model_name: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="模型名称")
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
method: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="方法(ABLUP/COMBINING)")
|
||
stage: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="测定阶段(juvenile幼龄/evaluation成株)")
|
||
accuracy: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="模型精度(批次PA=√均值可靠性)")
|
||
train_n: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="训练样本量")
|
||
heritability: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="遗传力 h²")
|
||
predict_date: Mapped[datetime | None] = mapped_column(Date, nullable=True, comment="预测日期")
|
||
data_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="数据版本(输入快照版本)")
|
||
input_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="输入快照SHA256(表型+系谱)")
|
||
engine_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="统计引擎版本")
|
||
is_active: Mapped[bool | None] = mapped_column(Boolean, nullable=True, default=False, comment="当前生效版本(同性状最近批次,供版本回滚)")
|
||
note: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_prediction_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class PredictionValueModel(ModelMixin, UserMixin, MappedBase):
|
||
"""个体预测值(EBV 持久化,V1.1 建表)。"""
|
||
|
||
__tablename__ = "bre_prediction_value"
|
||
|
||
prediction_id: Mapped[int] = mapped_column(
|
||
Integer, ForeignKey("bre_prediction.id", ondelete="CASCADE"),
|
||
index=True, nullable=False, comment="关联模型"
|
||
)
|
||
germplasm_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_germplasm.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="种质(亲本级)"
|
||
)
|
||
tree_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_tree.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="单株(树级)"
|
||
)
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
predicted_value: Mapped[float | None] = mapped_column(Float, nullable=True, comment="预测值/EBV")
|
||
reliability: Mapped[float | None] = mapped_column(Float, nullable=True, comment="可靠性")
|
||
pa: Mapped[float | None] = mapped_column(Float, nullable=True, comment="预测准确度 PA=√可靠性")
|
||
rank: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="排名")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_prediction_value_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class CombiningAbilityModel(ModelMixin, UserMixin, MappedBase):
|
||
"""配合力分析结果(§3.12;GCA 按亲本、SCA 按组合)。"""
|
||
|
||
__tablename__ = "bre_combining_ability"
|
||
|
||
model_name: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="模型名称")
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
method: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="方法")
|
||
design_type: Mapped[str | None] = mapped_column(
|
||
String(32), nullable=True,
|
||
comment="分析采用交配设计(full_diallel/partial_diallel/line_tester/nciii,结果快照)",
|
||
)
|
||
gca_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="亲本一般配合力 {parent: gca}")
|
||
sca_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="组合特殊配合力 {combo: {p1,p2,sca}}")
|
||
anova_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="配合力方差分解(F_gca/p_gca)")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_combining_ability_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class SelectionIndexModel(ModelMixin, UserMixin, MappedBase):
|
||
"""选择指数 批次(加权 Z 综合;可选接入 ABLUP 批次 EBV 与 h² 加权,结果持久化)。"""
|
||
|
||
__tablename__ = "bre_selection_index"
|
||
|
||
model_name: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="批次名称")
|
||
method: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="SI_EBV/SI_PHENO")
|
||
weights_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{trait_code: 用户权重}")
|
||
batch_refs_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{trait_code: ABLUP批次id}")
|
||
heritability_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{trait_code: h²}")
|
||
top_n: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="返回前 N")
|
||
result_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{traits, top:[{tree_id,index,detail}]}")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_selection_index_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class AnovaResultModel(ModelMixin, UserMixin, MappedBase):
|
||
"""单因素 ANOVA 结果(家系方差组分 + 广义遗传力 H²)。"""
|
||
|
||
__tablename__ = "bre_anova_result"
|
||
|
||
model_name: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="批次名称")
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
method: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="ANOVA/H2")
|
||
result_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="方差组分/H²/F/p")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_anova_result_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class CvResultModel(ModelMixin, UserMixin, MappedBase):
|
||
"""k-fold 交叉验证结果(外部验证预测准确度,区别于 PEV 可靠性)。"""
|
||
|
||
__tablename__ = "bre_cv_result"
|
||
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
trait_code: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="性状编码")
|
||
method: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="KFCV/ABLUP 或 KFCV/GXE")
|
||
k: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="折数")
|
||
n_total: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="总记录数")
|
||
n_individuals: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="加性个体数")
|
||
mean_pearson: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="有效折预测-观测 pearson 均值")
|
||
mean_rmse: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="有效折 RMSE 均值")
|
||
pooled_pearson: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="合并全部折 pearson")
|
||
pooled_rmse: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="合并全部折 RMSE")
|
||
cv_accuracy: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="预测准确度(=mean_pearson)")
|
||
h2: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="有效折遗传力均值")
|
||
folds_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="折明细快照")
|
||
data_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="数据版本")
|
||
input_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="输入快照SHA256")
|
||
engine_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="统计引擎版本")
|
||
note: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_cv_result_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class CvFoldModel(ModelMixin, UserMixin, MappedBase):
|
||
"""k-fold CV 折明细。"""
|
||
|
||
__tablename__ = "bre_cv_fold"
|
||
|
||
cv_result_id: Mapped[int] = mapped_column(
|
||
Integer, ForeignKey("bre_cv_result.id", ondelete="CASCADE"),
|
||
index=True, nullable=False, comment="关联 CV 结果"
|
||
)
|
||
fold_idx: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="折号(1-based)")
|
||
n_train: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="训练记录数")
|
||
n_test: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="测试个体数")
|
||
n_eval: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="有效评估个体数")
|
||
pearson: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="折内预测-观测 pearson")
|
||
rmse: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="折内 RMSE")
|
||
error: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="折失败原因")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_cv_fold_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class StatisticsJobModel(ModelMixin, UserMixin, MappedBase):
|
||
"""统计异步任务(R 引擎;ABLUP/COMBINING 提交后异步执行并回写结果)。"""
|
||
|
||
__tablename__ = "bre_statistics_job"
|
||
|
||
job_type: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="ABLUP/COMBINING")
|
||
params_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="入参")
|
||
status: Mapped[str] = mapped_column(String(16), nullable=False, default="PENDING", comment="PENDING/RUNNING/SUCCESS/FAILED")
|
||
result_ref: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="结果主表 id")
|
||
error_msg: Mapped[str | None] = mapped_column(Text, nullable=True, comment="错误信息")
|
||
started_time: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||
finished_time: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_statistics_job_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class GeneticCorrResultModel(ModelMixin, UserMixin, MappedBase):
|
||
"""成对双性状 BLUP 遗传相关矩阵结果(MT-BLUP,§8.18)。
|
||
|
||
逐对 bivariate 估计 σ²a1/σ²a2/σ²a12(固定单性状方差、仅对遗传相关 ρ 作
|
||
1-D 剖面 REML golden-max),输出遗传相关矩阵 r_g 供 Smith-Hazel 指数
|
||
G 矩阵非对角替换 Calo 近似。
|
||
"""
|
||
|
||
__tablename__ = "bre_genetic_corr_result"
|
||
|
||
trait_ids_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{trait_code: trait_id}")
|
||
matrix_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="遗传相关矩阵 {code: {code: r_g}}")
|
||
sigma_a_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="加性方差矩阵 {code: {code: σa}}")
|
||
heritability_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{code: h²}")
|
||
pairs_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="逐对详情 {pair: {r_g, va1, va2, ve1, ve2, n_common, converged, warning}}")
|
||
n_common: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="成对共有树数(最小)")
|
||
data_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="数据版本")
|
||
input_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="输入快照SHA256(表型+系谱)")
|
||
engine_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="统计引擎版本")
|
||
note: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_genetic_corr_result_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class TypeBResultModel(ModelMixin, UserMixin, MappedBase):
|
||
"""Type-B 多环境遗传相关结果(§8.27)。
|
||
|
||
同一性状在多个环境(site=研究点 / year=年份)的表型,以环境互为"性状"逐对
|
||
REML 双性状 BLUP 估计遗传相关 r_g(复用 mtblup.solve_bivariate);r_g 均值
|
||
即 Type-B 遗传相关,衡量基因型×环境互作强度与跨环境遗传稳定性。
|
||
"""
|
||
|
||
__tablename__ = "bre_type_b_result"
|
||
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
trait_code: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="性状编码")
|
||
env_dim: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="环境维度(site/year)")
|
||
method: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="方法(reml/calo,calo 无环境级EBV时回退reml)")
|
||
envs_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="{env_code: env_label}")
|
||
matrix_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="环境间遗传相关矩阵 {env: {env: r_g}}")
|
||
pairs_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="逐对详情 {pair: {r_g, va1, va2, ve1, ve2, n_common, converged, warning}}")
|
||
n_common: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="成对共有树数(最小)")
|
||
data_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="数据版本")
|
||
input_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="输入快照SHA256")
|
||
engine_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="统计引擎版本")
|
||
note: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_type_b_result_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class StabilityResultModel(ModelMixin, UserMixin, MappedBase):
|
||
"""AMMI / Finlay-Wilkinson 稳定性分析结果(§8.18)。
|
||
|
||
两因素(基因型×环境)均值表 → AMMI SVD(IPC1/IPC2/ASV/ecovalence) 与
|
||
Finlay-Wilkinson 回归斜率 b,输出稳定性排名。
|
||
"""
|
||
|
||
__tablename__ = "bre_stability_result"
|
||
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
trait_code: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="性状编码")
|
||
env_dim: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="环境维度(site/year)")
|
||
methods: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="方法(ammi,finlay)")
|
||
detail_json: Mapped[dict | None] = mapped_column(JSON, nullable=True, comment="稳定性分析明细快照")
|
||
data_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="数据版本")
|
||
input_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="输入快照SHA256")
|
||
engine_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="统计引擎版本")
|
||
note: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_stability_result_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class GwasResultModel(ModelMixin, UserMixin, MappedBase):
|
||
"""GWAS 关联分析批次结果(§8.22)。
|
||
|
||
GLM+PC 逐标记单标记回归(纯 numpy + fdist),输出显著标记集与 QTL 区间。
|
||
"""
|
||
|
||
__tablename__ = "bre_gwas_result"
|
||
|
||
dataset_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_genotyping_dataset.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="基因型数据集"
|
||
)
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
trait_code: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="性状编码")
|
||
method: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="方法(gwas/ssgwas)")
|
||
n_individuals: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="样本数(表型∩基因型)")
|
||
n_markers: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="标记总数")
|
||
m_after_maf: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="MAF 过滤后标记数")
|
||
maf_min: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="MAF 过滤下限")
|
||
n_pc: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="群体结构主成分数")
|
||
sig_level: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="显著性水平")
|
||
threshold_bonf: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="Bonferroni 阈值")
|
||
n_sig_bonf: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="Bonferroni 显著标记数")
|
||
n_sig_fdr: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="FDR q<α 标记数")
|
||
n_qtl: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="QTL 区间数")
|
||
data_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="数据版本")
|
||
input_hash: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="输入快照SHA256(表型+系谱+基因型)")
|
||
engine_version: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="统计引擎版本")
|
||
remark: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_gwas_result_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class GwasSnpModel(ModelMixin, UserMixin, MappedBase):
|
||
"""GWAS 逐标记关联结果(§8.22)。"""
|
||
|
||
__tablename__ = "bre_gwas_snp"
|
||
|
||
gwas_result_id: Mapped[int] = mapped_column(
|
||
Integer, ForeignKey("bre_gwas_result.id", ondelete="CASCADE"),
|
||
index=True, nullable=False, comment="关联 GWAS 批次"
|
||
)
|
||
marker_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_marker.id", ondelete="SET NULL"),
|
||
index=True, nullable=True, comment="标记"
|
||
)
|
||
marker_name: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="标记名称")
|
||
chromosome: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="染色体")
|
||
position: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="物理位置(bp)")
|
||
maf: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="次要等位频率")
|
||
effect: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="加性效应")
|
||
se: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="效应标准误")
|
||
t_value: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="t 值")
|
||
p_value: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="p 值")
|
||
neg_log10p: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="−log10(p)")
|
||
q_value: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="BH-FDR q 值")
|
||
sig_bonf: Mapped[bool | None] = mapped_column(Boolean, nullable=True, comment="Bonferroni 显著")
|
||
sig_fdr: Mapped[bool | None] = mapped_column(Boolean, nullable=True, comment="FDR 显著")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_gwas_snp_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class QtlModel(ModelMixin, UserMixin, MappedBase):
|
||
"""QTL 区间(§8.22)。
|
||
|
||
source=known 为人工录入已知 QTL(桃成熟期/果重等位点);source=gwas 为 GWAS
|
||
显著标记聚类自动定位(gwas_result_id 关联批次)。
|
||
"""
|
||
|
||
__tablename__ = "bre_qtl"
|
||
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="性状"
|
||
)
|
||
chromosome: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="染色体")
|
||
start_bp: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="区间起点(bp)")
|
||
end_bp: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="区间终点(bp)")
|
||
peak_marker_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_marker.id", ondelete="SET NULL"),
|
||
index=True, nullable=True, comment="峰标记"
|
||
)
|
||
peak_marker_name: Mapped[str | None] = mapped_column(String(64), nullable=True, comment="峰标记名称")
|
||
peak_p: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="峰标记 p 值")
|
||
n_markers: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="区间显著标记数")
|
||
effect: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="区间峰效应")
|
||
source: Mapped[str | None] = mapped_column(String(8), nullable=True, default="known", comment="来源(known/gwas)")
|
||
gwas_result_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_gwas_result.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="来源 GWAS 批次(source=gwas 时)"
|
||
)
|
||
remark: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_qtl_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class MasPanelModel(ModelMixin, UserMixin, MappedBase):
|
||
"""MAS 标记辅助选择面板(§8.22)。
|
||
|
||
一组与目标性状关联的标记(QTL 峰标记),供决策预览按有利剂量命中童期幼苗。
|
||
"""
|
||
|
||
__tablename__ = "bre_mas_panel"
|
||
|
||
panel_name: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="面板名称")
|
||
trait_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_trait.id", ondelete="CASCADE"),
|
||
index=True, nullable=True, comment="目标性状"
|
||
)
|
||
n_markers: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="标记数")
|
||
remark: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="备注")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_mas_panel_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class MasPanelMarkerModel(ModelMixin, UserMixin, MappedBase):
|
||
"""MAS 面板标记(§8.22)。"""
|
||
|
||
__tablename__ = "bre_mas_panel_marker"
|
||
|
||
panel_id: Mapped[int] = mapped_column(
|
||
Integer, ForeignKey("bre_mas_panel.id", ondelete="CASCADE"),
|
||
index=True, nullable=False, comment="关联面板"
|
||
)
|
||
marker_id: Mapped[int | None] = mapped_column(
|
||
Integer, ForeignKey("bre_marker.id", ondelete="SET NULL"),
|
||
index=True, nullable=True, comment="标记"
|
||
)
|
||
favorable_dose: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="有利剂量(0/1/2)")
|
||
effect: Mapped[float | None] = mapped_column(Numeric, nullable=True, comment="效应(绝对值参考)")
|
||
direction: Mapped[str | None] = mapped_column(String(8), nullable=True, default="high", comment="方向(high=剂量≥favorable_dose命中 / low=剂量≤命中)")
|
||
mode: Mapped[str | None] = mapped_column(
|
||
String(16), nullable=True, default="additive",
|
||
comment="基因作用模式:additive加性(剂量≥fav)/dominance显性(剂量≥1高/≤1低)/recessive隐性(剂量=2高/0低)/allele等位存在(有利等位)/haplotype单倍型(同组全命中)")
|
||
favorable_allele: Mapped[str | None] = mapped_column(String(16), nullable=True, comment="有利等位(allele/haplotype 模式用,SSR 等位索引)")
|
||
haplotype_group: Mapped[str | None] = mapped_column(String(32), nullable=True, comment="单倍型组(haplotype 模式:同组标记全命中才计 1)")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_mas_panel_marker_created_deleted", "created_time", "is_deleted"),
|
||
)
|