Spaces:
Sleeping
Sleeping
| 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 | |
| ) |