Virtual Embryo Challenge更新于 10-03 20:28(北京时间) / 每 5 分钟更新

总览 · ← 返回运行 20261003-004922-search-t2-heart-interp-g24

节点 n12

mix+空间分层上移植型内近邻坐标融合(T2HI-04):关闭已证无效的形状插值;Procrustes 对齐后,每个共有型的 b 侧细胞用 cKDTree 向其 a 侧同型最近邻做 3D 位移(α=1.0),恢复型内局部空间连续性,表达矩阵不动。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261003-004922-search-t2-heart-interp-g24
父节点n9
子节点n13
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 60.66(+0.9) · proxy 60.66(+0.9) · 3 次复测均分 59.94
审查通过 检查项1(越界读取):未发现问题——run.py 仅通过 src.task2_spatial.view_io 的 load_manifest/read_stage 读取 --data 指向的视图内数据(run.py:57-67),全部源码中无绝对路径、'..'、/mnt、/home、data/raw、评分器路径或网络下载调用。; 检查项2(硬编码目标统计量):未发现问题——代码中没有写死的细胞类型名、比例表、表达值或基因列表;所有数值常量(NN_MIN_TYPE_CELLS=5 nn_fuse.py:25、MIN_TYPE_CELLS=20 spatial_mix.py:21、CELLS_P…
用时?从运行开始到结束(或到现在)的挂钟时间。12 分
程序版本af89ea07a674ea1b4bf16532491b79df4abb7f50 (programs.git)

方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。

来自 programs.git af89ea07a6:solution/METHOD.md

mix+空间分层上移植型内近邻坐标融合(T2HI-04):关闭已证无效的形状插值;Procrustes 对齐后,每个共有型的 b 侧细胞用 cKDTree 向其 a 侧同型最近邻做 3D 位移(α=1.0),恢复型内局部空间连续性,表达矩阵不动。

方法

父节点 9 pipeline,SHAPE_INTERP 置 0(父节点已证类型级 xy 形状插值无效),保留 SPATIAL_STRATIFY=1(每共有型 xy k-means 分 bin、bin 内按 (1−t,t) 抽两阶段真实细胞,表达和坐标一起走,align=procrustes,scale_damp=1)。新增 solution/nn_fuse.py:选完细胞、放到位之后、jitter/缩放之前,对每个两阶段共有型(各 ≥ NN_MIN_TYPE_CELLS=5 细胞),用 scipy.spatial.cKDTree 在该型 a 侧全部对齐+缩放坐标上建树,把每个被选中的 b 侧同型细胞位移 α·(最近 a 侧同型邻居 − 自身位置),3D 含 z。非共有型细胞不动,表达矩阵不动(X 与对照逐位一致)。之后照常走父节点的 _jitter + scale_to_rms。

  • 开关:NN_FUSE=0 或 NN_FUSE_ALPHA=0 为关闭对照(已验证与 SHAPE_INTERP=0 的父节点输出逐位一致,X 和坐标均相同)。
  • 参数:NN_FUSE_ALPHA(默认 1.0)、NN_FUSE_NDIM(默认 3;2=仅 xy,z 不动)。
  • 单输入阶段(b is None)退路与父节点相同(分层抽最后输入,无融合)。
  • 位移是逐细胞、位置依赖的:同型不同细胞获得不同方向/幅度的位移(型内每轴位移 std 62–102),不是常数平移,也不是刚体变换。

α 网格(proxy,seed0,A 半)

α榜分local_spatialshape_scale
0(=父,SHAPE_INTERP=0)59.8054.13*53.76*
0.559.4954.0653.65
0.7559.8555.3753.78
1.0(提交)60.0756.2653.78
1.2560.0456.0153.91
1.559.8254.7954.23
1.0,仅 xy(NDIM=2)59.7354.9153.75

*父节点 9 表中数字;本节点 α=0 对照与其逐位一致。cell_state/expression_change 全部配置相同(66.17/64.07,X 未动)。α=1.0 与节点 10 在另一分支验证的值一致;3D 融合优于仅 xy(z 也参与配对恢复局部连续性)。

3 种子确认(α=1.0,A 半)

seed榜分local_spatialshape_scale
060.0756.2653.78
159.7556.0753.20
259.7455.7653.44
均值59.8556.0353.47

vs 父节点 9 rank3 = 59.17(local_spatial 53.97):+0.68,local_spatial +2.06(远超 T2 噪声 ~1 分,3 种子一致);shape_scale −0.43(噪声内)。与节点 10(非分层底座 + 同机制,rank3 60.13)方向一致。

机制生效证据(proxy E8.25_late+E9.5→E8.75,t=0.4,seed0,α=1.0)

  • 融合细胞数 2273 / 17616 = 12.9% 输出细胞(占被选 b 侧细胞 7046 的 32.3%;略低于 PLAN 的 15% 门槛,因为 proxy 共有型仅 5 个,非共有型的 b 细胞按设计不动)。
  • 5 个共有型全部通过 ≥5 阈值:NCC 341、Peri 621、V-CM 814、aPHM 239、pPHM 258 个 b 细胞被融合。
  • 融合前 b→a 同型最近邻平均距离 200.1(各型 102–405);融合后全局平均最近邻距离从 14.25(对照)降到 12.86(−9.8%),型内局部空间连续性恢复。
  • 位移向量型内每轴 std 62.5–101.9 > 0:逐细胞位置依赖位移,非常数位移。
  • 四组分响应:local_spatial 54.1→56.3(机制目标组,+2.1~2.3);shape_scale 53.8→53.8(持平);cell_state / expression_change 与对照逐位一致(X 未动)。
  • occupancy 变化可见未崩塌(occupancy_dice 0.837 记录于查分 metrics;输出 RMS 346.3 与对照相同,缩放步骤在融合后统一执行)。

对照结果(mechanism_off_control)

NN_FUSE_ALPHA=0 输出与 NN_FUSE=0(=SHAPE_INTERP=0 父节点路径)逐位一致(X 稀疏非零差 0、坐标 array_equal),已在代码改动前后各验证一次。α=1.0 比 α=0 对照(seed0 59.80)高 0.27 分、local_spatial 高 2.13 分——机制在 local_spatial 上生效超过噪声,榜分增益小于组增益因 shape_scale 微降抵消一部分。

验证过 / 未验证

  • 验证过:proxy 上 α∈{0,0.5,0.75,1.0,1.25,1.5}、3D vs xy、3 种子;off 对照逐位一致;vec-check 通过;seed 确定性(同 seed 重跑输出相同,rng 均来自 np.random.default_rng(seed),cKDTree 查询确定)。
  • 未验证:final 括号(E8.25+E8.75→E8.5,31 个共有型、覆盖率高得多,融合细胞占比会远高于 12.9%,效果预期更大但本节点无法测);α 在 final 上的最优值可能不同(proxy 峰值 1.0 与节点 10 独立分支一致,取 1.0 不另调)。
  • 生物学知识来源:仅方法卡/父节点的坐标系约定(z 为离散切片轴、procrustes 保 z、各阶段自己的帧),未引入新的外部先验。

下一步

  • 表达侧改进(cell_state 66.2 / expression_change 64.1 之外无杠杆;local_spatial 已 56):如 external/mosta_e95_v0 引导的密度加权或型内表达平滑。
  • 节点 10(非分层底座,rank3 60.13)与本节点(分层底座,均值 59.85)可比较:分层抽样本身对 local_spatial 无增益(54.0 vs 54.1),融合才是有效部件;后续 improve 可直接在任一底座上叠表达侧机制。

调研员的计划

名称mix+空间分层 上移植型内近邻坐标融合(T2HI-04),替换无效形状插值
动机父节点9的shape_interp已被证明无效(3种子均值59.07≈父59.04,ANALYSIS判死坐标形变方向)。全树最弱组为local_spatial 53.97、shape_scale 53.90。节点10在另一分支(node 7)上用型内近邻融合将local_spatial从54.03提升至56.65(+2.62,远超T2噪声1分),shape_scale +1.09,rank3达60.13(全树最佳)。该机制尚未在节点9的mix+空间分层分支上验证。ANALYSIS明确建议'已被证明有效的部件可以组合'。
做法步骤:1) 在父节点9的pipeline中,将SHAPE_INTERP设为0(关闭已证无效的形状插值),保留SPATIAL_STRATIFY=1;2) 新增nn_fuse.py:Procrustes对齐+缩放后、输出前,对每个两阶段共有型(各≥5细胞),用scipy.spatial.cKDTree建a侧该型细胞的树,将b侧每个细胞向其a侧同型最近邻位移α倍(3D,含z);非共有型不动,表达矩阵不动;3) 参数:α默认1.0(节点10验证值),搜索范围{0.5, 0.75, 1.0, 1.5},用vec-score在seed0上快速筛选,选最优后跑seed1/2确认;4) 单输入阶段退路:b is None时直接走父节点fallback(无融合);5) 实现约60行,30分钟内可完成;6) 若α=1.0的seed0分数>60.5(超父0.7以上),直接提交;否则尝试α网格。
风险1) 节点9的空间分层抽样改变了细胞选取方式(k-means bin内按比例抽),可能使b侧细胞的最近邻分布与节点7不同,融合效果减弱——Engineer应在第一次查分后对比local_spatial是否>55;2) α过大导致坐标塌缩损害shape_scale——若shape_scale<53.5则降α;3) 提升可能在噪声内(<1分)——需3种子确认。尽早发现:seed0查分若<59.5即停止调参,如实报告。

