Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-27 07:28:14

0001 #!/usr/bin/env python3
0002 """
0003 AID2E Command Line Interface.
0004 
0005 Provides commands for loading and running optimization configurations.
0006 """
0007 
0008 import sys
0009 from pathlib import Path
0010 from typing import Optional
0011 
0012 import click
0013 import importlib.metadata
0014 
0015 from aid2e import __MAIN_VERSION__
0016 from aid2e.utilities.configurations import FullConfig, load_config
0017 
0018 
0019 @click.group()
0020 @click.version_option(version=__MAIN_VERSION__, prog_name="aid2e")
0021 def cli():
0022     """
0023     AID2E - AI assisted Detector Design for EIC.
0024     
0025     A framework for optimization of detector designs and other complex systems.
0026     """
0027     pass
0028 
0029 
0030 def _load_plugin_commands(group: click.Group):
0031     """Discover and register plugin commands from entry points.
0032 
0033     Uses the `aid2e.commands` entry point group. Each entry point must
0034     resolve to a Click command object.
0035     """
0036     try:
0037         eps = importlib.metadata.entry_points()
0038         candidates = eps.select(group="aid2e.commands") if hasattr(eps, "select") else eps.get("aid2e.commands", [])
0039         for ep in candidates:
0040             try:
0041                 cmd = ep.load()
0042                 if isinstance(cmd, click.core.Command):
0043                     group.add_command(cmd)
0044             except Exception:
0045                 # Swallow plugin errors to keep the CLI functional
0046                 continue
0047     except Exception:
0048         # If entry point discovery fails, keep the CLI functional
0049         pass
0050 
0051 
0052 @cli.command(name="load")
0053 @click.argument("config_file", type=click.Path(exists=True))
0054 @click.option("--validate-only", is_flag=True, help="Only validate the configuration without running")
0055 @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output")
0056 def load(config_file: str, validate_only: bool, verbose: bool):
0057     """
0058     Load and validate an optimization configuration from a YAML file.
0059     
0060     CONFIG_FILE: Path to the YAML configuration file.
0061     
0062     Example:
0063         aid2e load optimization.yml
0064         aid2e load optimization.yml --validate-only
0065     """
0066     try:
0067         if verbose:
0068             click.echo(f"Loading configuration from: {config_file}")
0069 
0070         config = load_config(config_file)
0071 
0072         click.echo(click.style("✓ Configuration loaded successfully!", fg="green"))
0073         click.echo()
0074         click.echo(click.style("Configuration Summary:", bold=True))
0075         click.echo(f"  Problem: {config.problem.name}")
0076         click.echo(f"  Type: {config.problem.problem_type}")
0077         click.echo(f"  Output: {config.problem.output_location}")
0078         click.echo(f"  Work: {config.problem.work_location}")
0079         click.echo()
0080         click.echo(f"  Optimizer: {config.optimization.optimizer.name} ({config.optimization.optimizer.type})")
0081         click.echo(f"  Iterations: {config.optimization.n_iterations}")
0082         click.echo(f"  Initial Samples: {config.optimization.n_initial_samples}")
0083         click.echo(f"  Parallel Evaluations: {config.optimization.parallel_evaluations}")
0084         click.echo()
0085 
0086         param_names = config.problem.design_config.get_parameter_names()
0087         click.echo(f"  Design Parameters: {len(param_names)}")
0088         if verbose:
0089             for name in param_names:
0090                 param = config.problem.design_config.get_flat_parameters()[name]
0091                 bounds = config.problem.design_config.get_parameter_bounds(name)
0092                 click.echo(f"    - {name}: {param.value} {bounds}")
0093 
0094         if config.optimization.objectives:
0095             click.echo()
0096             click.echo(f"  Objectives ({len(config.optimization.objectives)}):")
0097             for obj in config.optimization.objectives:
0098                 click.echo(f"    - {obj}")
0099 
0100         if config.problem.design_config.parameter_constraints:
0101             click.echo()
0102             click.echo(f"  Parameter Constraints ({len(config.problem.design_config.parameter_constraints)}):")
0103             for constraint in config.problem.design_config.parameter_constraints:
0104                 click.echo(f"    - {constraint.name}: {constraint.rule}")
0105 
0106         if validate_only:
0107             click.echo()
0108             click.echo(click.style("✓ Validation complete. Configuration is valid.", fg="green"))
0109             return
0110 
0111         click.echo()
0112         click.echo(click.style("Note: Optimization execution not yet implemented.", fg="yellow"))
0113         click.echo("The configuration has been validated and is ready to use.")
0114 
0115     except FileNotFoundError as e:
0116         click.echo(click.style(f"✗ Error: {e}", fg="red"), err=True)
0117         sys.exit(1)
0118     except ValueError as e:
0119         click.echo(click.style(f"✗ Configuration Error: {e}", fg="red"), err=True)
0120         sys.exit(1)
0121     except Exception as e:
0122         click.echo(click.style(f"✗ Unexpected Error: {e}", fg="red"), err=True)
0123         if verbose:
0124             import traceback
0125             traceback.print_exc()
0126         sys.exit(1)
0127 
0128 
0129 @cli.command()
0130 @click.argument("config_file", type=click.Path(exists=True))
0131 def info(config_file: str):
0132     """
0133     Display detailed information about a configuration file.
0134     
0135     CONFIG_FILE: Path to the YAML configuration file.
0136     
0137     Example:
0138         aid2e info optimization.yml
0139     """
0140     try:
0141         config = load_config(config_file)
0142 
0143         click.echo(click.style("=" * 60, bold=True))
0144         click.echo(click.style(f"Configuration: {config.problem.name}", bold=True))
0145         click.echo(click.style("=" * 60, bold=True))
0146         click.echo()
0147 
0148         click.echo(click.style("PROBLEM CONFIGURATION", fg="cyan", bold=True))
0149         click.echo(f"  Name: {config.problem.name}")
0150         click.echo(f"  Type: {config.problem.problem_type}")
0151         click.echo(f"  Output Location: {config.problem.output_location}")
0152         click.echo(f"  Work Location: {config.problem.work_location}")
0153         click.echo()
0154 
0155         click.echo(click.style("DESIGN PARAMETERS", fg="cyan", bold=True))
0156         param_names = config.problem.design_config.get_parameter_names()
0157         flat_params = config.problem.design_config.get_flat_parameters()
0158 
0159         params_by_group = {}
0160         for name in param_names:
0161             group = name.split('.')[0]
0162             params_by_group.setdefault(group, []).append(name)
0163 
0164         for group, names in params_by_group.items():
0165             click.echo(f"\n  {group} ({len(names)} parameters):")
0166             for name in names:
0167                 param = flat_params[name]
0168                 param_short_name = name.split('.', 1)[1]
0169                 bounds = config.problem.design_config.get_parameter_bounds(name)
0170                 if bounds:
0171                     click.echo(f"    - {param_short_name}: {param.value} {bounds}")
0172                 else:
0173                     choices = config.problem.design_config.get_parameter_choices(name)
0174                     click.echo(f"    - {param_short_name}: {param.value} {choices}")
0175 
0176         if config.problem.design_config.parameter_constraints:
0177             click.echo()
0178             click.echo(click.style("PARAMETER CONSTRAINTS", fg="cyan", bold=True))
0179             for constraint in config.problem.design_config.parameter_constraints:
0180                 click.echo(f"  - {constraint.name}")
0181                 click.echo(f"    Rule: {constraint.rule}")
0182                 if constraint.description:
0183                     click.echo(f"    Description: {constraint.description}")
0184 
0185         click.echo()
0186         click.echo(click.style("OPTIMIZATION CONFIGURATION", fg="cyan", bold=True))
0187         click.echo(f"  Name: {config.optimization.name}")
0188         if config.optimization.description:
0189             click.echo(f"  Description: {config.optimization.description}")
0190         click.echo(f"  Optimizer: {config.optimization.optimizer.name} ({config.optimization.optimizer.type})")
0191         click.echo(f"  Iterations: {config.optimization.n_iterations}")
0192         click.echo(f"  Initial Samples: {config.optimization.n_initial_samples}")
0193         click.echo(f"  Parallel Evaluations: {config.optimization.parallel_evaluations}")
0194 
0195         if config.optimization.objectives:
0196             click.echo()
0197             click.echo(f"  Objectives ({len(config.optimization.objectives)}):")
0198             for obj in config.optimization.objectives:
0199                 click.echo(f"    - {obj}")
0200 
0201         if config.optimization.optimizer.parameters:
0202             click.echo()
0203             click.echo("  Optimizer Parameters:")
0204             for key, value in config.optimization.optimizer.parameters.items():
0205                 click.echo(f"    - {key}: {value}")
0206 
0207         click.echo()
0208         click.echo(click.style("=" * 60, bold=True))
0209 
0210     except Exception as e:
0211         click.echo(click.style(f"✗ Error: {e}", fg="red"), err=True)
0212         sys.exit(1)
0213 
0214 
0215 @cli.command()
0216 def version():
0217     """Display version information."""
0218     click.echo(f"AID2E Framework v{__MAIN_VERSION__}")
0219     click.echo("AI assisted Detector Design for EIC")
0220 
0221 
0222 @cli.command(name="optimize")
0223 @click.argument("config_file", type=click.Path(exists=True))
0224 @click.option("--validate-only", is_flag=True, help="Validate config but do not run")
0225 @click.option("-v", "--verbosity", count=True, help="Increase verbosity (can be used multiple times)")
0226 @click.option("--log", "log_file", type=click.Path(dir_okay=False), help="Path to log file")
0227 def optimize(config_file: str, validate_only: bool, verbosity: int, log_file: Optional[str]):
0228     """
0229     Run optimization based on configuration file.
0230     
0231     CONFIG_FILE: Path to the YAML configuration file.
0232     
0233     Example:
0234         aid2e optimize optimization.yml
0235         aid2e optimize optimization.yml --validate-only
0236         aid2e optimize optimization.yml -vv --log output.log
0237     """
0238     try:
0239         if verbosity > 0:
0240             click.echo(f"Loading configuration from: {config_file}")
0241         
0242         config = load_config(config_file)
0243         
0244         if validate_only:
0245             click.echo(click.style("✓ Configuration validated; skipping execution.", fg="green"))
0246             return
0247         
0248         # Display optimization info
0249         click.echo(click.style(f"Running optimization: {config.optimization.name}", fg="cyan", bold=True))
0250         click.echo(f"  Algorithm: {config.optimization.optimizer.name} ({config.optimization.optimizer.type})")
0251         click.echo(f"  Iterations: {config.optimization.n_iterations}")
0252         click.echo(f"  Verbosity: {verbosity}")
0253         if log_file:
0254             click.echo(f"  Log file: {log_file}")
0255         click.echo()
0256         
0257         # Placeholder for actual optimization execution
0258         click.echo(click.style("Note: Optimizer execution not yet implemented.", fg="yellow"))
0259         click.echo("The configuration has been validated and is ready for optimization.")
0260         
0261     except Exception as e:
0262         click.echo(click.style(f"✗ Error: {e}", fg="red"), err=True)
0263         if verbosity > 1:
0264             import traceback
0265             traceback.print_exc()
0266         sys.exit(1)
0267 
0268 
0269 _load_plugin_commands(cli)
0270 
0271 if __name__ == "__main__":
0272     cli()