| """ |
| Simple logging utilities for teleop evaluation. |
| """ |
|
|
| from datetime import datetime |
| import os |
| from pathlib import Path |
| from typing import Any, Dict |
|
|
| import numpy as np |
|
|
| import decoupled_wbc |
|
|
|
|
| class EvaluationLogger: |
| """Simple logger that writes evaluation metrics to a timestamped file.""" |
|
|
| def __init__(self, log_subdir: str = "logs_teleop"): |
| """ |
| Initialize the evaluation logger. |
| |
| Args: |
| log_subdir: Subdirectory name under project root for logs |
| """ |
| self.log_subdir = log_subdir |
| self._setup_logging() |
|
|
| def _setup_logging(self): |
| """Setup simple file logging with timestamp-based filename""" |
| |
| project_root = Path(os.path.dirname(decoupled_wbc.__file__)).parent |
|
|
| |
| self.logs_dir = project_root / self.log_subdir |
| self.logs_dir.mkdir(exist_ok=True) |
|
|
| |
| timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") |
| log_filename = f"eval_{timestamp}.log" |
| self.log_file_path = self.logs_dir / log_filename |
|
|
| |
| self.log_file = open(self.log_file_path, "w") |
|
|
| def write(self, message: str): |
| """Write a message to the log file.""" |
| self.log_file.write(message + "\n") |
| self.log_file.flush() |
|
|
| def log_metrics(self, metrics: Dict[str, Any]): |
| """ |
| Log evaluation metrics to file - just like the original print statements. |
| |
| Args: |
| metrics: Dictionary of metric names and values |
| """ |
| for metric_name, value in metrics.items(): |
| if isinstance(value, np.ndarray): |
| |
| if value.size == 1: |
| self.write(f"{metric_name}: {value.item()}") |
| else: |
| self.write(f"{metric_name}: {value}") |
| else: |
| self.write(f"{metric_name}: {value}") |
|
|
| def get_log_file_path(self) -> Path: |
| """Get the path to the current log file.""" |
| return self.log_file_path |
|
|
| def print(self): |
| """Print out the contents of the log file.""" |
| if self.log_file_path.exists(): |
| with open(self.log_file_path, "r") as f: |
| content = f.read() |
| print(content) |
| else: |
| print(f"Log file not found: {self.log_file_path}") |
|
|
| def close(self): |
| """Close the log file.""" |
| if hasattr(self, "log_file") and self.log_file: |
| self.log_file.close() |
|
|