代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。

对比:父节点版本 f29112843c。改动的文件:solution/METHOD.md +47 −30、solution/nn_fuse.py +118 −0、solution/run.py +25 −16

diff --git a/solution/METHOD.md b/solution/METHOD.mdindex c81cc32..7f3f9f0 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,42 +1,59 @@-# mix + 类型级 xy 形状插值(T2HI-02):共有型质心+协方差对数欧拉插值后仿射重排坐标,位移钳到 0.08×RMS;机制生效但 proxy 上与父节点持平(3 种子均值 59.07 vs 父 59.04)。+# mix+空间分层上移植型内近邻坐标融合(T2HI-04):关闭已证无效的形状插值;Procrustes 对齐后,每个共有型的 b 侧细胞用 cKDTree 向其 a 侧同型最近邻做 3D 位移(α=1.0),恢复型内局部空间连续性,表达矩阵不动。  ## 方法 -在父节点 8(mix,align=procrustes,scale_damp=1,空间分层抽样 SPATIAL_STRATIFY=1)之后新增坐标重映射(`solution/shape_interp.py`):+父节点 9 pipeline,SHAPE_INTERP 置 0(父节点已证类型级 xy 形状插值无效),保留 SPATIAL_STRATIFY=1(每共有型 xy k-means 分 bin、bin 内按 (1−t,t) 抽两阶段真实细胞,表达和坐标一起走,align=procrustes,scale_damp=1)。新增 `solution/nn_fuse.py`:选完细胞、放到位之后、jitter/缩放之前,对每个两阶段共有型(各 ≥ NN_MIN_TYPE_CELLS=5 细胞),用 `scipy.spatial.cKDTree` 在该型 a 侧全部对齐+缩放坐标上建树,把每个被选中的 b 侧同型细胞位移 α·(最近 a 侧同型邻居 − 自身位置),**3D 含 z**。非共有型细胞不动,表达矩阵不动(X 与对照逐位一致)。之后照常走父节点的 _jitter + scale_to_rms。 -1. 对每个两阶段共有型(两阶段各 ≥20 细胞,MIN_TYPE_CELLS=20),取该型在对齐+缩放到目标 RMS 后的全部细胞 xy,算质心 μ_a/μ_b 与协方差 Σ_a/Σ_b(对角加正则 1e-4·tr/2)。-2. 插值:μ_t=(1−t)μ_a+tμ_b;Σ_t=exp((1−t)logΣ_a+t·logΣ_b)(eigh 实现矩阵对数/指数,2×2)。-3. 被选入输出的该型细胞:来自 a 的 x_new=μ_t+L_t L_a⁻¹(x−μ_a),来自 b 的类似(L=Cholesky 下三角);z 不动(离散切片轴)。型内不同位置位移不同(非刚性,区别于节点 5 的刚体平移)。-4. 安全阀:det(Σ_a)/det(Σ_b)>100 退化为仅质心平移;质心位移钳到 SHAPE_SHIFT_CLAMP×全局 xy RMS(提交默认 0.08);重映射后 xy 超全局均值±3σ 钳位(本次 0 个触发);非共有型坐标不变。-5. 单输入阶段(b is None)退路与父节点一致;重映射后仍走父节点的 _jitter + scale_to_rms。-6. 开关:`SHAPE_INTERP=0` 为关闭对照(直接走父节点 `interpolate_spatial`,已验证输出逐位确定且与父代码路径相同);`SHAPE_BLEND`(默认 1)缩放线性形状部分,0=仅质心平移。+- 开关:`NN_FUSE=0` 或 `NN_FUSE_ALPHA=0` 为关闭对照(已验证与 SHAPE_INTERP=0 的父节点输出**逐位一致**,X 和坐标均相同)。+- 参数:`NN_FUSE_ALPHA`(默认 1.0)、`NN_FUSE_NDIM`(默认 3;2=仅 xy,z 不动)。+- 单输入阶段(b is None)退路与父节点相同(分层抽最后输入,无融合)。+- 位移是逐细胞、位置依赖的:同型不同细胞获得不同方向/幅度的位移(型内每轴位移 std 62–102),不是常数平移,也不是刚体变换。 -## 机制生效证据(proxy E8.25_late+E9.5→E8.75,t=0.4,seed0)+## α 网格(proxy,seed0,A 半) -- 共有型 5 个全部通过阈值,重映射 3553/17616 = 20.2% 输出细胞(>15% 门槛);每型质心按 t 精确移动(如 NCC:a 侧移 129→钳后按 0.08×RMS≈28 截断;面积 det^{1/2} 从 a/b 两端向几何插值移动,如 Peri 23149/24828→23806,V-CM 3319/23434→7254)。-- 输出云 occupancy(40 单位网格)bins 571→558,off/on occupancy_dice 0.960;表达矩阵与对照逐位相同(机制只动坐标)。-- 四组分响应(seed0 A 半,vs 父 59.80):shape_scale 53.76→53.60、local_spatial 54.13→53.48(未钳位时更低:52.46/52.38);expression_change、cell_state 与对照逐位一致(64.07/66.17,X 未动)。+| α | 榜分 | local_spatial | shape_scale |+|---|---:|---:|---:|+| 0(=父,SHAPE_INTERP=0) | 59.80 | 54.13* | 53.76* |+| 0.5 | 59.49 | 54.06 | 53.65 |+| 0.75 | 59.85 | 55.37 | 53.78 |+| **1.0(提交)** | **60.07** | **56.26** | **53.78** |+| 1.25 | 60.04 | 56.01 | 53.91 |+| 1.5 | 59.82 | 54.79 | 54.23 |+| 1.0,仅 xy(NDIM=2) | 59.73 | 54.91 | 53.75 | -## 对照与查分记录(vec-score A 半,quota 用 10/20)+*父节点 9 表中数字;本节点 α=0 对照与其逐位一致。cell_state/expression_change 全部配置相同(66.17/64.07,X 未动)。α=1.0 与节点 10 在另一分支验证的值一致;3D 融合优于仅 xy(z 也参与配对恢复局部连续性)。 -| 配置 | seed0 | seed1 | seed2 | 均值 |-|---|---:|---:|---:|---:|-| 父节点 8(=SHAPE_INTERP=0) | 59.80 | - | - | 59.04(rank3) |-| 机制开,无位移钳位 | 58.77 | - | - | - |-| 无钳位+随机抽样底座 | 58.79 | - | - | - |-| blend=0(仅质心收敛) | 58.44 | - | - | - |-| blend=0.5 | 58.62 | - | - | - |-| blend=1,钳 0.25/0.15 | 59.09/59.10 | - | - | - |-| **blend=1,钳 0.08(提交默认)** | **59.33** | **59.16** | **58.73** | **59.07** |-| blend=1,钳 0.04 | 59.30 | - | - | - |+## 3 种子确认(α=1.0,A 半) -## 结论(负面/持平,如实记录)+| seed | 榜分 | local_spatial | shape_scale |+|---|---:|---:|---:|+| 0 | 60.07 | 56.26 | 53.78 |+| 1 | 59.75 | 56.07 | 53.20 |+| 2 | 59.74 | 55.76 | 53.44 |+| 均值 | **59.85** | **56.03** | **53.47** | -- 机制按 PLAN 实现且确凿生效(20.2% 细胞被非刚性重排、质心/面积按 t 插值、occupancy 改变),但 proxy 上不提升 shape_scale / local_spatial:不钳位时两组分各降 ~1.3/~1.8 分,钳位越小越接近父节点,钳 0.08 时 3 种子均值 59.07 ≈ 父 59.04(噪声内持平)。-- 解释:proxy 共有型仅 5 个、覆盖 20% 细胞,杠杆不足(PLAN 风险 1 应验);且把两阶段同型细胞拉到同一 footprint 会增强局部混合,而节点 8 已证明局部混合方向对 local_spatial 无效——neighborhood_mmd 0.087→0.089 与此一致。-- 未验证:final 括号(E8.25+E8.75→E8.5,31 个共有型、覆盖率高得多)上机制杠杆更大,可能表现不同;本节点无法测。提交保持机制打开(钳 0.08),若 final 上共有型覆盖高,形变幅度自然更大。-- 生物学知识来源:仅方法卡/父节点的坐标系约定(z 为离散切片轴、保 z 的 procrustes 对齐),未引入新先验。+vs 父节点 9 rank3 = 59.17(local_spatial 53.97):+0.68,local_spatial +2.06(远超 T2 噪声 ~1 分,3 种子一致);shape_scale −0.43(噪声内)。与节点 10(非分层底座 + 同机制,rank3 60.13)方向一致。 -## 下一步建议+## 机制生效证据(proxy E8.25_late+E9.5→E8.75,t=0.4,seed0,α=1.0) -- 类型级坐标形变在 proxy 上判为无效方向(与节点 5 刚体位移、节点 8 空间分层同归);local_spatial/shape_scale 的三个坐标侧假设(刚体、非刚性、抽样)都已试完且均在噪声内。剩余空间更可能在表达侧(cell_state/expression_change 之外的组无法靠坐标移动)或外部数据(external/mosta_e95_v0 在 proxy 视图内可用,尚未被任何节点使用)。+- 融合细胞数 2273 / 17616 = **12.9% 输出细胞**(占被选 b 侧细胞 7046 的 32.3%;略低于 PLAN 的 15% 门槛,因为 proxy 共有型仅 5 个,非共有型的 b 细胞按设计不动)。+- 5 个共有型全部通过 ≥5 阈值:NCC 341、Peri 621、V-CM 814、aPHM 239、pPHM 258 个 b 细胞被融合。+- 融合前 b→a 同型最近邻平均距离 200.1(各型 102–405);融合后全局平均最近邻距离从 14.25(对照)降到 12.86(−9.8%),型内局部空间连续性恢复。+- 位移向量型内每轴 std 62.5–101.9 > 0:逐细胞位置依赖位移,非常数位移。+- 四组分响应:local_spatial 54.1→56.3(机制目标组,+2.1~2.3);shape_scale 53.8→53.8(持平);cell_state / expression_change 与对照逐位一致(X 未动)。+- occupancy 变化可见未崩塌(occupancy_dice 0.837 记录于查分 metrics;输出 RMS 346.3 与对照相同,缩放步骤在融合后统一执行)。++## 对照结果(mechanism_off_control)++NN_FUSE_ALPHA=0 输出与 NN_FUSE=0(=SHAPE_INTERP=0 父节点路径)逐位一致(X 稀疏非零差 0、坐标 array_equal),已在代码改动前后各验证一次。α=1.0 比 α=0 对照(seed0 59.80)高 0.27 分、local_spatial 高 2.13 分——机制在 local_spatial 上生效超过噪声,榜分增益小于组增益因 shape_scale 微降抵消一部分。++## 验证过 / 未验证++- 验证过:proxy 上 α∈{0,0.5,0.75,1.0,1.25,1.5}、3D vs xy、3 种子;off 对照逐位一致;vec-check 通过;seed 确定性(同 seed 重跑输出相同,rng 均来自 `np.random.default_rng(seed)`,cKDTree 查询确定)。+- 未验证:final 括号(E8.25+E8.75→E8.5,31 个共有型、覆盖率高得多,融合细胞占比会远高于 12.9%,效果预期更大但本节点无法测);α 在 final 上的最优值可能不同(proxy 峰值 1.0 与节点 10 独立分支一致,取 1.0 不另调)。+- 生物学知识来源:仅方法卡/父节点的坐标系约定(z 为离散切片轴、procrustes 保 z、各阶段自己的帧),未引入新的外部先验。++## 下一步++- 表达侧改进(cell_state 66.2 / expression_change 64.1 之外无杠杆;local_spatial 已 56):如 external/mosta_e95_v0 引导的密度加权或型内表达平滑。+- 节点 10(非分层底座,rank3 60.13)与本节点(分层底座,均值 59.85)可比较:分层抽样本身对 local_spatial 无增益(54.0 vs 54.1),融合才是有效部件;后续 improve 可直接在任一底座上叠表达侧机制。diff --git a/solution/nn_fuse.py b/solution/nn_fuse.pynew file mode 100644index 0000000..0d2bae1--- /dev/null+++ b/solution/nn_fuse.py@@ -0,0 +1,118 @@+"""mix + spatial stratification + per-type nearest-neighbour coordinate fusion (T2HI-04).++Pipeline identical to spatial_mix.interpolate_spatial (align=procrustes,+scale_damp=1, per-type spatially stratified (1-t, t) draw), plus one extra+step before jitter/rescale: for every cell type present in BOTH bracketing+stages (>= NN_MIN_TYPE_CELLS cells each side), a cKDTree is built over the+aligned+rescaled stage-a cells of that type and every picked stage-b cell+of the type is displaced by alpha * (nearest_a_neighbour - position) in 3D+(z included). Non-shared types and the expression matrix are untouched.+alpha = 0 skips fusion entirely -> bit-identical to the SHAPE_INTERP=0+parent (mechanism-off control).+"""++from __future__ import annotations++import numpy as np+from scipy.spatial import cKDTree++from src.task2_spatial.frame import align_pair, log_interp, rms_radius, scale_to_rms+from src.task2_spatial.methods import _jitter, _limits, _pack_expr+from src.task2_spatial.transport import as_dense++from spatial_mix import spatial_mix_indices++NN_MIN_TYPE_CELLS = 5+++def fuse_nn(coords: np.ndarray, labels_pick: np.ndarray, from_a: np.ndarray,+            labels_a: np.ndarray, labels_b: np.ndarray,+            ca: np.ndarray, cb: np.ndarray, alpha: float, fuse_ndim: int = 3) -> dict:+    """In-place displacement of picked b-side cells toward same-type a-side NNs."""+    diag = {"types": {}, "n_fused": 0, "disp_std_mean": 0.0, "nn_dist_before_mean": 0.0}+    if alpha == 0.0:+        return diag+    labels_a = np.asarray(labels_a).astype(str)+    labels_b = np.asarray(labels_b).astype(str)+    counts_a = {k: int(v) for k, v in zip(*np.unique(labels_a, return_counts=True))}+    counts_b = {k: int(v) for k, v in zip(*np.unique(labels_b, return_counts=True))}+    disp_stds, nn_dists = [], []+    for lab in sorted(set(counts_a) & set(counts_b)):+        if counts_a[lab] < NN_MIN_TYPE_CELLS or counts_b[lab] < NN_MIN_TYPE_CELLS:+            continue+        rows = np.flatnonzero(labels_pick == lab)+        rows_b = rows[~from_a[rows]]+        if rows_b.size == 0:+            continue+        xa = ca[labels_a == lab].astype(np.float64)+        tree = cKDTree(xa[:, :fuse_ndim])+        pos = coords[rows_b].astype(np.float64)+        dist, idx = tree.query(pos[:, :fuse_ndim], k=1)+        disp = np.zeros_like(pos)+        disp[:, :fuse_ndim] = alpha * (xa[idx][:, :fuse_ndim] - pos[:, :fuse_ndim])+        coords[rows_b] = pos + disp+        diag["n_fused"] += int(rows_b.size)+        diag["types"][lab] = {+            "n_b": int(rows_b.size),+            "nn_dist": float(np.mean(dist)),+            "disp_norm": float(np.mean(np.linalg.norm(disp, axis=1))),+            "disp_std": float(np.std(disp, axis=0).mean()),+        }+        disp_stds.append(float(np.std(disp, axis=0).mean()))+        nn_dists.append(float(np.mean(dist)))+    if disp_stds:+        diag["disp_std_mean"] = float(np.mean(disp_stds))+        diag["nn_dist_before_mean"] = float(np.mean(nn_dists))+    return diag+++def interpolate_fuse(stage_a, stage_b, t: float, params: dict,+                     cells_per_bin: int = 100, ndim: int = 2, alpha: float = 1.0, fuse_ndim: int = 3):+    t = float(t)+    damp = float(params.get("scale_damp", 1.0))+    align = str(params.get("align", "procrustes"))+    rng = np.random.default_rng(int(params.get("seed", 0)))++    aligned_a, aligned_b, info = align_pair(stage_a.coords, stage_b.coords, stage_a.labels, stage_b.labels, align)+    rms_a = rms_radius(stage_a.coords)+    rms_b = rms_radius(stage_b.coords)+    target_rms = log_interp(rms_a, rms_b, t, damp)+    ca = scale_to_rms(aligned_a, target_rms)+    cb = scale_to_rms(aligned_b, target_rms)+    n = _limits(params, stage_a.n, stage_b.n, t, "interp")++    ia, ib = spatial_mix_indices(stage_a.labels, stage_b.labels, ca, cb, t, n, rng, cells_per_bin, ndim)++    expr_parts, coord_parts = [], []+    if ia.size:+        expr_parts.append(as_dense(stage_a.X, ia))+        coord_parts.append(np.asarray(ca[ia], dtype=np.float64))+    if ib.size:+        expr_parts.append(as_dense(stage_b.X, ib))+        coord_parts.append(np.asarray(cb[ib], dtype=np.float64))++    expr = _pack_expr(expr_parts)+    coords = np.vstack(coord_parts)+    labels_pick = np.concatenate([+        np.asarray(stage_a.labels).astype(str)[ia],+        np.asarray(stage_b.labels).astype(str)[ib],+    ])+    from_a = np.concatenate([np.ones(ia.size, bool), np.zeros(ib.size, bool)])+    diag = fuse_nn(coords, labels_pick, from_a, stage_a.labels, stage_b.labels, ca, cb, float(alpha), fuse_ndim=int(fuse_ndim))+    coords = _jitter(coords, rng)+    coords = scale_to_rms(coords, target_rms)+    info.update(+        t=t, n=int(expr.shape[0]), rms_a=rms_a, rms_b=rms_b,+        target_rms=target_rms, out_rms=rms_radius(coords),+        coord="mix", expr="carry", blend="convex", scale_damp=damp,+        nearer="b" if t >= 0.5 else "a",+        n_from_a=int(ia.size), n_from_b=int(ib.size),+        spatial_stratify=True, cells_per_bin=cells_per_bin,+        nn_fuse=True, nn_alpha=float(alpha),+        n_fused=int(diag["n_fused"]),+        frac_fused=float(diag["n_fused"] / max(expr.shape[0], 1)),+        disp_std_mean=diag["disp_std_mean"],+        nn_dist_before_mean=diag["nn_dist_before_mean"],+        fuse_types=diag["types"],+    )+    return expr, coords.astype(np.float32), infodiff --git a/solution/run.py b/solution/run.pyindex 77b98b5..60068a7 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,19 +1,18 @@ #!/usr/bin/env python3-"""mix + per-type shape interpolation of xy coordinates (T2HI-02).+"""mix + spatial stratification + per-type NN coordinate fusion (T2HI-04). -Parent (node 8) pipeline: mix, align=procrustes, scale_damp=1, cells drawn-(1-t, t) stratified by type with spatial binning, expression and-coordinates travel together. New step (SHAPE_INTERP=1, default): every-cell type present in BOTH brackets (>= 20 cells each) gets its xy-footprint interpolated in time -- centroid mu_t=(1-t)mu_a+t mu_b,-covariance Sigma_t=exp((1-t)log Sigma_a + t log Sigma_b) (log-Euclidean)--- and its picked cells are affinely remapped onto that footprint-(x_new = mu_t + L_t L_src^-1 (x - mu_src), z untouched, discrete slice-axis). SHAPE_SHIFT_CLAMP caps the centroid displacement at that fraction-of the global xy RMS (default 0.08; large unclamped shifts hurt both-spatial groups on the proxy). SHAPE_BLEND scales the linear (shape) part-of the map; SHAPE_INTERP=0 is the mechanism-off control, bit-identical to-the parent (SPATIAL_STRATIFY=1).+Parent (node 9) pipeline with SHAPE_INTERP=0: mix, align=procrustes,+scale_damp=1, cells drawn (1-t, t) stratified by type with spatial+binning, expression and coordinates travel together (node 8 base; the+node-9 type-level xy shape interpolation was found inert on the proxy and+is disabled by default). New step (NN_FUSE=1, default): after the picks+are placed on the aligned+rescaled cloud, every cell type present in BOTH+brackets (>= NN_MIN_TYPE_CELLS cells each) gets a cKDTree over its+stage-a cells and each picked stage-b cell is displaced by+NN_FUSE_ALPHA * (nearest_a_neighbour - position) in 3D, restoring+within-type local spatial continuity of the mixed cloud. Non-shared types+and the expression matrix are untouched. NN_FUSE_ALPHA=0 (or NN_FUSE=0)+is the mechanism-off control, bit-identical to the SHAPE_INTERP=0 parent. If the target is not bracketed, falls back to the latest input before it. """ @@ -32,6 +31,7 @@ from src.task2_spatial.methods import interpolate from src.task2_spatial.sample import take from src.task2_spatial.view_io import board_params, interp_bracket, load_manifest, panel_genes, read_stage, write_t2 +from nn_fuse import interpolate_fuse from shape_interp import interpolate_shape from spatial_mix import interpolate_spatial @@ -39,9 +39,12 @@ PARAMS = {"align": "procrustes", "scale_damp": 1.0} CELLS_PER_BIN = int(os.environ.get("CELLS_PER_BIN", "100")) BIN_NDIM = int(os.environ.get("BIN_NDIM", "2")) SPATIAL_STRATIFY = os.environ.get("SPATIAL_STRATIFY", "1") != "0"-SHAPE_INTERP = os.environ.get("SHAPE_INTERP", "1") != "0"+SHAPE_INTERP = os.environ.get("SHAPE_INTERP", "0") != "0" SHAPE_BLEND = float(os.environ.get("SHAPE_BLEND", "1.0")) SHAPE_SHIFT_CLAMP = float(os.environ.get("SHAPE_SHIFT_CLAMP", "0.08"))+NN_FUSE = os.environ.get("NN_FUSE", "1") != "0"+NN_FUSE_ALPHA = float(os.environ.get("NN_FUSE_ALPHA", "1.0"))+NN_FUSE_NDIM = int(os.environ.get("NN_FUSE_NDIM", "3"))   def main() -> None:@@ -68,14 +71,20 @@ def main() -> None:                                                stratify=SPATIAL_STRATIFY,                                                cells_per_bin=CELLS_PER_BIN, ndim=BIN_NDIM,                                                blend=SHAPE_BLEND, shift_clamp=SHAPE_SHIFT_CLAMP)+    elif NN_FUSE and SPATIAL_STRATIFY:+        expr, coords, info = interpolate_fuse(stage_a, stage_b, t, params,+                                              cells_per_bin=CELLS_PER_BIN, ndim=BIN_NDIM,+                                              alpha=NN_FUSE_ALPHA, fuse_ndim=NN_FUSE_NDIM)     elif SPATIAL_STRATIFY:         expr, coords, info = interpolate_spatial(stage_a, stage_b, t, params, cells_per_bin=CELLS_PER_BIN, ndim=BIN_NDIM)     else:         expr, coords, info = interpolate(stage_a, stage_b, t, params)-    keep = {k: info.get(k) for k in ("t", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped", "align", "n_from_a", "n_from_b", "n_remap", "frac_remap", "n_clamped")}+    keep = {k: info.get(k) for k in ("t", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped", "align", "n_from_a", "n_from_b", "n_remap", "frac_remap", "n_clamped", "nn_alpha", "n_fused", "frac_fused", "disp_std_mean", "nn_dist_before_mean")}     print(json.dumps({"bracket": [a["stage"], b["stage"]], **keep}, default=float), file=sys.stderr)     if os.environ.get("SHAPE_DIAG"):         print(json.dumps(info.get("shape_types", {}), default=float), file=sys.stderr)+    if os.environ.get("FUSE_DIAG"):+        print(json.dumps(info.get("fuse_types", {}), default=float), file=sys.stderr)     write_t2(args.out, expr, coords, genes, seed=args.seed)  

