feat: Add comprehensive study management system to dashboard
Added full study configuration UI: - Create studies with isolated folder structure (sim/, results/, config.json) - File management: users drop .sim/.prt files into study's sim folder - NX expression extraction: journal script to explore .sim file - Configuration UI for design variables, objectives, and constraints - Save/load study configurations through API - Step-by-step workflow: create → add files → explore → configure → run Backend API (app.py): - POST /api/study/create - Create new study with folder structure - GET /api/study/<name>/sim/files - List files in sim folder - POST /api/study/<name>/explore - Extract expressions from .sim file - GET/POST /api/study/<name>/config - Load/save study configuration Frontend: - New study configuration view with 5-step wizard - Modal for creating new studies - Expression explorer with clickable selection - Dynamic forms for variables/objectives/constraints - Professional styling with config cards NX Integration: - extract_expressions.py journal script - Scans .sim and all loaded .prt files - Identifies potential design variable candidates - Exports expressions with values, formulas, units Each study is self-contained with its own geometry files and config.
This commit is contained in:
158
dashboard/scripts/extract_expressions.py
Normal file
158
dashboard/scripts/extract_expressions.py
Normal file
@@ -0,0 +1,158 @@
|
||||
"""
|
||||
NX Journal Script: Extract Expressions from .sim File
|
||||
|
||||
This script:
|
||||
1. Opens a .sim file
|
||||
2. Extracts all expressions from the .sim and loaded .prt files
|
||||
3. Saves expression data to JSON for the dashboard
|
||||
|
||||
Usage:
|
||||
run_journal.exe extract_expressions.py <sim_file_path> <output_json_path>
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import NXOpen
|
||||
|
||||
|
||||
def extract_all_expressions(sim_file_path, output_file_path):
|
||||
"""
|
||||
Extract all expressions from .sim file and loaded parts.
|
||||
|
||||
Args:
|
||||
sim_file_path: Path to .sim file
|
||||
output_file_path: Path to save JSON output
|
||||
"""
|
||||
try:
|
||||
# Get NX session
|
||||
session = NXOpen.Session.GetSession()
|
||||
|
||||
# Open the .sim file
|
||||
print(f"Opening .sim file: {sim_file_path}")
|
||||
part_load_status = None
|
||||
base_part, part_load_status = session.Parts.OpenBaseDisplay(sim_file_path)
|
||||
|
||||
if part_load_status:
|
||||
part_load_status.Dispose()
|
||||
|
||||
# Collect all expressions from all loaded parts
|
||||
all_expressions = {}
|
||||
|
||||
# Get work parts and components
|
||||
parts_to_scan = [base_part]
|
||||
|
||||
# Also scan all loaded components
|
||||
for component in base_part.ComponentAssembly.RootComponent.GetChildren():
|
||||
try:
|
||||
component_part = component.Prototype.OwningPart
|
||||
if component_part and component_part not in parts_to_scan:
|
||||
parts_to_scan.append(component_part)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Extract expressions from each part
|
||||
for part in parts_to_scan:
|
||||
part_name = part.Name
|
||||
print(f"Scanning expressions from: {part_name}")
|
||||
|
||||
expressions_list = []
|
||||
|
||||
# Get all expressions
|
||||
for expr in part.Expressions:
|
||||
try:
|
||||
expr_data = {
|
||||
'name': expr.Name,
|
||||
'value': expr.Value,
|
||||
'formula': expr.Equation,
|
||||
'units': expr.Units,
|
||||
'type': 'number', # Most expressions are numeric
|
||||
'source_part': part_name
|
||||
}
|
||||
|
||||
# Try to determine if it's a design variable candidate
|
||||
# (not a formula, can be changed)
|
||||
if '=' not in expr.Equation or expr.Equation.strip() == str(expr.Value):
|
||||
expr_data['is_variable_candidate'] = True
|
||||
else:
|
||||
expr_data['is_variable_candidate'] = False
|
||||
|
||||
expressions_list.append(expr_data)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not read expression {expr.Name}: {e}")
|
||||
continue
|
||||
|
||||
all_expressions[part_name] = expressions_list
|
||||
|
||||
# Collect simulation metadata
|
||||
metadata = {
|
||||
'sim_file': sim_file_path,
|
||||
'base_part': base_part.Name,
|
||||
'num_components': len(parts_to_scan),
|
||||
'total_expressions': sum(len(exprs) for exprs in all_expressions.values()),
|
||||
'variable_candidates': sum(
|
||||
1 for exprs in all_expressions.values()
|
||||
for expr in exprs
|
||||
if expr.get('is_variable_candidate', False)
|
||||
)
|
||||
}
|
||||
|
||||
# Prepare output
|
||||
output_data = {
|
||||
'metadata': metadata,
|
||||
'expressions_by_part': all_expressions
|
||||
}
|
||||
|
||||
# Save to JSON
|
||||
print(f"Saving expressions to: {output_file_path}")
|
||||
with open(output_file_path, 'w') as f:
|
||||
json.dump(output_data, f, indent=2)
|
||||
|
||||
print(f"Successfully extracted {metadata['total_expressions']} expressions")
|
||||
print(f"Found {metadata['variable_candidates']} potential design variables")
|
||||
|
||||
# Close part
|
||||
base_part.Close(NXOpen.BasePart.CloseWholeTree.True,
|
||||
NXOpen.BasePart.CloseModified.CloseModified, None)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_data = {
|
||||
'error': str(e),
|
||||
'sim_file': sim_file_path
|
||||
}
|
||||
|
||||
print(f"ERROR: {e}")
|
||||
|
||||
with open(output_file_path, 'w') as f:
|
||||
json.dump(error_data, f, indent=2)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for journal script."""
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: extract_expressions.py <sim_file_path> <output_json_path>")
|
||||
sys.exit(1)
|
||||
|
||||
sim_file_path = sys.argv[1]
|
||||
output_file_path = sys.argv[2]
|
||||
|
||||
print("="*60)
|
||||
print("NX Expression Extractor")
|
||||
print("="*60)
|
||||
|
||||
success = extract_all_expressions(sim_file_path, output_file_path)
|
||||
|
||||
if success:
|
||||
print("\nExpression extraction completed successfully!")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("\nExpression extraction failed!")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user