#!/usr/bin/env python3 """ Script para arreglar el problema 'Pipe' object has no attribute 'initial_head' en TSNet Este error indica incompatibilidad entre TSNet y la versión de WNTR """ import sys import os import traceback def fix_tsnet_initial_head_problem(): """ Investiga y corrige el problema de 'initial_head' en TSNet """ print("=== Corrección del problema 'initial_head' en TSNet ===") try: import tsnet import wntr import numpy as np print(f"✓ TSNet version: {tsnet.__version__}") print(f"✓ WNTR version: {wntr.__version__}") print(f"✓ NumPy version: {np.__version__}") except ImportError as e: print(f"✗ Error al importar: {e}") return False # Archivo INP problemático inp_file_path = ( r"c:\Users\migue\AppData\Local\Temp\TSNet\network_20250911_235556.inp" ) if not os.path.exists(inp_file_path): print(f"✗ Archivo INP no encontrado: {inp_file_path}") return False print(f"✓ Archivo INP encontrado: {inp_file_path}") try: print("\n=== Investigando el problema de initial_head ===") # Cargar modelo con WNTR primero wn = wntr.network.WaterNetworkModel(inp_file_path) print("✓ WNTR cargó el modelo exitosamente") # Investigar las propiedades de los pipes en WNTR print(f"\n=== Análisis de Pipes en WNTR ===") for pipe_name in wn.pipe_name_list: pipe = wn.get_link(pipe_name) print(f"Pipe '{pipe_name}':") print(f" - Tipo: {type(pipe)}") # Listar todas las propiedades del pipe pipe_attrs = [attr for attr in dir(pipe) if not attr.startswith("_")] print(f" - Atributos disponibles: {len(pipe_attrs)}") # Buscar atributos relacionados con 'head' head_attrs = [attr for attr in pipe_attrs if "head" in attr.lower()] print(f" - Atributos con 'head': {head_attrs}") # Verificar si initial_head existe if hasattr(pipe, "initial_head"): print(f" - ✓ initial_head existe: {pipe.initial_head}") else: print(f" - ✗ initial_head NO existe") # Buscar alternativas alternatives = [] for attr in [ "head", "initial_setting", "start_node_name", "end_node_name", ]: if hasattr(pipe, attr): alternatives.append(f"{attr}: {getattr(pipe, attr)}") print(f" - Alternativas posibles: {alternatives}") break # Solo analizar el primer pipe print(f"\n=== Intentando cargar con TSNet ===") # Intentar cargar con TSNet tm = tsnet.network.TransientModel(inp_file_path) print("✓ TSNet cargó el modelo") # Verificar parámetros temporales (ya corregidos) print(f" - simulation_period: {getattr(tm, 'simulation_period', 'N/A')}") print(f" - time_step: {getattr(tm, 'time_step', 'N/A')}") # Corregir parámetros si es necesario if hasattr(tm, "simulation_period") and tm.simulation_period <= 0: tm.simulation_period = 1.0 print(" - Corregido simulation_period = 1.0") if hasattr(tm, "time_step") and tm.time_step <= 0: tm.time_step = 0.1 print(" - Corregido time_step = 0.1") print(f"\n=== Análisis de Links en TSNet ===") if hasattr(tm, "links"): print(f" - Número de links: {len(tm.links)}") for i, link in enumerate(tm.links): if hasattr(link, "__class__"): print(f" - Link {i}: {link.__class__.__name__}") # Verificar si es un Pipe y si tiene initial_head if "Pipe" in str(type(link)): print(f" * Es un Pipe") link_attrs = [ attr for attr in dir(link) if not attr.startswith("_") ] head_attrs = [ attr for attr in link_attrs if "head" in attr.lower() ] print(f" * Atributos con 'head': {head_attrs}") if hasattr(link, "initial_head"): print(f" * ✓ initial_head existe: {link.initial_head}") else: print(f" * ✗ initial_head NO existe") # Intentar crear/asignar initial_head try: # Opción 1: Asignar un valor por defecto link.initial_head = 0.0 print( f" * ✓ initial_head asignado: {link.initial_head}" ) except Exception as e: print(f" * ✗ No se pudo asignar initial_head: {e}") # Opción 2: Buscar un método alternativo if hasattr(link, "start_node") and hasattr( link, "end_node" ): try: # Calcular head inicial basado en elevación de nodos start_elev = getattr( link.start_node, "elevation", 0.0 ) end_elev = getattr( link.end_node, "elevation", 0.0 ) avg_elev = (start_elev + end_elev) / 2.0 link.initial_head = avg_elev print( f" * ✓ initial_head calculado: {link.initial_head}" ) except Exception as e2: print( f" * ✗ Cálculo alternativo falló: {e2}" ) if i >= 2: # Solo analizar los primeros 3 links break print(f"\n=== Intentando simulación TSNet corregida ===") # Intentar simulación try: results = tsnet.simulation.MOCSimulator( tm, results_obj="results", friction="steady" ) print("🎉 ¡SIMULACIÓN TSNET EXITOSA!") print("✓ El problema de 'initial_head' está resuelto") return True except Exception as sim_error: print(f"✗ Error en simulación: {sim_error}") error_str = str(sim_error).lower() if "initial_head" in error_str: print("\n💡 DIAGNÓSTICO ESPECÍFICO:") print( "1. TSNet requiere que todos los Pipe objects tengan 'initial_head'" ) print("2. La versión actual de WNTR no proporciona este atributo") print("3. Necesitamos monkey-patch o pre-procesamiento del modelo") # Intentar monkey-patch print("\n=== Intentando Monkey-Patch ===") try: # Asignar initial_head a todos los pipes for link in tm.links: if "Pipe" in str(type(link)) and not hasattr( link, "initial_head" ): link.initial_head = 0.0 # Valor por defecto print("✓ Monkey-patch aplicado") # Reintentar simulación results = tsnet.simulation.MOCSimulator( tm, results_obj="results", friction="steady" ) print("🎉 ¡SIMULACIÓN EXITOSA CON MONKEY-PATCH!") return True except Exception as patch_error: print(f"✗ Monkey-patch falló: {patch_error}") return False except Exception as e: print(f"✗ Error: {e}") traceback.print_exc() return False def main(): """Función principal""" success = fix_tsnet_initial_head_problem() if success: print("\n🎉 ¡PROBLEMA RESUELTO!") print("TSNet puede ejecutar simulaciones sin fallback") else: print("\n❌ PROBLEMA NO RESUELTO") print("Se requiere investigación adicional o actualización de dependencias") return success if __name__ == "__main__": success = main() sys.exit(0 if success else 1)