调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。

用到的知识库条目

编号标题出处
k007Interval staging and held-out-window filtering of external datanotes/official/来件/virtualembryo.ai/rules.md
k026Canonicalise predicted 3D coordinates before submissionnotes/pitfalls/04_scorer_invariance.md
k027Joint expression-geometry generation with relative geometrynotes/competition/03_solution_landscape.md

分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。

改了什么关闭父节点9已证无效的类型级形状插值(SHAPE_INTERP=0),新增nn_fuse.py:对每个两阶段共有型(各>=5细胞),用cKDTree把被选中的b侧细胞向a侧同型最近邻做alpha倍3D位移(alpha=1.0,NDIM=3),表达矩阵不动;这是把节点10的型内近邻融合机制移植到空间分层底座。
各组分数的变化cell_state:不变 +0.00(66.95,X逐位未动,符合设计)
expression_change:不变 +0.00(64.37,X逐位未动,符合设计)
local_spatial:变好 +2.86(53.97->56.83,远超噪声,机制目标组)
shape_scale:噪声内 +0.59(53.90->54.49,T2噪声约1分)
family_idT2HI-04
假设是否成立是
经验
  1. 在mix+对齐缩放底座上,对共有型b侧细胞做cKDTree型内最近邻alpha倍位移(alpha=1.0,3D含z)可稳定提升local_spatial约+2~3分(节点10非分层底座+2.62,本节点分层底座+2.86),该机制跨底座可迁移。
  2. 3D融合优于仅xy(Engineer网格:alpha=1.0时56.26 vs NDIM=2的54.91),z轴也参与最近邻配对才能恢复局部连续性。
  3. alpha网格{0.5,0.75,1.0,1.25,1.5}在两个独立分支都在1.0附近取峰,且1.0过大并不塌缩shape_scale(本节点shape_scale反而微升),无需再调alpha。
  4. 已被证无效的部件应显式关闭(SHAPE_INTERP=0)而不是留在管线里,避免干扰与额外开销;本节点耗时1.9s、内存0.46GB与父持平。
  5. Engineer报告与变化量表一致(local_spatial提升、X不动、off对照逐位一致),alpha=0对照验证方法(逐位比较X与坐标)可复用为标准机制开关检验。
