Files
Atomizer/optimization_engine/utils/codebase_analyzer.py
Anto01 eabcc4c3ca refactor: Major reorganization of optimization_engine module structure
BREAKING CHANGE: Module paths have been reorganized for better maintainability.
Backwards compatibility aliases with deprecation warnings are provided.

New Structure:
- core/           - Optimization runners (runner, intelligent_optimizer, etc.)
- processors/     - Data processing
  - surrogates/   - Neural network surrogates
- nx/             - NX/Nastran integration (solver, updater, session_manager)
- study/          - Study management (creator, wizard, state, reset)
- reporting/      - Reports and analysis (visualizer, report_generator)
- config/         - Configuration management (manager, builder)
- utils/          - Utilities (logger, auto_doc, etc.)
- future/         - Research/experimental code

Migration:
- ~200 import changes across 125 files
- All __init__.py files use lazy loading to avoid circular imports
- Backwards compatibility layer supports old import paths with warnings
- All existing functionality preserved

To migrate existing code:
  OLD: from optimization_engine.nx_solver import NXSolver
  NEW: from optimization_engine.nx.solver import NXSolver

  OLD: from optimization_engine.runner import OptimizationRunner
  NEW: from optimization_engine.core.runner import OptimizationRunner

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:30:59 -05:00

416 lines
14 KiB
Python

