yushg's picture
Upload folder using huggingface_hub
a2d6a2a verified
Raw
History Blame Contribute Delete
8.05 kB
"""`ald-screen` command-line interface.
Examples:
ald-screen run examples/wf6_w.json
ald-screen run examples/wf6_w.json --json
ald-screen run examples/new_material_screen.json --csv out.csv --uma
ald-screen recipes # list the known-good calibration recipes
ald-screen demo # run the WF6 -> W headline case
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from densitygen.data import KNOWN_RECIPES
from densitygen.design import design
from densitygen.reporting import render_csv, render_report
from densitygen.schemas import Candidate, ScreeningRequest
from densitygen.screen import screen
def _run(args: argparse.Namespace) -> int:
payload = json.loads(Path(args.request).read_text())
if args.uma:
payload["use_ml_potential"] = True
request = ScreeningRequest.model_validate(payload)
resp = screen(request)
if args.csv:
Path(args.csv).write_text(render_csv(resp))
print(f"wrote {args.csv}", file=sys.stderr)
if args.json:
print(resp.model_dump_json(indent=2))
else:
print(render_report(resp))
return 0
def _recipes(_args: argparse.Namespace) -> int:
print("Known-good ALD recipes (calibration / regression set):\n")
for r in KNOWN_RECIPES:
print(f" {r.precursor:<8} + {r.co_reactant:<6} -> {r.film:<6} {r.note}")
return 0
def _demo(args: argparse.Namespace) -> int:
# The headline test case the platform is built around: WF6 -> W, screened
# against a couple of foils so the ranking behavior is visible.
request = ScreeningRequest(
film="W",
co_reactant="B2H6",
temperature_max_c=350,
use_ml_potential=args.uma,
candidates=[
Candidate(name="WF6"),
Candidate(name="WCl6", formula="WCl6"),
Candidate(name="TMA"), # foil: contains no W, must hard-fail
],
)
print(render_report(screen(request)))
return 0
def _viz(args: argparse.Namespace) -> int:
"""Bake the interactive viz bundle from a screening request."""
from densitygen.viz import response_to_payload, write_bundle
payload_in = json.loads(Path(args.request).read_text())
if args.uma:
payload_in["use_ml_potential"] = True
request = ScreeningRequest.model_validate(payload_in)
resp = screen(request)
data = response_to_payload(resp, request=request, mode="screen")
entry = write_bundle(data, args.out)
print(f"wrote viz bundle to {Path(args.out).resolve()}", file=sys.stderr)
print(f"open: {entry}", file=sys.stderr)
print(f" (or run `ald-screen serve {args.request}` for live precursor suggestions)",
file=sys.stderr)
return 0
def _serve(args: argparse.Namespace) -> int:
from densitygen.server import serve
if args.request:
payload_in = json.loads(Path(args.request).read_text())
request = ScreeningRequest.model_validate(payload_in)
else:
# A sensible default demo so `ald-screen serve` works with no args.
request = ScreeningRequest(
film="HfO2", co_reactant="H2O", temperature_max_c=300,
forbidden_elements=["Cl"],
candidates=[
Candidate(name="TEMAH"), Candidate(name="HfCl4"),
Candidate(name="TDMAH", formula="Hf[N(CH3)2]4"),
Candidate(name="Hf(OtBu)4", formula="Hf(OC4H9)4"),
],
)
serve(request, host=args.host, port=args.port, bundle_dir=args.out)
return 0
def _design(args: argparse.Namespace) -> int:
resp = design(
film=args.film,
co_reactant=args.co_reactant,
temperature_max_c=args.temperature_max_c,
forbidden_elements=[e.strip() for e in (args.forbidden or "").split(",") if e.strip()],
oxidation=args.oxidation,
top_n=args.top_n,
use_ml_potential=args.uma,
)
if args.json:
print(resp.model_dump_json(indent=2))
else:
print(render_report(resp))
return 0
def _interconnects(args: argparse.Namespace) -> int:
from densitygen.interconnects import (
HAVE_PRECURSORS, NEED_PRECURSORS, run_design_bucket, run_test_bucket)
print("=" * 72)
print("INTERCONNECT RESISTANCE — alternative metals to beat Cu/W at scaled nodes")
print("=" * 72)
print("\n### BUCKET A — materials WITH precursors: end-to-end screening tests ###")
for t in HAVE_PRECURSORS:
print(f"\n>>> {t.film}: {t.why}")
print(render_report(run_test_bucket(t, use_ml_potential=args.uma)))
print("\n\n### BUCKET B — materials WITHOUT precursors: inverse-design demos ###")
for t in NEED_PRECURSORS:
print(f"\n>>> {t.film}: {t.why}")
print(f" ({t.note})")
print(render_report(run_design_bucket(t, use_ml_potential=args.uma, top_n=args.top_n)))
return 0
def main(argv: list[str] | None = None) -> int:
p = argparse.ArgumentParser(prog="ald-screen", description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
sub = p.add_subparsers(dest="cmd", required=True)
pr = sub.add_parser("run", help="screen candidates from a JSON request file")
pr.add_argument("request", help="path to a ScreeningRequest JSON file")
pr.add_argument("--json", action="store_true", help="emit JSON instead of a text report")
pr.add_argument("--csv", metavar="PATH", help="also write a CSV scorecard")
pr.add_argument("--uma", action="store_true", help="use the hosted UMA model on Replicate")
pr.set_defaults(func=_run)
prc = sub.add_parser("recipes", help="list known-good calibration recipes")
prc.set_defaults(func=_recipes)
pd = sub.add_parser("demo", help="run the WF6 -> W headline case")
pd.add_argument("--uma", action="store_true", help="use the hosted UMA model")
pd.set_defaults(func=_demo)
pv = sub.add_parser("viz", help="bake the interactive viz bundle from a request JSON")
pv.add_argument("request", help="path to a ScreeningRequest JSON file")
pv.add_argument("--out", default="densitygen_viz", help="output bundle directory")
pv.add_argument("--uma", action="store_true", help="use the hosted UMA model")
pv.set_defaults(func=_viz)
ps = sub.add_parser("serve", help="serve the viz with a live /api/screen for precursor suggestions")
ps.add_argument("request", nargs="?", default=None,
help="optional ScreeningRequest JSON; omitted -> HfO2 demo")
ps.add_argument("--host", default="127.0.0.1")
ps.add_argument("--port", type=int, default=8765)
ps.add_argument("--out", default="densitygen_viz", help="bundle directory to serve")
ps.set_defaults(func=_serve)
pg = sub.add_parser("design", help="PROPOSE novel precursors for a film (inverse design)")
pg.add_argument("--film", required=True, help="target film, e.g. W, Mo, HfO2")
pg.add_argument("--co-reactant", dest="co_reactant", default=None)
pg.add_argument("--temperature-max-c", dest="temperature_max_c", type=float, default=None)
pg.add_argument("--forbidden", default="", help="comma-separated elements to exclude")
pg.add_argument("--oxidation", type=int, default=None, help="metal oxidation state override")
pg.add_argument("--top-n", dest="top_n", type=int, default=12)
pg.add_argument("--uma", action="store_true", help="confirm top survivors with real UMA energies")
pg.add_argument("--json", action="store_true")
pg.set_defaults(func=_design)
pi = sub.add_parser("interconnects",
help="interconnect-resistance demo: screen materials with "
"precursors, design ones without")
pi.add_argument("--uma", action="store_true", help="use real ML-potential energies")
pi.add_argument("--top-n", dest="top_n", type=int, default=6)
pi.set_defaults(func=_interconnects)
args = p.parse_args(argv)
return args.func(args)
if __name__ == "__main__":
raise SystemExit(main())