mechanism_active是
下一步建议
  1. 针对expression_change/cell_state(唯一未动的两组):在本底座上叠表达侧机制,如external/mosta_e95_v0引导的型内表达平滑或密度加权,坐标侧已接近饱和。
  2. 针对local_spatial:final括号有31个共有型(proxy仅5个、融合覆盖率12.9%),可保持alpha=1.0不动直接看final效果;若想在proxy上再挖,试NN_MIN_TYPE_CELLS从5降到3或把a侧最近邻查询改为k=3近邻均值,观察local_spatial是否再+1以上。
  3. 针对shape_scale(仍在53-55最弱区):坐标侧三假设(刚体、非刚性形变、抽样分层)均已试完且无效/持平,不建议再投坐标形变类改动,转向表达或外部数据。

对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。

只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。

分析员

角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。分析员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数?大模型一共回复了几轮(每轮可以调用多个工具)。2
工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。共 1 次:write 1
用时不到 1 分
token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。输入 11,067 · 输出 896 · 思考 196
任务(第一行)分析节点 n12 的打分结果,写 ANALYSIS.json
最后的回答(摘录)
ANALYSIS.json written
原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/analyst.jsonl 5 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/analyst.stderr

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数24
工具调用共 27 次:bash 15、edit 7、read 3、write 2
用时10 分
token 数输入 49,948 · 输出 10,023 · 思考 4,011
任务(第一行)按计划修改程序:mix+空间分层 上移植型内近邻坐标融合(T2HI-04),替换无效形状插值
最后的回答(摘录)
做了什么:在父节点 9 上关闭已证无效的形状插值(SHAPE_INTERP=0),新增 `nn_fuse.py`——共有型 b 侧细胞经 cKDTree 向 a 侧同型最近邻 3D 位移 α 倍(节点 10 机制移植到空间分层底座);α=0 对照与父节点逐位一致。

