File size: 9,060 Bytes
9616a51
55c034b
831e193
 
ee7b3c9
 
831e193
344632c
97bc8ca
 
 
 
831e193
 
 
9fec2f4
915e40c
5e51711
344632c
9fec2f4
69ed6a9
 
 
 
 
9fec2f4
344632c
9fec2f4
344632c
 
5e51711
344632c
 
 
 
 
 
 
69ed6a9
9fec2f4
344632c
 
 
 
5e51711
344632c
9e07ef2
344632c
9e07ef2
9fec2f4
 
a5fb792
9fec2f4
 
 
69ed6a9
9fec2f4
a5fb792
69ed6a9
9fec2f4
 
9616a51
 
9fec2f4
9616a51
9fec2f4
a5fb792
9616a51
9fec2f4
9616a51
344632c
 
69ed6a9
9e07ef2
 
344632c
9e07ef2
344632c
96c0e0b
9fec2f4
344632c
 
ee5e77f
9fec2f4
69ed6a9
344632c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69ed6a9
344632c
69ed6a9
344632c
69ed6a9
344632c
 
69ed6a9
344632c
 
 
ee5e77f
344632c
 
ee5e77f
 
344632c
ee5e77f
 
 
 
 
 
 
 
 
 
 
344632c
ee5e77f
 
344632c
 
 
 
 
5e51711
 
344632c
69ed6a9
344632c
 
 
9fec2f4
344632c
 
 
 
 
 
 
69ed6a9
344632c
69ed6a9
344632c
69ed6a9
344632c
69ed6a9
344632c
 
 
 
 
69ed6a9
344632c
 
 
5e51711
344632c
 
 
 
5e51711
 
 
 
 
 
344632c
ee5e77f
 
 
 
 
 
 
 
 
 
 
 
 
 
344632c
 
 
 
 
69ed6a9
 
344632c
69ed6a9
 
344632c
 
 
 
 
 
 
 
69ed6a9
344632c
 
69ed6a9
344632c
69ed6a9
344632c
69ed6a9
344632c
5e51711
 
344632c
5e51711
69ed6a9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# modules/morphosyntax/morphosyntax_interface.py

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,
)

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
            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).
    Se usan formularios (st.form) para minimizar el “temblor” al pulsar botones.
    """
    # CSS para layout vertical y estable
    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)

    # 1) Inicializar estados
    initialize_arc_analysis_state()
    arc_state = st.session_state.arc_analysis_state

    # 2) Creamos pestañas: "Texto Base" y "Iteraciones"
    tabs = st.tabs(["Texto Base", "Iteraciones"])

    # =================== PESTAÑA 1: Texto Base ==========================
    with tabs[0]:
        st.subheader("Análisis de Texto Base")

        # Botón "Nuevo Análisis"
        if st.button("Nuevo Análisis", key="btn_reset_base"):
            reset_arc_analysis_state()
            # Si quieres recargar la app por completo:
            # st.experimental_rerun()

        # ------ Usamos un formulario para agrupar los widgets ------
        with st.form("base_form"):
            # Textarea de texto base
            arc_state["base_text"] = st.text_area(
                "Ingrese su texto inicial",
                value=arc_state["base_text"],
                key="base_text_input",
                height=150
            )
            # Botón de submit
            submitted_base = st.form_submit_button("Analizar Texto Base")

        # Solo procesamos si se dio submit
        if submitted_base:
            if not arc_state["base_text"].strip():
                st.warning("Ingrese un texto para analizar.")
            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

                    # 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
                        st.success(f"Análisis base guardado. ID: {base_id}")

                except Exception as exc:
                    st.error("Error procesando texto base")
                    logger.error(f"Error en análisis base: {str(exc)}")

        # Mostrar diagrama base
        if arc_state["base_diagram"]:
            st.markdown("<hr class='divider'>", unsafe_allow_html=True)
            st.markdown("#### Diagrama de Arco (Texto Base)")
            st.write(arc_state["base_diagram"], unsafe_allow_html=True)

    # ================== PESTAÑA 2: Iteraciones ==========================
    with tabs[1]:
        st.subheader("Análisis de Cambios / Iteraciones")

        # Verificar que exista un texto base
        if not arc_state["base_id"]:
            st.info("Primero analiza un texto base en la pestaña anterior.")
            return

        # --- 1) Mostrar SIEMPRE el diagrama base arriba ---
        st.markdown("#### Diagrama de Arco (Texto Base)")
        if arc_state["base_diagram"]:
            st.write(arc_state["base_diagram"], unsafe_allow_html=True)
        else:
            st.info("No hay diagrama base disponible.")

        # ------ Usamos un formulario para la iteración ------
        with st.form("iteration_form"):
            st.markdown("<hr class='divider'>", unsafe_allow_html=True)
            st.subheader("Texto de Iteración")

            arc_state["iteration_text"] = st.text_area(
                "Ingrese su nueva versión / iteración",
                value=arc_state["iteration_text"],
                height=150
            )
            submitted_iter = st.form_submit_button("Analizar Cambios")

        # Procesar cuando el form se envíe
        if submitted_iter:
            if not arc_state["iteration_text"].strip():
                st.warning("Ingrese texto de iteración.")
            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

                    # 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:
                        st.success(f"Iteración guardada. ID: {iteration_id}")

                except Exception as exc:
                    st.error("Error procesando iteración")
                    logger.error(f"Error en iteración: {str(exc)}")

        # --- 3) Mostrar diagrama de iteración debajo ---
        if arc_state["iteration_diagram"]:
            st.markdown("<hr class='divider'>", unsafe_allow_html=True)
            st.markdown("#### Diagrama de Arco (Iteración)")
            st.write(arc_state["iteration_diagram"], unsafe_allow_html=True)