1
Fork 0

refactor: migrate configs from JSON to YAML

This commit is contained in:
Tibo De Peuter 2026-04-08 20:37:47 +02:00
parent ae483b306f
commit e9b52e9e8f
Signed by: tdpeuter
SSH key fingerprint: SHA256:u/h/LVoqKF1Iz02uOyxe6hcjmoZASCGV2HM0TG9ZMoU
5 changed files with 22 additions and 28 deletions

View file

@ -1,8 +0,0 @@
{
"morphology": {
"num_arms": 2,
"num_segments_per_arm": 4,
"use_p_control": true,
"use_torque_control": false
}
}

5
configs/example.yaml Normal file
View file

@ -0,0 +1,5 @@
morphology:
num_arms: 2
num_segments_per_arm: 4
use_p_control: true
use_torque_control: false

View file

@ -10,7 +10,7 @@ from brittle_star_project import (
SimulationConfig, SimulationConfig,
simulate_policy, simulate_policy,
) )
from brittle_star_project.environment import from_json from brittle_star_project.environment import from_file
from brittle_star_project.rl import RLModel # imports concrete models via rl.__init__ from brittle_star_project.rl import RLModel # imports concrete models via rl.__init__
from brittle_star_project.rl.base import get_rl_model_registry from brittle_star_project.rl.base import get_rl_model_registry
@ -44,7 +44,7 @@ def parse_args() -> argparse.Namespace:
def main() -> None: def main() -> None:
args = parse_args() args = parse_args()
morphology_cfg, arena_cfg, env_cfg = from_json("../configs/test.json") morphology_cfg, arena_cfg, env_cfg = from_file("../configs/test.yaml")
# ======= ENVIRONMENT SETUP ======= # ======= ENVIRONMENT SETUP =======

View file

@ -1,7 +1,6 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass, field from dataclasses import dataclass, field
import json
from .env_types import Task from .env_types import Task
@ -51,14 +50,11 @@ class EnvConfig:
def from_file(path: str) -> tuple[MorphologyConfig, ArenaConfig, EnvConfig]: def from_file(path: str) -> tuple[MorphologyConfig, ArenaConfig, EnvConfig]:
"""Load configurations from a JSON or YAML file.""" """Load configurations from a YAML file."""
with open(path, "r") as f: import yaml
if path.endswith(".yaml") or path.endswith(".yml"):
import yaml
config_dict = yaml.safe_load(f) with open(path, "r") as f:
else: config_dict = yaml.safe_load(f)
config_dict = json.load(f)
morphology = MorphologyConfig(**config_dict.get("morphology", {})) morphology = MorphologyConfig(**config_dict.get("morphology", {}))
arena = ArenaConfig(**config_dict.get("arena", {})) arena = ArenaConfig(**config_dict.get("arena", {}))

View file

@ -7,9 +7,9 @@ This logger ensures all experimental data is preserved by writing to:
""" """
import datetime import datetime
import json
import logging import logging
import subprocess import subprocess
import yaml
import sys import sys
import time import time
from pathlib import Path from pathlib import Path
@ -99,7 +99,7 @@ class UnifiedLogger:
self.metrics_dir = self.run_dir / "metrics" self.metrics_dir = self.run_dir / "metrics"
self.metrics_dir.mkdir(exist_ok=True) self.metrics_dir.mkdir(exist_ok=True)
self.config_file = self.run_dir / "config.json" self.config_file = self.run_dir / "config.yaml"
# Setup standard Python logging mirror # Setup standard Python logging mirror
self.text_log_file = self.run_dir / "run.log" self.text_log_file = self.run_dir / "run.log"
@ -196,7 +196,7 @@ class UnifiedLogger:
"""Save configuration to disk.""" """Save configuration to disk."""
try: try:
with open(self.config_file, "w") as f: with open(self.config_file, "w") as f:
json.dump(self.config, f, indent=2) yaml.dump(self.config, f, default_flow_style=False, indent=2, sort_keys=False)
self.info(f"Config saved to {self.config_file}") self.info(f"Config saved to {self.config_file}")
except Exception as e: except Exception as e:
self.error(f"Error saving config: {e}") self.error(f"Error saving config: {e}")
@ -263,10 +263,10 @@ class UnifiedLogger:
return return
try: try:
metrics_file = self.metrics_dir / "metrics.jsonl" metrics_file = self.metrics_dir / "metrics.yaml"
with open(metrics_file, "a") as f: with open(metrics_file, "a") as f:
for metric in self.metrics_buffer: for metric in self.metrics_buffer:
# Convert numpy/jax types to native Python types for JSON serialization # Convert numpy/jax types to native Python types for YAML serialization
serializable_metric = {} serializable_metric = {}
for k, v in metric.items(): for k, v in metric.items():
if hasattr(v, "item"): # numpy/jax scalar if hasattr(v, "item"): # numpy/jax scalar
@ -275,7 +275,8 @@ class UnifiedLogger:
serializable_metric[k] = v.tolist() serializable_metric[k] = v.tolist()
else: else:
serializable_metric[k] = v serializable_metric[k] = v
f.write(json.dumps(serializable_metric) + "\n") f.write("---\n")
yaml.dump(serializable_metric, f, default_flow_style=False)
self.metrics_buffer.clear() self.metrics_buffer.clear()
except Exception as e: except Exception as e:
self.error(f"Error flushing metrics: {e}") self.error(f"Error flushing metrics: {e}")
@ -298,9 +299,9 @@ class UnifiedLogger:
# Save metadata if provided # Save metadata if provided
if metadata: if metadata:
metadata_path = self.checkpoints_dir / f"{prefix}_step_{step}_metadata.json" metadata_path = self.checkpoints_dir / f"{prefix}_step_{step}_metadata.yaml"
with open(metadata_path, "w") as f: with open(metadata_path, "w") as f:
json.dump(metadata, f, indent=2) yaml.dump(metadata, f, default_flow_style=False)
self.info(f"Checkpoint saved: {checkpoint_path}") self.info(f"Checkpoint saved: {checkpoint_path}")
@ -334,9 +335,9 @@ class UnifiedLogger:
f.write(flax.serialization.to_bytes(params)) f.write(flax.serialization.to_bytes(params))
if metadata: if metadata:
metadata_path = self.run_dir / "final_model_metadata.json" metadata_path = self.run_dir / "final_model_metadata.yaml"
with open(metadata_path, "w") as f: with open(metadata_path, "w") as f:
json.dump(metadata, f, indent=2) yaml.dump(metadata, f, default_flow_style=False)
self.info(f"Final model saved: {final_model_path}") self.info(f"Final model saved: {final_model_path}")