#morphosyntax_interface.py import streamlit as st import re import logging from spacy import displacy # Funciones de análisis y DB que ya tienes en tus módulos from ..morphosyntax.morphosyntax_process import perform_advanced_morphosyntactic_analysis from ..database.morphosyntax_iterative_mongo_db import ( store_student_morphosyntax_base, store_student_morphosyntax_iteration, ) from translations import get_translations logger = logging.getLogger(__name__) ########################################################################### def initialize_arc_analysis_state(): """Inicializa el estado de análisis de arcos (base e iteraciones) si no existe.""" if "arc_analysis_state" not in st.session_state: st.session_state.arc_analysis_state = { "base_id": None, "base_text": "", "base_diagram": None, "iteration_text": "", "iteration_diagram": None, } logger.info("Estado de análisis de arcos inicializado.") ########################################################################### def reset_arc_analysis_state(): """Resetea completamente el estado de análisis de arcos.""" st.session_state.arc_analysis_state = { "base_id": None, "base_text": "", "base_diagram": None, "iteration_text": "", "iteration_diagram": None, } logger.info("Estado de arcos reseteado.") ########################################################################### def display_arc_diagram(doc): """ Genera y retorna el HTML del diagrama de arco para un Doc de spaCy. No imprime directamente; retorna el HTML para usar con st.write(...). """ try: diagram_html = "" for sent in doc.sents: svg_html = displacy.render( sent, style="dep", options={ "distance": 100, "arrow_spacing": 20, "word_spacing": 30 } ) # Ajustar tamaños en el SVG resultante svg_html = svg_html.replace('height="375"', 'height="200"') svg_html = re.sub( r']*>', lambda m: m.group(0).replace('height="450"', 'height="300"'), svg_html ) svg_html = re.sub( r']*transform="translate\((\d+),(\d+)\)"', lambda m: f'{svg_html}' return diagram_html except Exception as e: logger.error(f"Error en display_arc_diagram: {str(e)}") return "

Error generando diagrama

