| |
|
| |
|
| | import streamlit as st
|
| | import re
|
| | import logging
|
| | from spacy import displacy
|
| |
|
| |
|
| | 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
|
| | }
|
| | )
|
| |
|
| | svg_html = svg_html.replace('height="375"', 'height="200"')
|
| | svg_html = re.sub(
|
| | r'<svg[^>]*>',
|
| | lambda m: m.group(0).replace('height="450"', 'height="300"'),
|
| | svg_html
|
| | )
|
| | svg_html = re.sub(
|
| | r'<g [^>]*transform="translate\((\d+),(\d+)\)"',
|
| | lambda m: f'<g transform="translate({m.group(1)},50)"',
|
| | svg_html
|
| | )
|
| |
|
| | diagram_html += f'<div class="arc-diagram-container">{svg_html}</div>'
|
| | return diagram_html
|
| |
|
| | except Exception as e:
|
| | logger.error(f"Error en display_arc_diagram: {str(e)}")
|
| | return "<p style='color:red;'>Error generando diagrama</p>"
|
| |
|
| |
|
| | 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.
|
| | """
|
| |
|
| | st.markdown("""
|
| | <style>
|
| | .stTextArea textarea {
|
| | font-size: 1rem;
|
| | line-height: 1.5;
|
| | min-height: 100px !important;
|
| | height: 100px !important;
|
| | }
|
| | .arc-diagram-container {
|
| | width: 100%;
|
| | padding: 0.5rem;
|
| | margin: 0.5rem 0;
|
| | }
|
| | .divider {
|
| | height: 3px;
|
| | border: none;
|
| | background-color: #333;
|
| | margin: 2rem 0;
|
| | }
|
| | </style>
|
| | """, unsafe_allow_html=True)
|
| |
|
| |
|
| | initialize_arc_analysis_state()
|
| | arc_state = st.session_state.arc_analysis_state
|
| |
|
| |
|
| | 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])
|
| |
|
| |
|
| | with tabs[0]:
|
| |
|
| |
|
| |
|
| | 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
|
| | )
|
| |
|
| |
|
| | 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:
|
| |
|
| | doc = nlp_models[lang_code](arc_state["base_text"])
|
| | base_arc_html = display_arc_diagram(doc)
|
| | arc_state["base_diagram"] = base_arc_html
|
| |
|
| |
|
| | 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)}")
|
| |
|
| |
|
| | if st.button(morpho_t.get('btn_new_morpho_analysis', "Nuevo an谩lisis morfosint谩tico"), key="btn_reset_base"):
|
| |
|
| |
|
| | reset_arc_analysis_state()
|
| |
|
| |
|
| | if arc_state["base_diagram"]:
|
| | st.markdown("<hr class='divider'>", 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():
|
| |
|
| | st.info(morpho_t.get('baseline_diagram_not_available', "Diagrama de arco del texto inicial no disponible."))
|
| |
|
| |
|
| | with tabs[1]:
|
| |
|
| |
|
| |
|
| | if not arc_state["base_id"]:
|
| | st.info(morpho_t.get('info_first_analyze_base',
|
| | "Verifica la existencia de un texto anterior."))
|
| | return
|
| |
|
| |
|
| | 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."))
|
| |
|
| |
|
| | st.markdown("<hr class='divider'>", unsafe_allow_html=True)
|
| |
|
| |
|
| | 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
|
| | )
|
| |
|
| |
|
| | 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:
|
| |
|
| | 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
|
| |
|
| |
|
| | 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)}")
|
| |
|
| |
|
| |
|
| | if arc_state["iteration_diagram"]:
|
| | st.markdown("<hr class='divider'>", 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)
|
| |
|