查分(用 10/20):α 网格 {0.5, 0.75, 1.0, 1.25, 1.5} = 59.49 / 59.85 / **60.07** / 60.04 / 59.82(seed0),xy-only 融合 59.73;α=1.0 三种子 60.07 / 59.75 / 59.74,均值 **59.85** vs 父 rank3 59.17。local_spatial 三种子一致 56.0±0.3(父 54.0,+2.1 超噪声),shape_scale 持平,X 逐位不变。提交 α=1.0、3D 融合,vec-check 通过、确定性验证通过。

下一步最值得试:表达侧机制(cell_state/expression_change 是当前最强但唯一未动的组),如用 external/mosta_e95_v0 引导密度加权或型内表达平滑;以及在本底座上直接叠节点 10 已验证部件的组合。
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/engineer.jsonl 152 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/engineer.stderr

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数1
工具调用共 0 次:—
用时1 分
token 数输入 10,687 · 输出 929 · 思考 3,367
任务(第一行)为节点 n12(改进,父节点 n9)写改进计划 PLAN.json
最后的回答(摘录)
```json
{
  "name": "mix+空间分层 上移植型内近邻坐标融合(T2HI-04),替换无效形状插值",
  "motivation": "父节点9的shape_interp已被证明无效(3种子均值59.07≈父59.04,ANALYSIS判死坐标形变方向)。全树最弱组为local_spatial 53.97、shape_scale 53.90。节点10在另一分支(node 7)上用型内近邻融合将local_spatial从54.03提升至56.65(+2.62,远超T2噪声1分),shape_scale +1.09,rank3达60.13(全树最佳)。该机制尚未在节点9的mix+空间分层分支上验证。ANALYSIS明确建议'已被证明有效的部件可以组合'。",
  "approach": "步骤:1) 在父节点9的pipeline中,将SHAPE_INTERP设为0(关闭已证无效的形状插值),保留SPATIAL_STRATIFY=1;2) 新增nn_fuse.py:Procrustes对齐+缩放后、输出前,对每个两阶段共有型(各≥5细胞),用scipy.spatial.cKDTree建a侧该型细胞的树,将b侧每个细胞向其a侧同型最近邻位移α倍(3D,含z);非共有型不动,表达矩阵不动;3) 参数:α默认1.0(节点10验证值),搜索范围{0.5, 0.75, 1.0, 1.5},用vec-score在seed0上快速筛选,选最优后跑seed1/2确认;4) 单输入阶段退路:b is None时直接走父节点fallback(无融合);5) 实现约60行,30分钟内可完成;6) 若α=1.0的seed0分数>60.5(超父0.7以上),直接提交;否则尝试α网格。",
  "expected_groups": ["local_spatial", "shape_scale"],
  "risks": "1) 节点9的空间分层抽样改变了细胞选取方式(k-means bin内按比例抽),可能使b侧细胞的最近邻分布与节点7不同,融合效果减弱——Engineer应在第一次查分后对比local_spatial是否>55;2) α过大导致坐标塌缩损害shape_scale——若shape_scale<53.5则降α;3) 提升可能在噪声内(<1分)——需3种子确认。尽早发现:seed0查分若<59.5即停止调参,如实报告。",
  "family_id": "T2HI-04",
  "mechanism": "对每个共有型,用cKDTree将b侧细胞向其a侧同型最近邻位移α倍,恢复混合后型内局部空间连续性(逐细胞、位置依赖的位移,非刚体)。",
  "vs_constant_shift": "常数位移对同型所有细胞施加相同向量;本机制每个细胞的位移方向和幅度取决于其空间位置与最近a侧邻居的相对关系,型内不同位置细胞获得不同位移,是局部配对而非全局平移。",
  "mechanism_evidence": "Engineer应记录:1) 被融合细胞数/占比(应>15%输出细胞);2) 融合前后型内平均最近邻距离(应显著下降);3) 位移向量的型内标准差(应>0,证明非常数位移);4) 四组分各自变化,特别是local_spatial和shape_scale;5) occupancy grid dice(应有可见变化但不至于崩塌,0.85-0.97)。",
  "mechanism_off_control": "设NN_FUSE_ALPHA=0(或环境变量NN_FUSE=0),跳过融合步骤,输出应与SHAPE_INTERP=0的父节点逐位一致(表达和坐标均不变)。预期差别:α=0时输出等于父节点关闭shape_interp的结果;α>0时local_spatial应提升>1分。",
  "sources": []
}
```
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/researcher.jsonl 4 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/researcher.stderr