" ########################################################################### def display_morphosyntax_interface(lang_code, nlp_models, morpho_t): """ Interfaz principal para la visualización de diagramas de arco (Texto Base vs Iteraciones), usando traducciones con morpho_t. """ # CSS para layout y estilo st.markdown(""" """, unsafe_allow_html=True) # 1) Inicializar estados initialize_arc_analysis_state() arc_state = st.session_state.arc_analysis_state # 2) Crear pestañas con etiquetas traducidas tab_text_base = morpho_t.get('tab_text_baseline', 'Ingresa la primera versión de tu texto') tab_iterations = morpho_t.get('tab_iterations', 'Produce nuevas versiones de tu primer texto') tabs = st.tabs([tab_text_base, tab_iterations]) # =================== PESTAÑA 1: Texto Base ========================== with tabs[0]: # st.subheader(morpho_t.get('analysis_base_subheader', "Análisis de Texto Base")) # Textarea de texto base arc_state["base_text"] = st.text_area( morpho_t.get('input_baseline_text', "Ingresa el primer texto para analizarlo"), value=arc_state["base_text"], key="base_text_input", height=150 ) # Botón para analizar texto base if st.button(morpho_t.get('btn_analyze_baseline', "Analizar la primera versión de tu texto"), key="btn_analyze_base"): if not arc_state["base_text"].strip(): st.warning(morpho_t.get('warn_enter_text', "Ingrese un texto nuevo para analizarlo.")) else: try: # Procesar con spaCy doc = nlp_models[lang_code](arc_state["base_text"]) base_arc_html = display_arc_diagram(doc) arc_state["base_diagram"] = base_arc_html # Guardar en Mongo analysis = perform_advanced_morphosyntactic_analysis( arc_state["base_text"], nlp_models[lang_code] ) base_id = store_student_morphosyntax_base( username=st.session_state.username, text=arc_state["base_text"], arc_diagrams=analysis["arc_diagrams"] ) if base_id: arc_state["base_id"] = base_id saved_msg = morpho_t.get('analysis_base_saved', "Análisis base guardado. ID: {base_id}") st.success(saved_msg.format(base_id=base_id)) except Exception as exc: st.error(morpho_t.get('error_processing_baseline', "Error al procesar el texto inicial")) logger.error(f"Error en análisis base: {str(exc)}") # Botón para iniciar nuevo análisis if st.button(morpho_t.get('btn_new_morpho_analysis', "Nuevo análisis morfosintático"), key="btn_reset_base"): # Si fuera necesario recargar la app por completo: # st.experimental_rerun() reset_arc_analysis_state() # Mostrar diagrama base if arc_state["base_diagram"]: st.markdown("
", unsafe_allow_html=True) st.markdown(f"#### {morpho_t.get('arc_diagram_baseline_label', 'Diagrama de arco del texto inicial')}") st.write(arc_state["base_diagram"], unsafe_allow_html=True) else: if arc_state["base_text"].strip(): # Solo mostrar si ya hay texto base pero no se ha procesado st.info(morpho_t.get('baseline_diagram_not_available', "Diagrama de arco del texto inicial no disponible.")) # ================== PESTAÑA 2: Iteraciones ========================== with tabs[1]: #st.subheader(morpho_t.get('iteration_text_subheader', "Nueva versión del texto inicial")) # Verificar que exista un texto base if not arc_state["base_id"]: st.info(morpho_t.get('info_first_analyze_base', "Verifica la existencia de un texto anterior.")) return # --- 1) Mostrar SIEMPRE el diagrama base arriba --- st.markdown(f"#### {morpho_t.get('arc_diagram_base_label', 'Diagrama de arco del texto inicial')}") if arc_state["base_diagram"]: st.write(arc_state["base_diagram"], unsafe_allow_html=True) else: st.info(morpho_t.get('baseline_diagram_not_available', "Diagrama de arco del texto inicial no disponible.")) # --- 2) Caja de texto para la iteración --- st.markdown("
", unsafe_allow_html=True) #st.subheader(morpho_t.get('iteration_text_subheader', "Ingresa una nueva versión del texto inicial y compara los arcos de ambos textos")) arc_state["iteration_text"] = st.text_area( morpho_t.get('input_iteration_text', "Ingresa una nueva versión del texto inicial y compara los arcos de ambos textos"), value=arc_state["iteration_text"], height=150 ) # Botón para analizar iteración if st.button(morpho_t.get('btn_analyze_iteration', "Analizar Cambios"), key="btn_analyze_iteration"): if not arc_state["iteration_text"].strip(): st.warning(morpho_t.get('warn_enter_iteration_text', "Ingresa una nueva versión del texto inicial y compara los arcos de ambos textos.")) else: try: # Procesar con spaCy doc_iter = nlp_models[lang_code](arc_state["iteration_text"]) arc_html_iter = display_arc_diagram(doc_iter) arc_state["iteration_diagram"] = arc_html_iter # Guardar en Mongo analysis_iter = perform_advanced_morphosyntactic_analysis( arc_state["iteration_text"], nlp_models[lang_code] ) iteration_id = store_student_morphosyntax_iteration( username=st.session_state.username, base_id=arc_state["base_id"], original_text=arc_state["base_text"], iteration_text=arc_state["iteration_text"], arc_diagrams=analysis_iter["arc_diagrams"] ) if iteration_id: saved_iter_msg = morpho_t.get('iteration_saved', "Cambios guardados correctamente. ID: {iteration_id}") st.success(saved_iter_msg.format(iteration_id=iteration_id)) except Exception as exc: st.error(morpho_t.get('error_iteration', "Error procesando los nuevos cambios")) logger.error(f"Error en iteración: {str(exc)}") # --- 3) Mostrar diagrama de iteración debajo --- if arc_state["iteration_diagram"]: st.markdown("
", unsafe_allow_html=True) st.markdown(f"#### {morpho_t.get('arc_diagram_iteration_label', 'Diagrama de Arco (Iteración)')}") st.write(arc_state["iteration_diagram"], unsafe_allow_html=True)