import pandas as pd import os import sys import re from io_paths import load_io_path_mappings from process import process_data from post_process import post_process_io_data def create_desc_ip_sheet(): # Get Excel file path from command line arguments if len(sys.argv) < 2: print("Usage: python main.py ") sys.exit(1) excel_file = sys.argv[1] if not os.path.exists(excel_file): print(f"CRITICAL: Excel file not found: {excel_file}") sys.exit(1) # Load IO path mappings print("Loading IO path mappings...") apf_df, m12dr_df, hub_df, sorter_hub_df, sio_df, ib16_df, ob16e_df, ib16s_df = load_io_path_mappings() try: # Read Excel file to check available sheets xl = pd.ExcelFile(excel_file) print(f"Available sheets: {xl.sheet_names}") # Try to find sheets with similar names desc_sheet = None network_sheet = None for sheet in xl.sheet_names: if 'DESC' in sheet.upper(): desc_sheet = sheet if 'NETWORK' in sheet.upper(): network_sheet = sheet print(f"Found DESC sheet: {desc_sheet}") print(f"Found NETWORK sheet: {network_sheet}") if not desc_sheet or not network_sheet: print("CRITICAL: Required sheets 'DESC...' and 'NETWORK...' not found in the Excel file.") sys.exit(1) # Read the sheets desc_df = pd.read_excel(xl, sheet_name=desc_sheet) network_df = pd.read_excel(xl, sheet_name=network_sheet) print(f"\nDESC columns: {list(desc_df.columns)}") print(f"NETWORK columns: {list(network_df.columns)}") # Sort network data by PartNumber, DPM, and then Name network_df['PartNumber'] = network_df['PartNumber'].fillna('') # Handle NaN in PartNumber network_df['DPM'] = network_df['DPM'].fillna('') # Handle NaN in DPM network_df = network_df.sort_values(by=['PartNumber', 'DPM', 'Name']) # Process the data based on user requirements process_data( desc_df, network_df, excel_file, apf_df, m12dr_df, hub_df, sorter_hub_df, sio_df, ib16_df, ob16e_df, ib16s_df ) # Determine subsystem (e.g. MCM04) from the Excel file path so that # we reference the exact file produced in process_data subsystem_match = re.search(r"(MCM\d+)", excel_file, re.IGNORECASE) subsystem = subsystem_match.group(1).upper() if subsystem_match else "MCM" # Now run post-processing on the freshly generated workbook new_file = f"{subsystem}_DESC_IP_MERGED.xlsx" output_file = f"{subsystem}_OUTPUT.csv" post_process_io_data(new_file, output_file) # Copy the output file to the standard name expected by streamlined generator import shutil if os.path.exists(new_file): shutil.copy2(new_file, "DESC_IP_MERGED.xlsx") print(f"Created standard output file: DESC_IP_MERGED.xlsx") # Add minimal safety sheets for Routines Generator compatibility print("Adding minimal safety sheets for Routines Generator...") with pd.ExcelWriter("DESC_IP_MERGED.xlsx", mode='a', if_sheet_exists='replace') as writer: # Create minimal empty safety sheets that LimitedDataLoader expects # Note: These are minimal empty sheets - the actual safety devices will be extracted from DESC_IP empty_rst = pd.DataFrame(columns=['TAGNAME', 'DESCA', 'IO_PATH', 'TERM']) empty_sto = pd.DataFrame(columns=['TAGNAME', 'DESCA', 'IO_PATH', 'TERM']) empty_epc = pd.DataFrame(columns=['TAGNAME', 'DESCA', 'IO_PATH', 'TERM']) # Load zones configuration from zones_config.py print("Loading zones configuration...") try: # Import zones configuration sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../') from zones_config import ZONES_CONFIGS, DEFAULT_ZONES # Determine which zones configuration to use based on subsystem if subsystem in ZONES_CONFIGS: zones_config = ZONES_CONFIGS[subsystem] print(f"Using {subsystem} zones configuration") else: zones_config = DEFAULT_ZONES print(f"Using default zones configuration (subsystem {subsystem} not found)") # Convert zones configuration to DataFrame format zone_data = [] for zone_config in zones_config: zone_data.append({ 'name': zone_config.get('name', ''), 'start': zone_config.get('start', ''), 'stop': zone_config.get('stop', ''), 'interlock': zone_config.get('interlock', '') }) zones_df = pd.DataFrame(zone_data) print(f"Loaded {len(zone_data)} zones: {[z['name'] for z in zone_data]}") except ImportError as e: print(f"Warning: Could not load zones_config.py ({e}), falling back to minimal MCM zone") # Fallback to minimal MCM zone if zones_config.py is not available zones_df = pd.DataFrame([{ 'name': 'MCM', 'start': 'MCM_S_PB', 'stop': 'MCM_EPB_STATUS', 'interlock': '' }]) empty_rst.to_excel(writer, sheet_name='RST', index=False) empty_sto.to_excel(writer, sheet_name='STO', index=False) empty_epc.to_excel(writer, sheet_name='EPC', index=False) zones_df.to_excel(writer, sheet_name='ZONES', index=False) print("Added empty RST, STO, EPC, and configured ZONES sheets") except Exception as e: print(f"Error occurred during processing: {e}") sys.exit(1) if __name__ == "__main__": create_desc_ip_sheet()