AIdeaText commited on
Commit
3ab545a
verified
1 Parent(s): e336c0d

Create morphosyntax_interface.py

Browse files
modules/morphosyntax/morphosyntax_interface.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #morphosyntax_interface.py
2
+
3
+ import streamlit as st
4
+ import re
5
+ import logging
6
+ from spacy import displacy
7
+
8
+ # Funciones de an谩lisis y DB que ya tienes en tus m贸dulos
9
+ from ..morphosyntax.morphosyntax_process import perform_advanced_morphosyntactic_analysis
10
+ from ..database.morphosyntax_iterative_mongo_db import (
11
+ store_student_morphosyntax_base,
12
+ store_student_morphosyntax_iteration,
13
+ )
14
+
15
+ from translations import get_translations
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ ###########################################################################
20
+ def initialize_arc_analysis_state():
21
+ """Inicializa el estado de an谩lisis de arcos (base e iteraciones) si no existe."""
22
+ if "arc_analysis_state" not in st.session_state:
23
+ st.session_state.arc_analysis_state = {
24
+ "base_id": None,
25
+ "base_text": "",
26
+ "base_diagram": None,
27
+ "iteration_text": "",
28
+ "iteration_diagram": None,
29
+ }
30
+ logger.info("Estado de an谩lisis de arcos inicializado.")
31
+
32
+ ###########################################################################
33
+ def reset_arc_analysis_state():
34
+ """Resetea completamente el estado de an谩lisis de arcos."""
35
+ st.session_state.arc_analysis_state = {
36
+ "base_id": None,
37
+ "base_text": "",
38
+ "base_diagram": None,
39
+ "iteration_text": "",
40
+ "iteration_diagram": None,
41
+ }
42
+ logger.info("Estado de arcos reseteado.")
43
+
44
+ ###########################################################################
45
+ def display_arc_diagram(doc):
46
+ """
47
+ Genera y retorna el HTML del diagrama de arco para un Doc de spaCy.
48
+ No imprime directamente; retorna el HTML para usar con st.write(...).
49
+ """
50
+ try:
51
+ diagram_html = ""
52
+ for sent in doc.sents:
53
+ svg_html = displacy.render(
54
+ sent,
55
+ style="dep",
56
+ options={
57
+ "distance": 100,
58
+ "arrow_spacing": 20,
59
+ "word_spacing": 30
60
+ }
61
+ )
62
+ # Ajustar tama帽os en el SVG resultante
63
+ svg_html = svg_html.replace('height="375"', 'height="200"')
64
+ svg_html = re.sub(
65
+ r'<svg[^>]*>',
66
+ lambda m: m.group(0).replace('height="450"', 'height="300"'),
67
+ svg_html
68
+ )
69
+ svg_html = re.sub(
70
+ r'<g [^>]*transform="translate\((\d+),(\d+)\)"',
71
+ lambda m: f'<g transform="translate({m.group(1)},50)"',
72
+ svg_html
73
+ )
74
+ # Envolver en contenedor
75
+ diagram_html += f'<div class="arc-diagram-container">{svg_html}</div>'
76
+ return diagram_html
77
+
78
+ except Exception as e:
79
+ logger.error(f"Error en display_arc_diagram: {str(e)}")
80
+ return "<p style='color:red;'>Error generando diagrama</p>"
81
+
82
+ ###########################################################################
83
+ def display_morphosyntax_interface(lang_code, nlp_models, morpho_t):
84
+ """
85
+ Interfaz principal para la visualizaci贸n de diagramas de arco
86
+ (Texto Base vs Iteraciones), usando traducciones con morpho_t.
87
+ """
88
+ # CSS para layout y estilo
89
+ st.markdown("""
90
+ <style>
91
+ .stTextArea textarea {
92
+ font-size: 1rem;
93
+ line-height: 1.5;
94
+ min-height: 100px !important;
95
+ height: 100px !important;
96
+ }
97
+ .arc-diagram-container {
98
+ width: 100%;
99
+ padding: 0.5rem;
100
+ margin: 0.5rem 0;
101
+ }
102
+ .divider {
103
+ height: 3px;
104
+ border: none;
105
+ background-color: #333;
106
+ margin: 2rem 0;
107
+ }
108
+ </style>
109
+ """, unsafe_allow_html=True)
110
+
111
+ # 1) Inicializar estados
112
+ initialize_arc_analysis_state()
113
+ arc_state = st.session_state.arc_analysis_state
114
+
115
+ # 2) Crear pesta帽as con etiquetas traducidas
116
+ tab_text_base = morpho_t.get('tab_text_base', 'Texto Base')
117
+ tab_iterations = morpho_t.get('tab_iterations', 'Iteraciones')
118
+ tabs = st.tabs([tab_text_base, tab_iterations])
119
+
120
+ # =================== PESTA脩A 1: Texto Base ==========================
121
+ with tabs[0]:
122
+ st.subheader(morpho_t.get('analysis_base_subheader', "An谩lisis de Texto Base"))
123
+
124
+ # Bot贸n para iniciar nuevo an谩lisis
125
+ if st.button(morpho_t.get('btn_new_analysis', "Nuevo An谩lisis"), key="btn_reset_base"):
126
+ # Si fuera necesario recargar la app por completo:
127
+ # st.experimental_rerun()
128
+ reset_arc_analysis_state()
129
+
130
+ # Textarea de texto base
131
+ arc_state["base_text"] = st.text_area(
132
+ morpho_t.get('input_base_text', "Ingrese su texto inicial"),
133
+ value=arc_state["base_text"],
134
+ key="base_text_input",
135
+ height=150
136
+ )
137
+
138
+ # Bot贸n para analizar texto base
139
+ if st.button(morpho_t.get('btn_analyze_base', "Analizar Texto Base"), key="btn_analyze_base"):
140
+ if not arc_state["base_text"].strip():
141
+ st.warning(morpho_t.get('warn_enter_text', "Ingrese un texto para analizar."))
142
+ else:
143
+ try:
144
+ # Procesar con spaCy
145
+ doc = nlp_models[lang_code](arc_state["base_text"])
146
+ base_arc_html = display_arc_diagram(doc)
147
+ arc_state["base_diagram"] = base_arc_html
148
+
149
+ # Guardar en Mongo
150
+ analysis = perform_advanced_morphosyntactic_analysis(
151
+ arc_state["base_text"],
152
+ nlp_models[lang_code]
153
+ )
154
+ base_id = store_student_morphosyntax_base(
155
+ username=st.session_state.username,
156
+ text=arc_state["base_text"],
157
+ arc_diagrams=analysis["arc_diagrams"]
158
+ )
159
+ if base_id:
160
+ arc_state["base_id"] = base_id
161
+ saved_msg = morpho_t.get('analysis_base_saved', "An谩lisis base guardado. ID: {base_id}")
162
+ st.success(saved_msg.format(base_id=base_id))
163
+
164
+ except Exception as exc:
165
+ st.error(morpho_t.get('error_processing_base', "Error procesando texto base"))
166
+ logger.error(f"Error en an谩lisis base: {str(exc)}")
167
+
168
+ # Mostrar diagrama base
169
+ if arc_state["base_diagram"]:
170
+ st.markdown("<hr class='divider'>", unsafe_allow_html=True)
171
+ st.markdown(f"#### {morpho_t.get('arc_diagram_base_label', 'Diagrama de Arco (Texto Base)')}")
172
+ st.write(arc_state["base_diagram"], unsafe_allow_html=True)
173
+ else:
174
+ if arc_state["base_text"].strip():
175
+ # Solo mostrar si ya hay texto base pero no se ha procesado
176
+ st.info(morpho_t.get('base_diagram_not_available', "No hay diagrama base disponible."))
177
+
178
+ # ================== PESTA脩A 2: Iteraciones ==========================
179
+ with tabs[1]:
180
+ st.subheader(morpho_t.get('analysis_iterations_subheader', "An谩lisis de Cambios / Iteraciones"))
181
+
182
+ # Verificar que exista un texto base
183
+ if not arc_state["base_id"]:
184
+ st.info(morpho_t.get('info_first_analyze_base',
185
+ "Primero analiza un texto base en la pesta帽a anterior."))
186
+ return
187
+
188
+ # --- 1) Mostrar SIEMPRE el diagrama base arriba ---
189
+ st.markdown(f"#### {morpho_t.get('arc_diagram_base_label', 'Diagrama de Arco (Texto Base)')}")
190
+ if arc_state["base_diagram"]:
191
+ st.write(arc_state["base_diagram"], unsafe_allow_html=True)
192
+ else:
193
+ st.info(morpho_t.get('base_diagram_not_available', "No hay diagrama base disponible."))
194
+
195
+ # --- 2) Caja de texto para la iteraci贸n ---
196
+ st.markdown("<hr class='divider'>", unsafe_allow_html=True)
197
+ st.subheader(morpho_t.get('iteration_text_subheader', "Texto de Iteraci贸n"))
198
+
199
+ arc_state["iteration_text"] = st.text_area(
200
+ morpho_t.get('input_iteration_text', "Ingrese su nueva versi贸n / iteraci贸n"),
201
+ value=arc_state["iteration_text"],
202
+ height=150
203
+ )
204
+
205
+ # Bot贸n para analizar iteraci贸n
206
+ if st.button(morpho_t.get('btn_analyze_iteration', "Analizar Cambios"), key="btn_analyze_iteration"):
207
+ if not arc_state["iteration_text"].strip():
208
+ st.warning(morpho_t.get('warn_enter_iteration_text', "Ingrese texto de iteraci贸n."))
209
+ else:
210
+ try:
211
+ # Procesar con spaCy
212
+ doc_iter = nlp_models[lang_code](arc_state["iteration_text"])
213
+ arc_html_iter = display_arc_diagram(doc_iter)
214
+ arc_state["iteration_diagram"] = arc_html_iter
215
+
216
+ # Guardar en Mongo
217
+ analysis_iter = perform_advanced_morphosyntactic_analysis(
218
+ arc_state["iteration_text"],
219
+ nlp_models[lang_code]
220
+ )
221
+ iteration_id = store_student_morphosyntax_iteration(
222
+ username=st.session_state.username,
223
+ base_id=arc_state["base_id"],
224
+ original_text=arc_state["base_text"],
225
+ iteration_text=arc_state["iteration_text"],
226
+ arc_diagrams=analysis_iter["arc_diagrams"]
227
+ )
228
+ if iteration_id:
229
+ saved_iter_msg = morpho_t.get('iteration_saved', "Iteraci贸n guardada. ID: {iteration_id}")
230
+ st.success(saved_iter_msg.format(iteration_id=iteration_id))
231
+
232
+ except Exception as exc:
233
+ st.error(morpho_t.get('error_iteration', "Error procesando iteraci贸n"))
234
+ logger.error(f"Error en iteraci贸n: {str(exc)}")
235
+
236
+ # --- 3) Mostrar diagrama de iteraci贸n debajo ---
237
+ if arc_state["iteration_diagram"]:
238
+ st.markdown("<hr class='divider'>", unsafe_allow_html=True)
239
+ st.markdown(f"#### {morpho_t.get('arc_diagram_iteration_label', 'Diagrama de Arco (Iteraci贸n)')}")
240
+ st.write(arc_state["iteration_diagram"], unsafe_allow_html=True)