Buckets:
| #!/usr/bin/env python3 | |
| """build_l1_structure — L1 结构层落地(v2:region 分五级可信度)。 | |
| region 不是一个可比的键,而是五种不同强度的证据。分级规则(按 mapping_status): | |
| exact / exact_single_species -> anatomical 解剖定位,且有本体节点 | |
| uberon_missing -> anatomical_unmapped 解剖定位,但无 UBERON 节点 | |
| task_code_reinterpreted -> inferred 由任务码推定,不是解剖定位 | |
| compound -> compound 一个标签覆盖多个区(如 M1_PMd) | |
| coarse / rollup -> coarse 粗粒度或上卷 | |
| unassigned / 缺失 -> none 无解剖标签 | |
| 产出 structure.parquet(带 region_confidence)与 joins.json(带各级计数与建议用法)。 | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from pathlib import Path | |
| import numpy as np | |
| import pandas as pd | |
| ROOT = Path("/domains") | |
| OUT = ROOT / "framework" | |
| rows = [] | |
| notes = {} | |
| CONF = { | |
| "exact": "anatomical", | |
| "exact_single_species": "anatomical", | |
| "uberon_missing": "anatomical_unmapped", | |
| "task_code_reinterpreted": "inferred", | |
| "compound": "compound", | |
| "coarse": "coarse", | |
| "rollup": "coarse", | |
| "unassigned": "none", | |
| } | |
| def conf_series(s): | |
| return s.map(CONF).fillna("none") | |
| # 粗标签解析到父区(与 counts-v4 既有映射一致,不引入新精度) | |
| RESOLVE = {"DMFC": "PFC", "Area2": "S1"} | |
| def add(df, level, member, provenance, conf=None): | |
| d = df.copy() | |
| for c in ["source", "species", "modality", "region", "region_kind", "domain_l1"]: | |
| if c not in d.columns: | |
| d[c] = None | |
| d["region_resolved"] = d["region"].map( | |
| lambda r: RESOLVE.get(str(r), r) if pd.notna(r) else r) | |
| d["region_resolution"] = d["region"].map( | |
| lambda r: "parent_rollup" if str(r) in RESOLVE else "as_labeled") | |
| if member == "steinmetz": | |
| d["region_assignment"] = "per_unit" | |
| elif member == "counts_v4": | |
| d["region_assignment"] = "per_segment" | |
| elif member == "flywire": | |
| d["region_assignment"] = "per_node" | |
| elif member == "omnibrain_multi": | |
| d["region_assignment"] = np.where( | |
| d["source"].astype(str) == "mouse_steinmetz", "session_majority", "window_area") | |
| else: | |
| d["region_assignment"] = "unknown" | |
| if isinstance(conf, str) and conf in d.columns: | |
| d["region_confidence"] = conf_series(d[conf]) | |
| else: | |
| d["region_confidence"] = conf or "none" | |
| g = (d.groupby(["source", "species", "modality", "region", "region_resolved", | |
| "region_resolution", "region_assignment", "region_kind", | |
| "region_confidence", "domain_l1"], dropna=False) | |
| .size().reset_index(name="n")) | |
| g["level"] = level | |
| g["member"] = member | |
| g["provenance"] = provenance | |
| rows.append(g[["level", "member", "source", "species", "modality", "region", | |
| "region_resolved", "region_resolution", "region_assignment", | |
| "region_kind", "region_confidence", "domain_l1", "n", "provenance"]]) | |
| notes[member] = {"rows_in": int(len(d)), "groups": int(len(g)), | |
| "confidence": d.region_confidence.value_counts().to_dict()} | |
| # 1) 小鼠:单元级,Allen 缩写,属解剖定位 | |
| u = pd.read_parquet(ROOT / "steinmetz/units.parquet") | |
| u["source"] = "mouse_steinmetz" | |
| u["species"] = "mus_musculus" | |
| u["modality"] = "extracellular_spike" | |
| u["domain_l1"] = u["functional_domain"] | |
| u["region_kind"] = "anatomy" | |
| add(u, "unit", "steinmetz", "steinmetz/units.parquet", conf="anatomical") | |
| # 2) counts-v4:片段级,带 mapping_status | |
| ci = pd.read_parquet(ROOT / "counts-v4/counts_index.parquet") | |
| add(ci, "segment", "counts_v4", "counts-v4/counts_index.parquet", conf="mapping_status") | |
| # 3) omnibrain-multi:窗级标签,带 mapping_status | |
| mi = pd.read_parquet(ROOT / "omnibrain-multi/index_timeseries.parquet") | |
| for c in ["domain_l1", "region_kind", "mapping_status"]: | |
| if c not in mi.columns: | |
| mi[c] = None | |
| add(mi, "window", "omnibrain_multi", "omnibrain-multi/index_timeseries.parquet", | |
| conf="mapping_status") | |
| # 4) FlyWire:super_class 属粗粒度分组 | |
| fw = pd.read_parquet(ROOT / "flywire/node_features.parquet") | |
| fw["source"] = "flywire" | |
| fw["species"] = "drosophila_melanogaster" | |
| fw["modality"] = "connectome" | |
| fw["region_kind"] = "anatomy" | |
| fw["domain_l1"] = None | |
| add(fw, "node", "flywire", "flywire/node_features.parquet", conf="coarse") | |
| S = pd.concat(rows, ignore_index=True) | |
| S = S[S.region.notna() | S.domain_l1.notna()] | |
| S.to_parquet(OUT / "structure.parquet", index=False) | |
| S.to_csv(OUT / "structure.csv", index=False) | |
| def keyinfo(key, kind, members, semantics, joinable, caveat, extra=None, | |
| vocab_rel="shared"): | |
| per = {} | |
| for m in members: | |
| sub = S[(S.member == m) & S[key].notna()] | |
| per[m] = sorted(set(sub[key].astype(str))) | |
| union = set().union(*per.values()) if per else set() | |
| rec = dict(key=key, kind=kind, members=members, n_distinct_union=len(union), | |
| n_distinct_by_member={m: len(v) for m, v in per.items()}, | |
| vocabulary_relation=vocab_rel, | |
| values_by_member={m: v[:25] for m, v in per.items()}, | |
| joinable_across_members=joinable, | |
| semantics=semantics, caveat=caveat) | |
| if extra: | |
| rec.update(extra) | |
| return rec | |
| members_with_region = sorted(S[S.region.notna()].member.unique()) | |
| members_with_domain = sorted(S[S.domain_l1.notna()].member.unique()) | |
| conf_by_level = (S.groupby(["level", "region_confidence"]).n.sum() | |
| .unstack(fill_value=0).to_dict(orient="index")) | |
| conf_by_member = (S.groupby(["member", "region_confidence"]).n.sum() | |
| .unstack(fill_value=0).to_dict(orient="index")) | |
| keys = [ | |
| keyinfo("source", "categorical", sorted(S.member.unique()), | |
| "数据来源(数据集/片段集合)", True, | |
| "同名 source 在 counts_v4 与 steinmetz 中是同一批记录的不同编码"), | |
| keyinfo("species", "categorical", sorted(S.member.unique()), | |
| "物种", True, "只有 3 个值;EEG 与侵入式共用 homo_sapiens"), | |
| keyinfo("modality", "categorical", sorted(S.member.unique()), | |
| "记录模态", True, "scalp_eeg 与 intracortical 在 L2 的可用不变量不同"), | |
| keyinfo("region", "anatomical_node", members_with_region, | |
| "解剖区(偏序节点,不是层级)", "partial", | |
| "三套词表(Allen / Brodmann / FlyWire super_class)不能直接相等;" | |
| "且同一列混了五种证据强度,跨成员比较必须先用 region_confidence 过滤", | |
| vocab_rel="multi_vocabulary", | |
| extra={"region_confidence_by_level": {lv: {k: int(v) for k, v in d.items()} | |
| for lv, d in conf_by_level.items()}, | |
| "region_confidence_by_member": {m: {k: int(v) for k, v in d.items()} | |
| for m, d in conf_by_member.items()}, | |
| "mapping_status_raw": (mi["mapping_status"].value_counts().to_dict() | |
| if "mapping_status" in mi.columns else None), | |
| "region_assignment": { | |
| "note": "标签的归属粒度;与 region_confidence(映射质量)是两个维度", | |
| "counts": {k: int(v) for k, v in | |
| S.groupby("region_assignment").n.sum().items()}, | |
| "session_majority_accuracy": 0.271, | |
| "session_majority_evidence": "39 个 session 的主导区占比中位 26.6%;" | |
| "单元加权正确率 27.1%(其余 72.9% 的单元被归到错误区);" | |
| "仅 9/39 个 session 的占比 ≥30%,0/39 ≥70%"}, | |
| "recommended_filter": "跨物种/跨成员比较只用 region_confidence == 'anatomical';" | |
| "'inferred' 与 'compound' 必须在图注中单列;region_assignment == 'session_majority' 的数据不可用于区级分析"}), | |
| keyinfo("domain_l1", "functional_node", members_with_domain, | |
| "功能域(multi 是 6 类 L1;小鼠 units 表是 13 个 functional_domain)", "partial", | |
| "两套词表:13 个 functional_domain 未与 6 个 L1 域对齐;与 region 也不可交换", | |
| vocab_rel="multi_vocabulary"), | |
| dict(key="unit", kind="instance", members=["steinmetz", "primate_macaque_nlb", | |
| "primate_dmfc_rsg", "counts_v4_ragged"], | |
| joinable_across_members=False, | |
| semantics="单个神经元/通道", | |
| caveat="跨成员的 unit 列不是同一个神经元;禁止拼接或按列对齐"), | |
| dict(key="window", kind="sampling", members=["omnibrain_multi", "omnibrain_spike_view"], | |
| joinable_across_members=False, | |
| semantics="100 ms × 8 bin 的滑动窗", | |
| caveat="窗是派生采样单位,不同成员的 stride/长度不同,不能当样本键"), | |
| dict(key="trial", kind="instance", members=["primate_human_eeg", "omnibrain4d_eeg_test"], | |
| joinable_across_members=False, | |
| semantics="试次", | |
| caveat="不同数据集试次编号无共同含义"), | |
| ] | |
| axes = ["source", "region", "domain_l1"] | |
| d = mi.dropna(subset=["region"]) | |
| obs = d.groupby(axes, dropna=False).ngroups | |
| theo = int(np.prod([d[a].nunique() for a in axes])) | |
| holes = dict(axes=axes, observed=int(obs), theoretical=int(theo), | |
| empty_fraction=round(1 - obs / theo, 3) if theo else None, | |
| n_per_axis={a: int(d[a].nunique()) for a in axes}, | |
| source="omnibrain-multi/index_timeseries.parquet") | |
| joins = dict(schema_version="1.1", | |
| note="L1 只放结构键与覆盖计数,不含活动数据;join 合法性按语义判定,不按列名", | |
| keys=keys, holes=holes, | |
| levels={lvl: int(g.member.nunique()) for lvl, g in S.groupby("level")}, | |
| members=notes) | |
| (OUT / "joins.json").write_text(json.dumps(joins, indent=2, ensure_ascii=False), | |
| encoding="utf-8") | |
| print(f"structure rows={len(S)}") | |
| print("confidence by level:", | |
| pd.DataFrame(conf_by_level).fillna(0).astype(int).to_string()) | |
| print("\nby member:") | |
| print(conf_by_member and pd.DataFrame(conf_by_member).fillna(0).astype(int).to_string()) | |
| print("\nholes:", holes["empty_fraction"], holes["observed"], "/", holes["theoretical"]) | |
Xet Storage Details
- Size:
- 10.7 kB
- Xet hash:
- 44d714aa2fc46edea9cbc6e31578133099a9f3f4b705f02d52f2e226116c4084
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.