Skip to content

Commit

Permalink
Fix CI
Browse files Browse the repository at this point in the history
  • Loading branch information
chraibi committed Oct 29, 2024
1 parent 9840f3e commit f901425
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 46 deletions.
69 changes: 38 additions & 31 deletions generage_variations.py
Original file line number Diff line number Diff line change
@@ -1,65 +1,72 @@
"""Generate variation files necessary to start simulations."""

import json
import logging
import pathlib
from typing import Any, Dict, List, Union
import typer
from datetime import datetime

def get_nested_value(config: Dict, param_path: str) -> Any:

def get_nested_value(config: Dict[str, Any], param_path: str) -> Any:
"""Get value from nested dictionary using dot notation."""
keys = param_path.split('/')
keys = param_path.split("/")
current = config
for key in keys:
current = current[key]
return current

def set_nested_value(config: Dict, param_path: str, value: Any) -> None:

def set_nested_value(config: Dict[str, Any], param_path: str, value: Any) -> None:
"""Set value in nested dictionary using dot notation."""
keys = param_path.split('/')
keys = param_path.split("/")
current = config
for key in keys[:-1]:
current = current[key]
current[keys[-1]] = value


def create_parameter_variations(
base_config: Dict,
base_config: Dict[str, Any],
param_path: str,
values: List[Union[float, int, str]],
description: str = ""
) -> List[Dict]:
values: List[Union[float, int]],
description: str = "",
) -> List[Dict[str, Any]]:
"""
Create variations of the configuration by varying a single parameter.
Args:
base_config: The base configuration dictionary
param_path: Path to the parameter using '/' notation (e.g., 'motivation_parameters/height')
values: List of values to try for this parameter
description: Optional description of what these variations represent
Returns:
List of variation dictionaries
"""
original_value = get_nested_value(base_config, param_path)
variations = []

for value in values:
variation = {
"name": f"{param_path.replace('/', '_')}_{value}",
"description": description,
"original_value": original_value,
"parameters": {
param_path: value
}
"parameters": {param_path: value},
}
variations.append(variation)

return variations

def save_variations(variations: List[Dict], output_path: pathlib.Path) -> None:

def save_variations(
variations: List[Dict[str, Any]], output_path: pathlib.Path
) -> None:
"""Save variations to a JSON file with proper formatting."""
with open(output_path, "w", encoding="utf8") as f:
json.dump(variations, f, indent=4)


def main(
inifile: pathlib.Path = typer.Option(
pathlib.Path("files/inifile.json"),
Expand All @@ -85,22 +92,24 @@ def main(
"""Generate parameter variations for simulation runs."""
if not param or not values:
print("Usage example:")
print(" python generate_variations.py --inifile files/inifile.json \\\n"
" --param motivation_parameters/height \\\n"
" --values 0.5,1.0,1.5 \\\n"
" --description 'Testing different heights'")
print(
" python generate_variations.py --inifile files/inifile.json \\\n"
" --param motivation_parameters/height \\\n"
" --values 0.5,1.0,1.5 \\\n"
" --description 'Testing different heights'"
)
return

# Load base configuration
with open(inifile, "r", encoding="utf8") as f:
base_config = json.load(f)

# Parse values (handle both float and int)
try:
parsed_values = []
for v in values.split(','):
parsed_values: List[float | int] = []
for v in values.split(","):
v = v.strip()
if '.' in v:
if "." in v:
parsed_values.append(float(v))
else:
parsed_values.append(int(v))
Expand All @@ -110,24 +119,22 @@ def main(

# Generate variations
variations = create_parameter_variations(
base_config,
param,
parsed_values,
description
base_config, param, parsed_values, description
)

# Determine output path
if output is None:
param_name = param.replace('/', '_')
param_name = param.replace("/", "_")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output = pathlib.Path(f"variations_{param_name}_{timestamp}.json")

# Save variations
save_variations(variations, output)
print(f"Created {len(variations)} variations in {output}")
print("\nVariations summary:")
for var in variations:
print(f"- {var['name']}: {var['parameters'][param]}")


if __name__ == "__main__":
typer.run(main)
29 changes: 14 additions & 15 deletions simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def init_simulation(
output_file=pathlib.Path(_trajectory_path), every_nth_frame=_fps
),
)
logging.info("Init simulation done")
logging.info("Init simulation done.")
return simulation


Expand Down Expand Up @@ -512,7 +512,7 @@ def start_simulation(config_path: str, output_path: str) -> float:
return evac_time


def load_variations(variations_path: pathlib.Path) -> List[Dict]:
def load_variations(variations_path: pathlib.Path) -> List[Dict[str, Any]]:
"""Load parameter variations from a JSON file."""
if not variations_path.exists():
raise FileNotFoundError(f"Variations file not found: {variations_path}")
Expand All @@ -529,7 +529,7 @@ def load_variations(variations_path: pathlib.Path) -> List[Dict]:


def modify_and_save_config(
base_config: Dict, variation: Dict[str, any], output_path: pathlib.Path
base_config: Dict[str, Any], variation: Dict[str, Any], output_path: pathlib.Path
) -> None:
"""
Modify base configuration with variation parameters and save to new file.
Expand Down Expand Up @@ -573,27 +573,27 @@ def main(
init_logger()

# Load base configuration
logging.info(f"Loading base configuration from {inifile}")
logging.info(f"Loading base configuration from {inifile}.")
try:
with open(inifile, "r", encoding="utf8") as f:
base_config = json.load(f)
except FileNotFoundError:
logging.error(f"Base configuration file not found: {inifile}")
logging.error(f"Base configuration file not found: {inifile}.")
raise typer.Exit(code=1)

# Load variations
logging.info(f"Loading variations from {variations_file}")
logging.info(f"Loading variations from {variations_file}.")
try:
variations = load_variations(variations_file)
except (FileNotFoundError, json.JSONDecodeError, ValueError) as e:
logging.error(f"Error loading variations: {e}")
raise typer.Exit(code=1)
logging.error(f"Error loading variations: {e}.")
raise typer.Exit(code=2)

# Create output directory
output_dir.mkdir(parents=True, exist_ok=True)

# Save a copy of the variations used for this run
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
run_info = {
"timestamp": timestamp,
"base_config": str(inifile),
Expand Down Expand Up @@ -631,10 +631,10 @@ def main(

# Run simulation
try:
evac_time = start_simulation(new_config_path, output_path)
evac_time = start_simulation(str(new_config_path), str(output_path))
status = "completed"
except Exception as e:
logging.error(f"Error in simulation: {e}")
logging.error(f"Error in simulation: {e}.")
evac_time = None
status = "failed"

Expand All @@ -650,18 +650,17 @@ def main(
}
results.append(result)

logging.info(f"Status: {status}")
logging.info(f"Status: {status}.")
if evac_time is not None:
logging.info(f"Evacuation time: {evac_time:.2f} [s]")
logging.info(f"Evacuation time: {evac_time:.2f} [s].")

# Save all results
results_file = output_dir / f"results_{timestamp}.json"
with open(results_file, "w") as f:
json.dump(results, f, indent=4)

logging.info(f"\nSimulation batch completed. Results saved to {results_file}")
logging.info(f"\nSimulation batch completed. Results saved to {results_file}.")

# Print summary
completed = sum(1 for r in results if r["status"] == "completed")
failed = sum(1 for r in results if r["status"] == "failed")
logging.info("\nSummary:")
Expand Down

0 comments on commit f901425

Please sign in to comment.