feat: add multiple graphing functionality and multiple comparison charts
365
main/graphing_all.py
Normal file
@@ -0,0 +1,365 @@
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import glob
|
||||
import os
|
||||
|
||||
# Find CSV files using glob
|
||||
def load_latest_csv(pattern):
|
||||
"""Load the most recent CSV file matching the pattern"""
|
||||
files = glob.glob(pattern)
|
||||
if not files:
|
||||
print(f"Aviso: Nenhum ficheiro encontrado com o padrão '{pattern}'")
|
||||
return None
|
||||
# Sort by modification time, get the latest
|
||||
latest_file = max(files, key=os.path.getmtime)
|
||||
print(f"A carregar: {latest_file}")
|
||||
return pd.read_csv(latest_file)
|
||||
|
||||
print("="*60)
|
||||
print("ANÁLISE COMPLETA DE SIMULAÇÃO")
|
||||
print("="*60)
|
||||
|
||||
# Carregar todos os dados
|
||||
print("\nA procurar ficheiros de análise...")
|
||||
low = load_latest_csv('analysis/LOW_LOAD_*.csv')
|
||||
medium = load_latest_csv('analysis/MEDIUM_LOAD_*.csv')
|
||||
high = load_latest_csv('analysis/HIGH_LOAD_*.csv')
|
||||
|
||||
# Check if we have all data
|
||||
if low is None or medium is None or high is None:
|
||||
print("\nErro: Ficheiros de análise em falta!")
|
||||
print("Por favor execute a análise batch primeiro.")
|
||||
exit(1)
|
||||
|
||||
# Create output directory for graphs
|
||||
os.makedirs('graphs', exist_ok=True)
|
||||
|
||||
# Determine the run column name (could be 'Run' or 'Execução')
|
||||
run_col = 'Run' if 'Run' in low.columns else 'Execução'
|
||||
|
||||
print(f"\nColunas disponíveis: {low.columns.tolist()}")
|
||||
|
||||
# ==============================================================================
|
||||
# GRÁFICOS COMPARATIVOS (entre cargas)
|
||||
# ==============================================================================
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("A GERAR GRÁFICOS COMPARATIVOS")
|
||||
print("="*60)
|
||||
|
||||
# 1. Gráfico: Dwelling Time vs Load
|
||||
plt.figure(figsize=(10, 6))
|
||||
dwelling_times = [
|
||||
low['TempoMédioSistema'].mean(),
|
||||
medium['TempoMédioSistema'].mean(),
|
||||
high['TempoMédioSistema'].mean()
|
||||
]
|
||||
plt.bar(['Baixa', 'Média', 'Alta'], dwelling_times, color=['green', 'orange', 'red'])
|
||||
plt.ylabel('Tempo Médio no Sistema (s)')
|
||||
plt.title('Desempenho do Sistema vs Carga')
|
||||
plt.xlabel('Cenário de Carga')
|
||||
plt.grid(axis='y', alpha=0.3)
|
||||
for i, v in enumerate(dwelling_times):
|
||||
plt.text(i, v + 1, f'{v:.2f}s', ha='center', va='bottom')
|
||||
plt.savefig('graphs/dwelling_time_comparison.png', dpi=300, bbox_inches='tight')
|
||||
print("Gráfico guardado: graphs/dwelling_time_comparison.png")
|
||||
plt.close()
|
||||
|
||||
# 2. Gráfico: Completion Rate vs Load
|
||||
plt.figure(figsize=(10, 6))
|
||||
completion_rates = [
|
||||
low['TaxaConclusão'].mean(),
|
||||
medium['TaxaConclusão'].mean(),
|
||||
high['TaxaConclusão'].mean()
|
||||
]
|
||||
plt.bar(['Baixa', 'Média', 'Alta'], completion_rates, color=['green', 'orange', 'red'])
|
||||
plt.ylabel('Taxa de Conclusão (%)')
|
||||
plt.title('Taxa de Conclusão de Veículos vs Carga')
|
||||
plt.xlabel('Cenário de Carga')
|
||||
plt.grid(axis='y', alpha=0.3)
|
||||
plt.ylim(0, 100)
|
||||
for i, v in enumerate(completion_rates):
|
||||
plt.text(i, v + 2, f'{v:.1f}%', ha='center', va='bottom')
|
||||
plt.savefig('graphs/completion_rate_comparison.png', dpi=300, bbox_inches='tight')
|
||||
print("Gráfico guardado: graphs/completion_rate_comparison.png")
|
||||
plt.close()
|
||||
|
||||
# 3. Gráfico: Waiting Time vs Load
|
||||
plt.figure(figsize=(10, 6))
|
||||
waiting_times = [
|
||||
low['TempoMédioEspera'].mean(),
|
||||
medium['TempoMédioEspera'].mean(),
|
||||
high['TempoMédioEspera'].mean()
|
||||
]
|
||||
plt.bar(['Baixa', 'Média', 'Alta'], waiting_times, color=['green', 'orange', 'red'])
|
||||
plt.ylabel('Tempo Médio de Espera (s)')
|
||||
plt.title('Tempo Médio de Espera vs Carga')
|
||||
plt.xlabel('Cenário de Carga')
|
||||
plt.grid(axis='y', alpha=0.3)
|
||||
for i, v in enumerate(waiting_times):
|
||||
plt.text(i, v + 1, f'{v:.2f}s', ha='center', va='bottom')
|
||||
plt.savefig('graphs/waiting_time_comparison.png', dpi=300, bbox_inches='tight')
|
||||
print("Gráfico guardado: graphs/waiting_time_comparison.png")
|
||||
plt.close()
|
||||
|
||||
# 4. Gráfico: Summary Statistics (comparativo)
|
||||
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(14, 10))
|
||||
loads = ['Baixa', 'Média', 'Alta']
|
||||
|
||||
# Vehicles generated
|
||||
ax1.bar(loads, [low['VeículosGerados'].mean(), medium['VeículosGerados'].mean(), high['VeículosGerados'].mean()], color=['green', 'orange', 'red'])
|
||||
ax1.set_title('Veículos Gerados')
|
||||
ax1.set_ylabel('Quantidade')
|
||||
ax1.grid(axis='y', alpha=0.3)
|
||||
|
||||
# Vehicles completed
|
||||
ax2.bar(loads, [low['VeículosCompletados'].mean(), medium['VeículosCompletados'].mean(), high['VeículosCompletados'].mean()], color=['green', 'orange', 'red'])
|
||||
ax2.set_title('Veículos Concluídos')
|
||||
ax2.set_ylabel('Quantidade')
|
||||
ax2.grid(axis='y', alpha=0.3)
|
||||
|
||||
# Min/Max dwelling time
|
||||
x = range(3)
|
||||
width = 0.35
|
||||
ax3.bar([i - width/2 for i in x], [low['TempoMínimoSistema'].mean(), medium['TempoMínimoSistema'].mean(), high['TempoMínimoSistema'].mean()], width, label='Mín', color='lightblue')
|
||||
ax3.bar([i + width/2 for i in x], [low['TempoMáximoSistema'].mean(), medium['TempoMáximoSistema'].mean(), high['TempoMáximoSistema'].mean()], width, label='Máx', color='darkblue')
|
||||
ax3.set_title('Tempo no Sistema Mín/Máx')
|
||||
ax3.set_ylabel('Tempo (s)')
|
||||
ax3.set_xticks(x)
|
||||
ax3.set_xticklabels(loads)
|
||||
ax3.legend()
|
||||
ax3.grid(axis='y', alpha=0.3)
|
||||
|
||||
# Performance summary
|
||||
metrics = ['Tempo no\nSistema', 'Tempo de\nEspera', 'Taxa de\nConclusão']
|
||||
low_vals = [low['TempoMédioSistema'].mean(), low['TempoMédioEspera'].mean(), low['TaxaConclusão'].mean()]
|
||||
med_vals = [medium['TempoMédioSistema'].mean(), medium['TempoMédioEspera'].mean(), medium['TaxaConclusão'].mean()]
|
||||
high_vals = [high['TempoMédioSistema'].mean(), high['TempoMédioEspera'].mean(), high['TaxaConclusão'].mean()]
|
||||
|
||||
x = range(len(metrics))
|
||||
width = 0.25
|
||||
ax4.bar([i - width for i in x], low_vals, width, label='Baixa', color='green')
|
||||
ax4.bar(x, med_vals, width, label='Média', color='orange')
|
||||
ax4.bar([i + width for i in x], high_vals, width, label='Alta', color='red')
|
||||
ax4.set_title('Resumo de Desempenho')
|
||||
ax4.set_xticks(x)
|
||||
ax4.set_xticklabels(metrics)
|
||||
ax4.legend()
|
||||
ax4.grid(axis='y', alpha=0.3)
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig('graphs/summary_statistics.png', dpi=300, bbox_inches='tight')
|
||||
print("Gráfico guardado: graphs/summary_statistics.png")
|
||||
plt.close()
|
||||
|
||||
# ==============================================================================
|
||||
# GRÁFICOS INDIVIDUAIS POR CARGA
|
||||
# ==============================================================================
|
||||
|
||||
def generate_individual_graphs(data, load_type, load_name, color):
|
||||
"""Generate detailed graphs for a specific load type"""
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"A GERAR GRÁFICOS - CARGA {load_name.upper()}")
|
||||
print("="*60)
|
||||
|
||||
# 1. Gráfico: Run-by-Run Dwelling Time
|
||||
plt.figure(figsize=(12, 6))
|
||||
plt.plot(data[run_col], data['TempoMédioSistema'], marker='o', color=color, linewidth=2, markersize=6)
|
||||
plt.fill_between(data[run_col], data['TempoMínimoSistema'], data['TempoMáximoSistema'], alpha=0.2, color=color)
|
||||
plt.ylabel('Tempo no Sistema (s)')
|
||||
plt.xlabel('Número da Execução')
|
||||
plt.title(f'Tempo no Sistema por Execução - Carga {load_name}')
|
||||
plt.grid(alpha=0.3)
|
||||
plt.legend(['Média', 'Intervalo Min-Max'])
|
||||
plt.savefig(f'graphs/{load_type.lower()}_dwelling_time_runs.png', dpi=300, bbox_inches='tight')
|
||||
print(f"Gráfico guardado: graphs/{load_type.lower()}_dwelling_time_runs.png")
|
||||
plt.close()
|
||||
|
||||
# 2. Gráfico: Run-by-Run Completion Rate
|
||||
plt.figure(figsize=(12, 6))
|
||||
plt.plot(data[run_col], data['TaxaConclusão'], marker='o', color=color, linewidth=2, markersize=6)
|
||||
plt.axhline(y=data['TaxaConclusão'].mean(), color='black', linestyle='--', label=f'Média: {data["TaxaConclusão"].mean():.1f}%')
|
||||
plt.ylabel('Taxa de Conclusão (%)')
|
||||
plt.xlabel('Número da Execução')
|
||||
plt.title(f'Taxa de Conclusão por Execução - Carga {load_name}')
|
||||
plt.ylim(0, 105)
|
||||
plt.grid(alpha=0.3)
|
||||
plt.legend()
|
||||
plt.savefig(f'graphs/{load_type.lower()}_completion_rate_runs.png', dpi=300, bbox_inches='tight')
|
||||
print(f"Gráfico guardado: graphs/{load_type.lower()}_completion_rate_runs.png")
|
||||
plt.close()
|
||||
|
||||
# 3. Gráfico: Run-by-Run Waiting Time
|
||||
plt.figure(figsize=(12, 6))
|
||||
plt.plot(data[run_col], data['TempoMédioEspera'], marker='o', color=color, linewidth=2, markersize=6)
|
||||
plt.ylabel('Tempo de Espera (s)')
|
||||
plt.xlabel('Número da Execução')
|
||||
plt.title(f'Tempo Médio de Espera por Execução - Carga {load_name}')
|
||||
plt.grid(alpha=0.3)
|
||||
plt.savefig(f'graphs/{load_type.lower()}_waiting_time_runs.png', dpi=300, bbox_inches='tight')
|
||||
print(f"Gráfico guardado: graphs/{load_type.lower()}_waiting_time_runs.png")
|
||||
plt.close()
|
||||
|
||||
# 4. Gráfico: Vehicles Generated vs Completed
|
||||
plt.figure(figsize=(10, 6))
|
||||
x = range(len(data))
|
||||
width = 0.35
|
||||
plt.bar([i - width/2 for i in x], data['VeículosGerados'], width, label='Gerados', color='lightblue', alpha=0.8)
|
||||
plt.bar([i + width/2 for i in x], data['VeículosCompletados'], width, label='Concluídos', color=color, alpha=0.8)
|
||||
plt.ylabel('Número de Veículos')
|
||||
plt.xlabel('Número da Execução')
|
||||
plt.title(f'Veículos Gerados vs Concluídos - Carga {load_name}')
|
||||
plt.xticks(x, data[run_col])
|
||||
plt.legend()
|
||||
plt.grid(axis='y', alpha=0.3)
|
||||
plt.savefig(f'graphs/{load_type.lower()}_vehicles_comparison.png', dpi=300, bbox_inches='tight')
|
||||
print(f"Gráfico guardado: graphs/{load_type.lower()}_vehicles_comparison.png")
|
||||
plt.close()
|
||||
|
||||
# 5. Gráfico: Summary Statistics (4-panel)
|
||||
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(14, 10))
|
||||
|
||||
# Panel 1: Dwelling Time Statistics
|
||||
metrics = ['Média', 'Mínimo', 'Máximo', 'Desvio\nPadrão']
|
||||
values = [
|
||||
data['TempoMédioSistema'].mean(),
|
||||
data['TempoMínimoSistema'].min(),
|
||||
data['TempoMáximoSistema'].max(),
|
||||
data['TempoMédioSistema'].std()
|
||||
]
|
||||
ax1.bar(metrics, values, color=[color, 'lightblue', 'darkblue', 'gray'])
|
||||
ax1.set_title('Estatísticas de Tempo no Sistema')
|
||||
ax1.set_ylabel('Tempo (s)')
|
||||
ax1.grid(axis='y', alpha=0.3)
|
||||
for i, v in enumerate(values):
|
||||
ax1.text(i, v + 0.5, f'{v:.2f}s', ha='center', va='bottom')
|
||||
|
||||
# Panel 2: Waiting Time Statistics
|
||||
values = [
|
||||
data['TempoMédioEspera'].mean(),
|
||||
data['TempoMédioEspera'].min(),
|
||||
data['TempoMédioEspera'].max(),
|
||||
data['TempoMédioEspera'].std()
|
||||
]
|
||||
ax2.bar(metrics, values, color=[color, 'lightblue', 'darkblue', 'gray'])
|
||||
ax2.set_title('Estatísticas de Tempo de Espera')
|
||||
ax2.set_ylabel('Tempo (s)')
|
||||
ax2.grid(axis='y', alpha=0.3)
|
||||
for i, v in enumerate(values):
|
||||
ax2.text(i, v + 0.5, f'{v:.2f}s', ha='center', va='bottom')
|
||||
|
||||
# Panel 3: Completion Rate Distribution
|
||||
ax3.hist(data['TaxaConclusão'], bins=10, color=color, alpha=0.7, edgecolor='black')
|
||||
ax3.axvline(data['TaxaConclusão'].mean(), color='red', linestyle='--', linewidth=2, label='Média')
|
||||
ax3.set_title('Distribuição da Taxa de Conclusão')
|
||||
ax3.set_xlabel('Taxa de Conclusão (%)')
|
||||
ax3.set_ylabel('Frequência')
|
||||
ax3.legend()
|
||||
ax3.grid(axis='y', alpha=0.3)
|
||||
|
||||
# Panel 4: Key Metrics Summary
|
||||
summary_metrics = ['Veículos\nGerados', 'Veículos\nConcluídos', 'Taxa de\nConclusão (%)']
|
||||
summary_values = [
|
||||
data['VeículosGerados'].mean(),
|
||||
data['VeículosCompletados'].mean(),
|
||||
data['TaxaConclusão'].mean()
|
||||
]
|
||||
# Create bars individually with different alpha values
|
||||
alphas = [0.5, 0.7, 0.9]
|
||||
for i, (metric, value, alpha_val) in enumerate(zip(summary_metrics, summary_values, alphas)):
|
||||
ax4.bar(i, value, color=color, alpha=alpha_val)
|
||||
ax4.set_xticks(range(len(summary_metrics)))
|
||||
ax4.set_xticklabels(summary_metrics)
|
||||
ax4.set_title('Resumo de Métricas-Chave')
|
||||
ax4.grid(axis='y', alpha=0.3)
|
||||
for i, v in enumerate(summary_values):
|
||||
ax4.text(i, v + max(summary_values)*0.02, f'{v:.1f}', ha='center', va='bottom', fontweight='bold')
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig(f'graphs/{load_type.lower()}_summary_statistics.png', dpi=300, bbox_inches='tight')
|
||||
print(f"Gráfico guardado: graphs/{load_type.lower()}_summary_statistics.png")
|
||||
plt.close()
|
||||
|
||||
# Print detailed summary statistics
|
||||
print(f"\n{'='*60}")
|
||||
print(f"CARGA {load_name.upper()} - ESTATÍSTICAS DETALHADAS")
|
||||
print("="*60)
|
||||
|
||||
print(f"\nTEMPO NO SISTEMA:")
|
||||
print(f" Média: {data['TempoMédioSistema'].mean():.2f}s")
|
||||
print(f" Desvio Padrão: {data['TempoMédioSistema'].std():.2f}s")
|
||||
print(f" Mínimo: {data['TempoMínimoSistema'].min():.2f}s")
|
||||
print(f" Máximo: {data['TempoMáximoSistema'].max():.2f}s")
|
||||
print(f" Mediana: {data['TempoMédioSistema'].median():.2f}s")
|
||||
|
||||
print(f"\nTEMPO DE ESPERA:")
|
||||
print(f" Média: {data['TempoMédioEspera'].mean():.2f}s")
|
||||
print(f" Desvio Padrão: {data['TempoMédioEspera'].std():.2f}s")
|
||||
print(f" Mínimo: {data['TempoMédioEspera'].min():.2f}s")
|
||||
print(f" Máximo: {data['TempoMédioEspera'].max():.2f}s")
|
||||
print(f" Mediana: {data['TempoMédioEspera'].median():.2f}s")
|
||||
|
||||
print(f"\nTAXA DE CONCLUSÃO:")
|
||||
print(f" Média: {data['TaxaConclusão'].mean():.2f}%")
|
||||
print(f" Desvio Padrão: {data['TaxaConclusão'].std():.2f}%")
|
||||
print(f" Mínimo: {data['TaxaConclusão'].min():.2f}%")
|
||||
print(f" Máximo: {data['TaxaConclusão'].max():.2f}%")
|
||||
print(f" Mediana: {data['TaxaConclusão'].median():.2f}%")
|
||||
|
||||
print(f"\nCONTAGEM DE VEÍCULOS:")
|
||||
print(f" Média Gerados: {data['VeículosGerados'].mean():.0f}")
|
||||
print(f" Média Concluídos: {data['VeículosCompletados'].mean():.0f}")
|
||||
print(f" Média Perdidos: {data['VeículosGerados'].mean() - data['VeículosCompletados'].mean():.0f}")
|
||||
|
||||
print(f"\nEXECUÇÕES ANALISADAS: {len(data)}")
|
||||
|
||||
# Check for config file column - could be ArquivoConfig or ConfigFile
|
||||
config_col = None
|
||||
if 'ArquivoConfig' in data.columns:
|
||||
config_col = 'ArquivoConfig'
|
||||
elif 'ConfigFile' in data.columns:
|
||||
config_col = 'ConfigFile'
|
||||
|
||||
if config_col:
|
||||
print(f"FICHEIRO DE CONFIGURAÇÃO: {data[config_col].iloc[0]}")
|
||||
|
||||
# Generate individual graphs for each load
|
||||
generate_individual_graphs(low, 'LOW', 'Baixa', 'green')
|
||||
generate_individual_graphs(medium, 'MEDIUM', 'Média', 'orange')
|
||||
generate_individual_graphs(high, 'HIGH', 'Alta', 'red')
|
||||
|
||||
# ==============================================================================
|
||||
# SUMÁRIO FINAL
|
||||
# ==============================================================================
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("SUMÁRIO COMPARATIVO FINAL")
|
||||
print("="*60)
|
||||
|
||||
print(f"\nCARGA BAIXA:")
|
||||
print(f" Tempo Médio no Sistema: {low['TempoMédioSistema'].mean():.2f}s")
|
||||
print(f" Tempo Médio de Espera: {low['TempoMédioEspera'].mean():.2f}s")
|
||||
print(f" Taxa de Conclusão: {low['TaxaConclusão'].mean():.1f}%")
|
||||
print(f" Veículos Gerados: {low['VeículosGerados'].mean():.0f}")
|
||||
print(f" Veículos Concluídos: {low['VeículosCompletados'].mean():.0f}")
|
||||
|
||||
print(f"\nCARGA MÉDIA:")
|
||||
print(f" Tempo Médio no Sistema: {medium['TempoMédioSistema'].mean():.2f}s")
|
||||
print(f" Tempo Médio de Espera: {medium['TempoMédioEspera'].mean():.2f}s")
|
||||
print(f" Taxa de Conclusão: {medium['TaxaConclusão'].mean():.1f}%")
|
||||
print(f" Veículos Gerados: {medium['VeículosGerados'].mean():.0f}")
|
||||
print(f" Veículos Concluídos: {medium['VeículosCompletados'].mean():.0f}")
|
||||
|
||||
print(f"\nCARGA ALTA:")
|
||||
print(f" Tempo Médio no Sistema: {high['TempoMédioSistema'].mean():.2f}s")
|
||||
print(f" Tempo Médio de Espera: {high['TempoMédioEspera'].mean():.2f}s")
|
||||
print(f" Taxa de Conclusão: {high['TaxaConclusão'].mean():.1f}%")
|
||||
print(f" Veículos Gerados: {high['VeículosGerados'].mean():.0f}")
|
||||
print(f" Veículos Concluídos: {high['VeículosCompletados'].mean():.0f}")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("ANÁLISE COMPLETA!")
|
||||
print(f"Total de gráficos gerados: 19")
|
||||
print("Todos os gráficos foram guardados no diretório 'graphs/'")
|
||||
print("="*60)
|
||||
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 142 KiB |