#!/usr/bin/env python3 """Seed the Field Atlas / commons from published DMS studies (ESM-free). Turns a set of public DMS assays into de-identified substitution-effect rows (dee.core.dms_seed → the same k-anonymized aggregation user data goes through) so the commons has real, citable value on day one. No model needed — this only pools measured values by substitution TYPE, keeping a substitution only when ≥ MIN_USERS independent studies measured it. Input: a manifest JSON, a list of assays: [ {"name": "...", "csv": "path/to/dms.csv"}, ... ] (ProteinGym-style CSVs: a 'mutant' column + a 'DMS_score' column.) By default it WRITES the rows to a JSON file for review. Pass --push to upload them to public.mutation_priors via dee.auth (requires SUPABASE creds in the environment — run it where the service key lives, e.g. the deploy box). Usage: python scripts/seed_commons_from_dms.py manifest.json [--out seed_rows.json] [--push] """ import argparse import json import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from dee.core.dms_seed import parse_proteingym_csv, seed_rows # noqa: E402 def main(): ap = argparse.ArgumentParser() ap.add_argument("manifest") ap.add_argument("--out", default="seed_rows.json") ap.add_argument("--push", action="store_true", help="upload to public.mutation_priors (needs SUPABASE env)") args = ap.parse_args() assays = [] for a in json.loads(Path(args.manifest).read_text(encoding="utf-8")): recs = parse_proteingym_csv(Path(a["csv"]).read_text(encoding="utf-8")) if recs: assays.append((a.get("name", a["csv"]), recs)) print(f" {a.get('name', a['csv']):28s} {len(recs):7d} records") rows = seed_rows(assays) # enforces the effective-date gate + k-anonymity Path(args.out).write_text(json.dumps(rows, indent=2), encoding="utf-8") print(f"\n{len(rows)} de-identified substitution row(s) (>= MIN_USERS studies each) -> {args.out}") if args.push: from dee import auth result = auth.replace_mutation_priors(rows) print(f"push -> {result}") else: print("(dry run — pass --push to upload to the live commons)") if __name__ == "__main__": main()