审查员

角色审查员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数8
工具调用共 12 次:bash 7、read 4、write 1
用时2 分
token 数输入 26,885 · 输出 2,336 · 思考 4,842
任务(第一行)审查节点 n12 的程序是否越界读取、写死目标、钻评分器漏洞
最后的回答(摘录)
o absolute paths, `..`, `/mnt`, `/home`, `data/raw`, scorer paths, or network calls in any source. |
| 2 | 硬编码目标统计量 | Clean. No type names / ratio tables / gene lists. Constants (`NN_MIN_TYPE_CELLS=5`, `MIN_TYPE_CELLS=20`, `NN_FUSE_ALPHA=1.0`) are generic hyperparams; type sets/counts computed at runtime from input `labels` (nn_fuse.py:37-40, spatial_mix.py:30-47). |
| 3 | 钻评分器漏洞 | Clean. NN fusion is per-cell, position-dependent same-type displacement encoding a biological spatial-coherence prior; uses only input coords; not rotation/mirror (occupancy_dice chirality), not row-order, not averaging/global-scaling. Expression matrix untouched (cell_state/expression_change flat vs parent). local_spatial +2.86 exceeds ~1pt noise, 3-seed consistent. |
| 4 | 结果不确定 | Clean. `--seed` accepted (run.py:54); all randomness from `np.random.default_rng(seed)` (run.py:63, nn_fuse.py:74, spatial_mix.py:166); cKDTree deterministic. |
| 5 | 保留阶段/基因型 | Clean. No E8.5/E10.5/E12.5/(8.25,8.75)/9.5<E≤13.5 measurements and no Gata4/β-catenin info in code or METHOD.md. README final-view numbers (n=17616=manifest `max_cells`, RMS 277.1, 31 types) are computed on-the-fly from non-reserved inputs E8.25_late+E8.75; METHOD.md declares no new external prior. |
| 6 | 只在替代评测成立 | Clean. No hardcoded stage/file names; bracket from `interp_bracket(manifest)` (run.py:59); single-stage fallback (run.py:60-65); type/threshold logic generic — runs on final view (2-input bracket) via same path. |

Note on #5: `README.md` contains a forward-looking description of the final-view bracket (`E8.25_late + E8.75 → E8.5`) with expected aggregate numbers. I judged this non-fatal because the program computes everything at runtime and those numbers are not reserved-stage measurements nor consumed by any code path. Flagging it for transparency.

The deliverable `REVIEW.json` (verdict `pass` with the 6 per-criterion reasons) was written before plan mode engaged; no further file changes will be made unless you approve.
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/reviewer.jsonl 122 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/12/reviewer.stderr