"""
Codebase Capability Analyzer
Scans the Atomizer codebase to build a capability index showing what features
are already implemented. This enables intelligent gap detection.
Author: Atomizer Development Team
Version: 0.1.0 (Phase 2.5)
Last Updated: 2025-01-16
"""
import ast
import re
from pathlib import Path
from typing import Dict, List, Set, Any, Optional
from dataclasses import dataclass
@dataclass
class CodeCapability:
"""Represents a discovered capability in the codebase."""
name: str
category: str
file_path: Path
confidence: float
details: Dict[str, Any]
class CodebaseCapabilityAnalyzer:
"""Analyzes the Atomizer codebase to identify existing capabilities."""
def __init__(self, project_root: Optional[Path] = None):
if project_root is None:
# Auto-detect project root
current = Path(__file__).resolve()
while current.parent != current:
if (current / 'optimization_engine').exists():
project_root = current
break
current = current.parent
self.project_root = project_root
self.capabilities: Dict[str, Dict[str, Any]] = {}
def analyze_codebase(self) -> Dict[str, Any]:
"""
Analyze the entire codebase and build capability index.
Returns:
{
'optimization': {
'optuna_integration': True,
'parameter_updating': True,
'expression_parsing': True
},
'simulation': {
'nx_solver': True,
'sol101': True,
'sol103': False
},
'result_extraction': {
'displacement': True,
'stress': True,
'strain': False
},
'geometry': {
'parameter_extraction': True,
'expression_filtering': True
},
'materials': {
'xml_generation': True
}
}
"""
capabilities = {
'optimization': {},
'simulation': {},
'result_extraction': {},
'geometry': {},
'materials': {},
'loads_bc': {},
'mesh': {},
'reporting': {}
}
# Analyze optimization capabilities
capabilities['optimization'] = self._analyze_optimization()
# Analyze simulation capabilities
capabilities['simulation'] = self._analyze_simulation()
# Analyze result extraction capabilities
capabilities['result_extraction'] = self._analyze_result_extraction()
# Analyze geometry capabilities
capabilities['geometry'] = self._analyze_geometry()
# Analyze material capabilities
capabilities['materials'] = self._analyze_materials()
self.capabilities = capabilities
return capabilities
def _analyze_optimization(self) -> Dict[str, bool]:
"""Analyze optimization-related capabilities."""
capabilities = {
'optuna_integration': False,
'parameter_updating': False,
'expression_parsing': False,
'history_tracking': False
}
# Check for Optuna integration
optuna_files = list(self.project_root.glob('optimization_engine/*optuna*.py'))
if optuna_files or self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'import\s+optuna|from\s+optuna'
):
capabilities['optuna_integration'] = True
# Check for parameter updating
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'def\s+update_parameter|class\s+\w*Parameter\w*Updater'
):
capabilities['parameter_updating'] = True
# Check for expression parsing
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'def\s+parse_expression|def\s+extract.*expression'
):
capabilities['expression_parsing'] = True
# Check for history tracking
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'class\s+\w*History|def\s+track_history'
):
capabilities['history_tracking'] = True
return capabilities
def _analyze_simulation(self) -> Dict[str, bool]:
"""Analyze simulation-related capabilities."""
capabilities = {
'nx_solver': False,
'sol101': False,
'sol103': False,
'sol106': False,
'journal_execution': False
}
# Check for NX solver integration
nx_solver_file = self.project_root / 'optimization_engine' / 'nx_solver.py'
if nx_solver_file.exists():
capabilities['nx_solver'] = True
content = nx_solver_file.read_text(encoding='utf-8')
# Check for specific solution types
if 'sol101' in content.lower() or 'SOL101' in content:
capabilities['sol101'] = True
if 'sol103' in content.lower() or 'SOL103' in content:
capabilities['sol103'] = True
if 'sol106' in content.lower() or 'SOL106' in content:
capabilities['sol106'] = True
# Check for journal execution
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'def\s+run.*journal|def\s+execute.*journal'
):
capabilities['journal_execution'] = True
return capabilities
def _analyze_result_extraction(self) -> Dict[str, bool]:
"""Analyze result extraction capabilities."""
capabilities = {
'displacement': False,
'stress': False,
'strain': False,
'modal': False,
'temperature': False
}
# Check result extractors directory
extractors_dir = self.project_root / 'optimization_engine' / 'result_extractors'
if extractors_dir.exists():
# Look for OP2 extraction capabilities
for py_file in extractors_dir.glob('*.py'):
content = py_file.read_text(encoding='utf-8')
# Check for displacement extraction
if re.search(r'displacement|displacements', content, re.IGNORECASE):
capabilities['displacement'] = True
# Check for stress extraction
if re.search(r'stress|von_mises', content, re.IGNORECASE):
capabilities['stress'] = True
# Check for strain extraction
if re.search(r'strain|strains', content, re.IGNORECASE):
# Need to verify it's actual extraction, not just a comment
if re.search(r'def\s+\w*extract.*strain|strain.*=.*op2', content, re.IGNORECASE):
capabilities['strain'] = True
# Check for modal extraction
if re.search(r'modal|mode_shape|eigenvalue', content, re.IGNORECASE):
capabilities['modal'] = True
# Check for temperature extraction
if re.search(r'temperature|thermal', content, re.IGNORECASE):
capabilities['temperature'] = True
return capabilities
def _analyze_geometry(self) -> Dict[str, bool]:
"""Analyze geometry-related capabilities."""
capabilities = {
'parameter_extraction': False,
'expression_filtering': False,
'feature_creation': False
}
# Check for parameter extraction (including expression reading/finding)
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'def\s+extract.*parameter|def\s+get.*parameter|def\s+find.*expression|def\s+read.*expression|def\s+get.*expression'
):
capabilities['parameter_extraction'] = True
# Check for expression filtering (v_ prefix)
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'v_|filter.*expression|contains.*v_'
):
capabilities['expression_filtering'] = True
# Check for feature creation
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'def\s+create.*feature|def\s+add.*feature'
):
capabilities['feature_creation'] = True
return capabilities
def _analyze_materials(self) -> Dict[str, bool]:
"""Analyze material-related capabilities."""
capabilities = {
'xml_generation': False,
'material_assignment': False
}
# Check for material XML generation
material_files = list(self.project_root.glob('optimization_engine/custom_functions/*material*.py'))
if material_files:
capabilities['xml_generation'] = True
# Check for material assignment
if self._file_contains_pattern(
self.project_root / 'optimization_engine',
r'def\s+assign.*material|def\s+set.*material'
):
capabilities['material_assignment'] = True
return capabilities
def _file_contains_pattern(self, directory: Path, pattern: str) -> bool:
"""Check if any Python file in directory contains the regex pattern."""
if not directory.exists():
return False
for py_file in directory.rglob('*.py'):
try:
content = py_file.read_text(encoding='utf-8')
if re.search(pattern, content):
return True
except Exception:
continue
return False
def get_capability_details(self, category: str, capability: str) -> Optional[Dict[str, Any]]:
"""Get detailed information about a specific capability."""
if category not in self.capabilities:
return None
if capability not in self.capabilities[category]:
return None
if not self.capabilities[category][capability]:
return None
# Find the file that implements this capability
details = {
'exists': True,
'category': category,
'name': capability,
'implementation_files': []
}
# Search for implementation files based on category
search_patterns = {
'optimization': ['optuna', 'parameter', 'expression'],
'simulation': ['nx_solver', 'journal'],
'result_extraction': ['op2', 'extractor', 'result'],
'geometry': ['parameter', 'expression', 'geometry'],
'materials': ['material', 'xml']
}
if category in search_patterns:
for pattern in search_patterns[category]:
for py_file in (self.project_root / 'optimization_engine').rglob(f'*{pattern}*.py'):
if py_file.is_file():
details['implementation_files'].append(str(py_file.relative_to(self.project_root)))
return details
def find_similar_capabilities(self, missing_capability: str, category: str) -> List[str]:
"""Find existing capabilities similar to the missing one."""
if category not in self.capabilities:
return []
similar = []
# Special case: for result_extraction, all extraction types are similar
# because they use the same OP2 extraction pattern
if category == 'result_extraction':
for capability, exists in self.capabilities[category].items():
if exists and capability != missing_capability:
similar.append(capability)
return similar
# Simple similarity: check if words overlap
missing_words = set(missing_capability.lower().split('_'))
for capability, exists in self.capabilities[category].items():
if not exists:
continue
capability_words = set(capability.lower().split('_'))
# If there's word overlap, consider it similar
if missing_words & capability_words:
similar.append(capability)
return similar
def get_summary(self) -> str:
"""Get a human-readable summary of capabilities."""
if not self.capabilities:
self.analyze_codebase()
lines = ["Atomizer Codebase Capabilities Summary", "=" * 50, ""]
for category, caps in self.capabilities.items():
if not caps:
continue
existing = [name for name, exists in caps.items() if exists]
missing = [name for name, exists in caps.items() if not exists]
if existing:
lines.append(f"{category.upper()}:")
lines.append(f" Implemented ({len(existing)}):")
for cap in existing:
lines.append(f" - {cap}")
if missing:
lines.append(f" Not Found ({len(missing)}):")
for cap in missing:
lines.append(f" - {cap}")
lines.append("")
return "\n".join(lines)
def main():
"""Test the codebase analyzer."""
analyzer = CodebaseCapabilityAnalyzer()
print("Analyzing Atomizer codebase...")
print("=" * 80)
capabilities = analyzer.analyze_codebase()
print("\nCapabilities Found:")
print("-" * 80)
print(analyzer.get_summary())
print("\nDetailed Check: Result Extraction")
print("-" * 80)
for capability, exists in capabilities['result_extraction'].items():
status = "FOUND" if exists else "MISSING"
print(f" {capability:20s} : {status}")
if exists:
details = analyzer.get_capability_details('result_extraction', capability)
if details and details.get('implementation_files'):
print(f" Files: {', '.join(details['implementation_files'][:2])}")
print("\nSimilar to 'strain':")
print("-" * 80)
similar = analyzer.find_similar_capabilities('strain', 'result_extraction')
if similar:
for cap in similar:
print(f" - {cap} (could be used as pattern)")
else:
print(" No similar capabilities found")
if __name__ == '__main__':
main()