ThomasHeisig's picture
Sync GitHub main e8a04aea24121d15707238534e635cf0ceee8eaf (part 8)
250836c verified
Raw History Blame Contribute Delete
5.99 kB
"""CLI entry point for the isolated MHRN Playground."""
from __future__ import annotations
import argparse
import json
from .service import catalog, replay, robustness, run
from .visualize.session_dashboard import dashboard_payload
from .visualize.topology_2d import project_2d
from .visualize.topology_3d import project_3d
from .visualize.topology_5d_projection import project_5d
def _projection(result: dict[str, object], mode: str) -> object:
topology = result.get("topology", {})
coordinates = topology.get("coordinates", []) if isinstance(topology, dict) else []
if mode == "2d":
return project_2d(coordinates)
if mode == "3d":
return project_3d(coordinates)
return project_5d(coordinates, components=2)
def _add_run_arguments(parser: argparse.ArgumentParser) -> None:
parser.add_argument("--ticks", type=int, default=256)
parser.add_argument("--neurons", type=int, default=128)
parser.add_argument("--edges", type=int, default=512)
parser.add_argument("--seed", type=int, default=12345)
parser.add_argument("--dimensions", type=int, default=5)
parser.add_argument("--model", default="izhikevich_rs")
parser.add_argument("--topology", default="mhrn_5d")
parser.add_argument("--synapse", default="static")
parser.add_argument("--plasticity", default="none")
parser.add_argument("--stimulus", default="deterministic")
parser.add_argument("--ensemble", type=int, default=1)
parser.add_argument("--geometry-mode", default="shortcut_union")
parser.add_argument("--geometry-lambda-a", type=float, default=0.5)
parser.add_argument("--geometry-lambda-b", type=float, default=0.5)
parser.add_argument("--geometry-sigma", type=float, default=0.1)
parser.add_argument("--geometry-p0", type=float, default=0.3)
parser.add_argument("--geometry-delay-velocity", type=float, default=0.25)
parser.add_argument("--neural-io", action="store_true")
parser.add_argument("--io-input-channels", type=int, default=16)
parser.add_argument("--io-output-channels", type=int, default=16)
parser.add_argument("--io-codec", default="population_latency_v1")
parser.add_argument("--io-decoder", default="population_rate_v1")
parser.add_argument("--io-payload", default="0.5")
parser.add_argument("--io-window", type=int, default=16)
parser.add_argument("--io-current", type=float, default=25.0)
parser.add_argument("--persist", action="store_true")
def _io_payload(args: argparse.Namespace) -> object:
raw = args.io_payload
if args.io_codec == "population_latency_v1":
return float(raw)
if args.io_codec == "vector_population_v1":
value = json.loads(raw)
if not isinstance(value, list):
raise ValueError("--io-payload must be a JSON list for vector codec")
return value
return raw
def _payload(args: argparse.Namespace) -> dict[str, object]:
return {
"ticks": args.ticks,
"n_neurons": args.neurons,
"edge_budget": args.edges,
"seed": args.seed,
"dimensions": args.dimensions,
"neuron_model": args.model,
"topology": args.topology,
"synapse_model": args.synapse,
"plasticity_rule": args.plasticity,
"stimulus": args.stimulus,
"ensemble_runs": args.ensemble,
"geometry_mode": args.geometry_mode,
"geometry_lambda_a": args.geometry_lambda_a,
"geometry_lambda_b": args.geometry_lambda_b,
"geometry_sigma": args.geometry_sigma,
"geometry_p0": args.geometry_p0,
"geometry_delay_velocity": args.geometry_delay_velocity,
"neural_io_enabled": args.neural_io,
"neural_io_input_channels": args.io_input_channels,
"neural_io_output_channels": args.io_output_channels,
"neural_io_input_codec": args.io_codec,
"neural_io_output_decoder": args.io_decoder,
"neural_io_input_payload": _io_payload(args),
"neural_io_window_ticks": args.io_window,
"neural_io_input_current": args.io_current,
"persist": args.persist,
}
def main() -> int:
parser = argparse.ArgumentParser(description="MHRN non-canonical Playground")
sub = parser.add_subparsers(dest="command", required=True)
sub.add_parser("catalog")
sub.add_parser("list-models")
sub.add_parser("list-topologies")
runner = sub.add_parser("run")
_add_run_arguments(runner)
robust = sub.add_parser("robustness")
_add_run_arguments(robust)
replayer = sub.add_parser("replay")
replayer.add_argument("session_id")
visualizer = sub.add_parser("visualize")
visualizer.add_argument("session_id")
visualizer.add_argument("--projection", choices=("2d", "3d", "5d"), default="5d")
args = parser.parse_args()
info = catalog()
if args.command == "catalog":
print(json.dumps(info, indent=2, ensure_ascii=False))
return 0
if args.command == "list-models":
print(json.dumps(info["models"], indent=2, ensure_ascii=False))
return 0
if args.command == "list-topologies":
print(json.dumps(info["topologies"], indent=2, ensure_ascii=False))
return 0
if args.command == "replay":
print(json.dumps(replay(args.session_id), indent=2, ensure_ascii=False))
return 0
if args.command == "visualize":
result = replay(args.session_id)
output = {
"session_id": args.session_id,
"projection": args.projection,
"points": _projection(result, args.projection),
"dashboard": dashboard_payload(result),
}
print(json.dumps(output, indent=2, ensure_ascii=False))
return 0
if args.command == "robustness":
print(json.dumps(robustness(_payload(args)), indent=2, ensure_ascii=False))
return 0
print(json.dumps(run(_payload(args)), indent=2, ensure_ascii=False))
return 0
if __name__ == "__main__":
raise SystemExit(main())