import gradio as gr from gradio_client import Client, handle_file import pandas as pd import json import tempfile import os from datetime import datetime import plotly.graph_objects as go import plotly.express as px import matplotlib.pyplot as plt import numpy as np # Configuración de clientes biotech_client = Client("C2MV/BiotechU4") analysis_client = Client("C2MV/Project-HF-2025") # Tema personalizado theme = gr.themes.Soft( primary_hue="blue", secondary_hue="indigo", neutral_hue="slate", spacing_size="md", radius_size="lg", ) def process_biotech_data(file, models, component, use_de, maxfev, exp_names): """Procesa los datos en el primer endpoint de BiotechU4""" try: result = biotech_client.predict( file=handle_file(file.name), models=models, component=component, use_de=use_de, maxfev=maxfev, exp_names=exp_names, theme=False, api_name="/run_analysis_wrapper" ) return result except Exception as e: return None, None, f"Error en el análisis: {str(e)}" def create_dummy_plot(): """Crea un plot de ejemplo cuando no se pueden parsear los datos""" fig = go.Figure() # Añadir datos de ejemplo x = np.linspace(0, 10, 100) y = np.exp(-x/5) * np.cos(2*np.pi*x) fig.add_trace(go.Scatter( x=x, y=y, mode='lines', name='Datos de ejemplo', line=dict(color='blue', width=2) )) fig.update_layout( title="Visualización de Resultados", xaxis_title="Tiempo", yaxis_title="Valor", template="plotly_white", height=500 ) return fig def parse_plot_data(plot_dict): """Convierte el diccionario del plot en un objeto visualizable""" if not plot_dict: return create_dummy_plot() try: # Si es un diccionario con tipo y plot if isinstance(plot_dict, dict) and 'type' in plot_dict and 'plot' in plot_dict: plot_type = plot_dict['type'] plot_data = plot_dict['plot'] # Si es plotly if plot_type == 'plotly': if isinstance(plot_data, str): try: # Intentar parsear como JSON plot_json = json.loads(plot_data) # Crear figura de Plotly desde JSON fig = go.Figure(plot_json) return fig except: # Si falla, intentar evaluar como dict try: import ast plot_dict = ast.literal_eval(plot_data) fig = go.Figure(plot_dict) return fig except: pass elif isinstance(plot_data, dict): # Si ya es un diccionario, crear figura directamente fig = go.Figure(plot_data) return fig # Si es matplotlib, crear una figura simple elif plot_type == 'matplotlib': return create_dummy_plot() # Si es altair o bokeh, también crear dummy elif plot_type in ['altair', 'bokeh']: return create_dummy_plot() # Si el plot_dict ya es una figura válida, devolverla if hasattr(plot_dict, 'data') or hasattr(plot_dict, 'figure'): return plot_dict except Exception as e: print(f"Error parsing plot: {str(e)}") # En caso de error, devolver plot dummy return create_dummy_plot() def download_results_as_csv(df_data): """Descarga los resultados como CSV desde BiotechU4""" try: result = biotech_client.predict( df=df_data, api_name="/download_results_excel" ) return result except Exception as e: # Si falla, crear un archivo temporal con los datos if df_data and 'data' in df_data and 'headers' in df_data: try: df = pd.DataFrame(df_data['data'], columns=df_data['headers']) temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) df.to_csv(temp_file.name, index=False) temp_file.close() return temp_file.name except: pass return None def generate_claude_report(csv_file, model, detail_level, language, additional_specs): """Genera el informe usando Claude""" try: result = analysis_client.predict( files=[handle_file(csv_file)], model=model, detail=detail_level, language=language, additional_specs=additional_specs, api_name="/process_and_store" ) return result except Exception as e: return f"Error en el análisis: {str(e)}", "" def export_report(format_type, language, analysis, code): """Exporta el informe en el formato seleccionado""" try: result = analysis_client.predict( format=format_type, language=language, api_name="/handle_export" ) return result[1], result[0] except Exception as e: return None, f"Error al exportar: {str(e)}" def process_complete_pipeline( file, models, component, use_de, maxfev, exp_names, claude_model, detail_level, language, additional_specs, export_format ): """Pipeline completo de procesamiento""" progress_updates = [] if not file: empty_fig = create_dummy_plot() return empty_fig, None, None, None, None, "❌ Por favor, sube un archivo para procesar" if not models: empty_fig = create_dummy_plot() return empty_fig, None, None, None, None, "❌ Por favor, selecciona al menos un modelo" # Paso 1: Procesar con BiotechU4 progress_updates.append("🔄 Procesando datos biotecnológicos...") plot_data, df_data, status = process_biotech_data( file, models, component, use_de, maxfev, exp_names ) if plot_data is None or "Error" in str(status): empty_fig = create_dummy_plot() return empty_fig, None, None, None, None, status # Parsear el plot correctamente plot = parse_plot_data(plot_data) progress_updates.append("✅ Análisis biotecnológico completado") # Paso 2: Descargar resultados como CSV progress_updates.append("📥 Descargando resultados...") csv_file = download_results_as_csv(df_data) if not csv_file: return plot, df_data, None, None, None, "\n".join(progress_updates) + "\n❌ Error al descargar resultados" # Paso 3: Generar análisis con Claude progress_updates.append(f"🤖 Generando análisis con {claude_model}...") analysis, code = generate_claude_report( csv_file, claude_model, detail_level, language, additional_specs ) if "Error" in analysis: return plot, df_data, analysis, code, None, "\n".join(progress_updates) + f"\n❌ {analysis}" progress_updates.append("✅ Análisis con Claude completado") # Paso 4: Exportar informe progress_updates.append(f"📄 Exportando informe en formato {export_format}...") report_file, export_status = export_report(export_format, language, analysis, code) if report_file: progress_updates.append("✅ Informe exportado exitosamente") else: progress_updates.append(f"❌ {export_status}") final_status = "\n".join(progress_updates) return plot, df_data, analysis, code, report_file, final_status # CSS personalizado custom_css = """ .container { max-width: 1400px; margin: auto; } .file-upload { border: 2px dashed #3b82f6; border-radius: 12px; padding: 20px; text-align: center; transition: all 0.3s ease; } .file-upload:hover { border-color: #2563eb; background-color: #eff6ff; } button.primary { background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%); border: none; color: white; font-weight: bold; transition: all 0.3s ease; } button.primary:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(59, 130, 246, 0.3); } .tabs { border-radius: 12px; overflow: hidden; } .tab-nav { background-color: #f3f4f6; padding: 5px; } .tab-nav button { border-radius: 8px; margin: 0 2px; } .tab-nav button.selected { background-color: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .gr-dataframe { border-radius: 8px; overflow: hidden; } .gr-dataframe table { font-size: 14px; } """ # Interfaz de Gradio with gr.Blocks(theme=theme, title="BioTech Analysis & Report Generator", css=custom_css) as demo: gr.Markdown( """ # 🧬 BioTech Analysis & Report Generator ### Pipeline completo de análisis biotecnológico con IA Este sistema combina análisis avanzado de datos biotecnológicos con generación de informes mediante Claude 3.5. """ ) with gr.Row(): with gr.Column(scale=1): gr.Markdown("## 📊 Configuración del Análisis") # Inputs para BiotechU4 file_input = gr.File( label="📁 Archivo de datos (CSV/Excel)", file_types=[".csv", ".xlsx", ".xls"], elem_classes=["file-upload"] ) with gr.Group(): gr.Markdown("### 🔬 Parámetros de Análisis") models_input = gr.CheckboxGroup( choices=['logistic', 'gompertz', 'moser', 'baranyi', 'monod', 'contois', 'andrews', 'tessier', 'richards', 'stannard', 'huang'], value=['logistic', 'gompertz', 'moser', 'baranyi'], label="📊 Modelos a probar" ) component_input = gr.Dropdown( choices=['all', 'biomass', 'substrate', 'product'], value='all', label="📈 Componente a visualizar" ) exp_names_input = gr.Textbox( label="🏷️ Nombres de experimentos", placeholder="Experimento 1, Experimento 2...", value="Análisis Biotecnológico" ) with gr.Row(): use_de_input = gr.Checkbox( label="🧮 Usar Evolución Diferencial", value=False ) maxfev_input = gr.Number( label="🔄 Iteraciones máximas", value=50000, minimum=1000, maximum=100000, step=1000 ) with gr.Group(): gr.Markdown("### 🤖 Configuración de Claude") claude_model_input = gr.Dropdown( choices=[ 'claude-3-7-sonnet-20250219', 'claude-3-5-sonnet-20241022', 'claude-3-5-haiku-20241022', 'claude-sonnet-4-20250514', 'claude-opus-4-20250514' ], value='claude-3-7-sonnet-20250219', label="🤖 Modelo de Claude" ) detail_level_input = gr.Radio( choices=['detailed', 'summarized'], value='detailed', label="📋 Nivel de detalle del análisis" ) language_input = gr.Dropdown( choices=['en', 'es', 'fr', 'de', 'pt'], value='es', label="🌐 Idioma del informe" ) additional_specs_input = gr.Textbox( label="📝 Especificaciones adicionales", placeholder="Añade contexto o requisitos específicos para el análisis...", lines=3, value="Proporciona un análisis detallado de los modelos ajustados, incluyendo métricas de bondad de ajuste, comparación entre modelos y recomendaciones prácticas." ) export_format_input = gr.Radio( choices=['PDF', 'DOCX'], value='PDF', label="📄 Formato de exportación" ) process_btn = gr.Button( "🚀 Ejecutar Pipeline Completo", variant="primary", size="lg", elem_classes=["primary"] ) with gr.Column(scale=2): gr.Markdown("## 📈 Resultados") with gr.Tabs(elem_classes=["tabs"]): with gr.TabItem("📊 Visualización"): plot_output = gr.Plot(label="Gráfico interactivo") with gr.TabItem("📋 Tabla de Resultados"): table_output = gr.Dataframe( label="Resultados del ajuste", interactive=False ) with gr.TabItem("📝 Análisis de Claude"): analysis_output = gr.Markdown(label="Análisis comparativo") with gr.TabItem("💻 Código"): code_output = gr.Code( label="Código de implementación", language="python" ) with gr.Row(): status_output = gr.Textbox( label="📊 Estado del proceso", lines=6, interactive=False ) with gr.Row(): report_output = gr.File( label="📥 Descargar informe", interactive=False ) # Conectar la función principal process_btn.click( fn=process_complete_pipeline, inputs=[ file_input, models_input, component_input, use_de_input, maxfev_input, exp_names_input, claude_model_input, detail_level_input, language_input, additional_specs_input, export_format_input ], outputs=[ plot_output, table_output, analysis_output, code_output, report_output, status_output ] ) # Footer gr.Markdown( """ --- ### 📚 Instrucciones de uso: 1. **Sube tu archivo de datos** en formato CSV o Excel 2. **Selecciona los modelos** que deseas probar para el ajuste 3. **Configura los parámetros** de análisis según tus necesidades 4. **Elige el modelo de Claude** para generar el informe 5. **Especifica el idioma y formato** de exportación deseado 6. **Haz clic en "Ejecutar Pipeline Completo"** y espera los resultados El sistema procesará tus datos, realizará el ajuste de modelos, generará un análisis detallado con IA y producirá un informe profesional descargable. """ ) if __name__ == "__main__": demo.launch( share=False, show_error=True )