AIdeaText commited on
Commit
9fec2f4
verified
1 Parent(s): 1091cf2

Update modules/morphosyntax/morphosyntax_interface.py

Browse files
modules/morphosyntax/morphosyntax_interface.py CHANGED
@@ -15,136 +15,322 @@ from ..database.morphosyntax_iterative_mongo_db import (
15
 
16
  logger = logging.getLogger(__name__)
17
 
 
18
  def initialize_arc_analysis_state():
19
  """Inicializa el estado del an谩lisis de arcos y el cach茅 si no existen."""
20
- if "arc_analysis_state" not in st.session_state:
21
  st.session_state.arc_analysis_state = {
22
- "base_id": None,
23
- "original_text": "",
24
- "iteration_text": "",
25
- "analysis_count": 0,
 
 
26
  }
 
27
 
 
 
 
 
 
 
28
  def reset_morpho_state():
29
  """Resetea el estado del an谩lisis morfosint谩ctico en sesi贸n."""
30
- st.session_state.arc_analysis_state = {
31
- "base_id": None,
32
- "original_text": "",
33
- "iteration_text": "",
34
- "analysis_count": 0,
35
- }
36
-
37
- def display_arc_diagram(doc):
38
- """Muestra un diagrama de arco."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  try:
40
  for sent in doc.sents:
41
- rendered = displacy.render(
42
- sent,
43
  style="dep",
44
- options={"distance": 100, "arrow_spacing": 20, "word_spacing": 30}
 
 
 
 
45
  )
46
- # Ajustes del SVG
47
- rendered = rendered.replace('height="375"', 'height="200"')
48
- rendered = re.sub(
49
  r'<svg[^>]*>',
50
  lambda m: m.group(0).replace('height="450"', 'height="300"'),
51
- rendered
52
  )
53
- rendered = re.sub(
54
  r'<g [^>]*transform="translate\((\d+),(\d+)\)"',
55
  lambda m: f'<g transform="translate({m.group(1)},50)"',
56
- rendered
57
  )
58
- st.write(f'<div class="arc-diagram-container">{rendered}</div>', unsafe_allow_html=True)
 
 
 
59
 
60
  except Exception as e:
61
  logger.error(f"Error en display_arc_diagram: {str(e)}")
62
 
63
- def display_morphosyntax_interface(lang_code, nlp_models):
64
- st.title("An谩lisis Morfosint谩ctico")
65
-
66
- # 1) Inicializar estados
67
- initialize_arc_analysis_state()
68
-
69
- # 2) Tabs
70
- tabs = st.tabs(["Arco", "Categor铆as", "Morfol贸gico"])
71
-
72
- # ==================== TAB 0: An谩lisis de Arco =========================
73
- with tabs[0]:
74
- st.write("Texto base e iteraciones...")
75
-
76
- # Bot贸n Nuevo An谩lisis
77
- if st.button("Nuevo An谩lisis", key="new_analysis"):
78
- reset_morpho_state()
79
- st.experimental_rerun()
80
-
81
- # Texto base
82
- st.session_state.arc_analysis_state["original_text"] = st.text_area(
83
- "Texto Original",
84
- value=st.session_state.arc_analysis_state["original_text"],
85
- key="base_text_input"
86
- )
87
-
88
- # Bot贸n para analizar texto base
89
- if st.button("Analizar Texto Base", key="analyze_base"):
90
- # L贸gica de Spacy
91
- if not st.session_state.arc_analysis_state["original_text"].strip():
92
- st.warning("Ingrese texto original para analizar.")
93
- else:
94
- doc = nlp_models[lang_code](
95
- st.session_state.arc_analysis_state["original_text"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  )
97
- # Realizar an谩lisis (displacy, etc.)
98
- display_arc_diagram(doc)
99
-
100
- # Guardar en DB
101
- base_id = store_student_morphosyntax_base(
102
- st.session_state.username,
103
- st.session_state.arc_analysis_state["original_text"],
104
- arc_diagrams=None # Pon el dict real con arcos
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  )
106
- if base_id:
107
- st.session_state.arc_analysis_state["base_id"] = base_id
108
- st.success(f"An谩lisis base guardado. base_id={base_id}")
109
-
110
- st.markdown("---")
111
-
112
- # Texto de iteraci贸n
113
- st.session_state.arc_analysis_state["iteration_text"] = st.text_area(
114
- "Texto de Iteraci贸n",
115
- value=st.session_state.arc_analysis_state["iteration_text"],
116
- key="iteration_text_input"
117
- )
118
-
119
- # Bot贸n para analizar iteraci贸n
120
- if st.button("Analizar Cambios", key="analyze_iteration"):
121
- if not st.session_state.arc_analysis_state["iteration_text"].strip():
122
- st.warning("Ingrese texto de iteraci贸n para analizar.")
123
- elif not st.session_state.arc_analysis_state["base_id"]:
124
- st.error("No existe un base_id a煤n (analice el texto base primero).")
125
- else:
126
- # Realizar el an谩lisis con Spacy
127
- doc_iter = nlp_models[lang_code](
128
- st.session_state.arc_analysis_state["iteration_text"]
129
  )
130
- display_arc_diagram(doc_iter)
131
-
132
- # Guardar iteraci贸n en DB
133
- iteration_id = store_student_morphosyntax_iteration(
134
- st.session_state.username,
135
- st.session_state.arc_analysis_state["base_id"],
136
- st.session_state.arc_analysis_state["original_text"],
137
- st.session_state.arc_analysis_state["iteration_text"],
138
- arc_diagrams=None # Pon el dict real con arcos
139
  )
140
- if iteration_id:
141
- st.success(f"Iteraci贸n guardada. iteration_id={iteration_id}")
142
-
143
- # ==================== TAB 1: An谩lisis de Categor铆as ====================
144
- with tabs[1]:
145
- st.info("En desarrollo...")
146
-
147
- # ==================== TAB 2: An谩lisis Morfol贸gico ======================
148
- with tabs[2]:
149
- st.info("En desarrollo...")
150
-
 
15
 
16
  logger = logging.getLogger(__name__)
17
 
18
+ ###########################################################################
19
  def initialize_arc_analysis_state():
20
  """Inicializa el estado del an谩lisis de arcos y el cach茅 si no existen."""
21
+ if 'arc_analysis_state' not in st.session_state:
22
  st.session_state.arc_analysis_state = {
23
+ 'base_id': None, # ID del an谩lisis base
24
+ 'original_text': '', # Texto original
25
+ 'original_analysis': None, # Resultado an谩lisis original
26
+ 'iteration_text': '', # Texto de iteraci贸n
27
+ 'iteration_analysis': None,# Resultado an谩lisis iteraci贸n
28
+ 'analysis_count': 0
29
  }
30
+ logger.info("Estado de an谩lisis de arcos inicializado")
31
 
32
+ # Inicializar cach茅 de an谩lisis
33
+ if 'analysis_cache' not in st.session_state:
34
+ st.session_state.analysis_cache = {}
35
+ logger.info("Cach茅 de an谩lisis inicializado")
36
+
37
+ ####################################################################
38
  def reset_morpho_state():
39
  """Resetea el estado del an谩lisis morfosint谩ctico en sesi贸n."""
40
+ if 'arc_analysis_state' in st.session_state:
41
+ st.session_state.arc_analysis_state = {
42
+ 'base_id': None,
43
+ 'original_text': '',
44
+ 'original_analysis': None,
45
+ 'iteration_text': '',
46
+ 'iteration_analysis': None,
47
+ 'analysis_count': 0
48
+ }
49
+
50
+
51
+ def display_original_analysis(container, analysis, lang_code, morpho_t):
52
+ """Muestra el an谩lisis original en el contenedor especificado."""
53
+ with container:
54
+ st.subheader("An谩lisis Original")
55
+ display_morphosyntax_results(analysis, lang_code, morpho_t)
56
+
57
+
58
+ def display_iteration_analysis(container, analysis, lang_code, morpho_t):
59
+ """Muestra el an谩lisis de cambios en el contenedor especificado."""
60
+ with container:
61
+ st.subheader("An谩lisis de Cambios")
62
+ display_morphosyntax_results(analysis, lang_code, morpho_t)
63
+
64
+
65
+ def display_arc_diagram(doc, analysis):
66
+ """Muestra un diagrama de arco sin t铆tulo."""
67
  try:
68
  for sent in doc.sents:
69
+ svg_html = displacy.render(
70
+ sent,
71
  style="dep",
72
+ options={
73
+ "distance": 100,
74
+ "arrow_spacing": 20,
75
+ "word_spacing": 30
76
+ }
77
  )
78
+ # Ajustar tama帽o y posici贸n
79
+ svg_html = svg_html.replace('height="375"', 'height="200"')
80
+ svg_html = re.sub(
81
  r'<svg[^>]*>',
82
  lambda m: m.group(0).replace('height="450"', 'height="300"'),
83
+ svg_html
84
  )
85
+ svg_html = re.sub(
86
  r'<g [^>]*transform="translate\((\d+),(\d+)\)"',
87
  lambda m: f'<g transform="translate({m.group(1)},50)"',
88
+ svg_html
89
  )
90
+
91
+ # Envolver en contenedor con estilo
92
+ svg_html = f'<div class="arc-diagram-container">{svg_html}</div>'
93
+ st.write(svg_html, unsafe_allow_html=True)
94
 
95
  except Exception as e:
96
  logger.error(f"Error en display_arc_diagram: {str(e)}")
97
 
98
+
99
+ def cache_analysis_results(key, result):
100
+ """Almacena resultados de an谩lisis en cach茅."""
101
+ if not hasattr(st.session_state, 'analysis_cache'):
102
+ initialize_arc_analysis_state()
103
+ st.session_state.analysis_cache[key] = result
104
+ logger.info(f"Resultado almacenado en cach茅 con clave: {key}")
105
+
106
+
107
+ def get_cached_analysis(key):
108
+ """Recupera resultados de an谩lisis del cach茅."""
109
+ if not hasattr(st.session_state, 'analysis_cache'):
110
+ initialize_arc_analysis_state()
111
+ return None
112
+ return st.session_state.analysis_cache.get(key)
113
+
114
+
115
+ def display_morphosyntax_interface(lang_code, nlp_models, morpho_t):
116
+ """
117
+ Interfaz principal para el an谩lisis morfosint谩ctico.
118
+ Evita resets indebidos y conserva la pesta帽a activa.
119
+ """
120
+ try:
121
+ # CSS para layout estable
122
+ st.markdown("""
123
+ <style>
124
+ .stTextArea textarea {
125
+ font-size: 1rem;
126
+ line-height: 1.5;
127
+ min-height: 100px !important;
128
+ height: 100px !important;
129
+ }
130
+ .arc-diagram-container {
131
+ width: 100%;
132
+ padding: 0.5rem;
133
+ margin: 0.5rem 0;
134
+ }
135
+ .divider {
136
+ height: 3px;
137
+ border: none;
138
+ background-color: #333;
139
+ margin: 2rem 0;
140
+ }
141
+ </style>
142
+ """, unsafe_allow_html=True)
143
+
144
+ # Inicializar estados de an谩lisis si no existen
145
+ initialize_arc_analysis_state()
146
+
147
+ # ------------------------------------------------------------------
148
+ # Si tuvieras un control de tabs global, puedes comentarlo:
149
+ #
150
+ # st.session_state.tab_states['morpho_active'] = True
151
+ # st.session_state.selected_tab = 1
152
+ # ------------------------------------------------------------------
153
+
154
+ # Crear subtabs
155
+ subtabs = st.tabs([
156
+ "An谩lisis de Diagramas de Arco",
157
+ "An谩lisis de Categor铆as",
158
+ "An谩lisis Morfol贸gico"
159
+ ])
160
+
161
+ # -------------------- Subtab 0: Diagramas de Arco --------------------
162
+ with subtabs[0]:
163
+ # Bot贸n de reset
164
+ col1, col2, col3 = st.columns([2, 1, 2])
165
+ with col1:
166
+ if st.button("Nuevo An谩lisis", type="secondary", use_container_width=True):
167
+ reset_morpho_state()
168
+ # Forzar el rec谩lculo limpio
169
+ st.rerun()
170
+
171
+ # Container principal para an谩lisis base
172
+ analysis_container = st.container()
173
+ with analysis_container:
174
+ # Entrada de texto original
175
+ text_input_key = f"original_text_{st.session_state.arc_analysis_state['analysis_count']}"
176
+ text_input = st.text_area(
177
+ "Texto original",
178
+ value=st.session_state.arc_analysis_state.get('original_text', ''),
179
+ key=text_input_key,
180
+ height=100
181
  )
182
+
183
+ # Bot贸n de an谩lisis
184
+ col1, col2, col3 = st.columns([2, 1, 2])
185
+ with col1:
186
+ analyze_button = st.button(
187
+ "Analizar Texto",
188
+ type="primary",
189
+ use_container_width=True
190
+ )
191
+
192
+ # Procesar texto original
193
+ if analyze_button and text_input.strip():
194
+ try:
195
+ # Realizar an谩lisis base (SpaCy)
196
+ doc = nlp_models[lang_code](text_input)
197
+ analysis = perform_advanced_morphosyntactic_analysis(
198
+ text_input,
199
+ nlp_models[lang_code]
200
+ )
201
+
202
+ # Guardar an谩lisis base en BD y obtener ID
203
+ base_id = store_student_morphosyntax_base(
204
+ st.session_state.username,
205
+ text_input,
206
+ analysis['arc_diagrams']
207
+ )
208
+
209
+ if base_id:
210
+ # Actualizar el estado en session_state
211
+ st.session_state.arc_analysis_state.update({
212
+ 'base_id': base_id,
213
+ 'original_text': text_input,
214
+ 'original_analysis': analysis, # guardamos el dict
215
+ 'analysis_count': st.session_state.arc_analysis_state['analysis_count'] + 1
216
+ })
217
+
218
+ # Mostrar diagrama base
219
+ display_arc_diagram(doc, analysis)
220
+
221
+ # L铆nea divisora
222
+ st.markdown('<hr class="divider">', unsafe_allow_html=True)
223
+
224
+ # 脕rea de iteraci贸n: usar un formulario
225
+ with st.form("iteration_form"):
226
+ # Separamos la key para la iteraci贸n para que no se sobreescriba
227
+ iteration_text_key = f"iteration_text_{st.session_state.arc_analysis_state['analysis_count']}"
228
+
229
+ # Mostrar el texto de iteraci贸n que tengamos en session_state
230
+ iteration_text = st.text_area(
231
+ "Texto de iteraci贸n",
232
+ value=st.session_state.arc_analysis_state.get('iteration_text', text_input),
233
+ key=iteration_text_key,
234
+ height=100
235
+ )
236
+
237
+ # Bot贸n de submit en el formulario
238
+ col1, col2, col3 = st.columns([2,1,2])
239
+ with col1:
240
+ submitted = st.form_submit_button(
241
+ "Analizar Cambios",
242
+ type="primary",
243
+ use_container_width=True
244
+ )
245
+
246
+ # Procesar iteraci贸n
247
+ if submitted and iteration_text.strip():
248
+ try:
249
+ doc_iter = nlp_models[lang_code](iteration_text)
250
+ analysis_iter = perform_advanced_morphosyntactic_analysis(
251
+ iteration_text,
252
+ nlp_models[lang_code]
253
+ )
254
+
255
+ # Guardar iteraci贸n
256
+ iteration_id = store_student_morphosyntax_iteration(
257
+ st.session_state.username,
258
+ base_id,
259
+ text_input, # Texto original
260
+ iteration_text, # Texto de iteraci贸n
261
+ analysis_iter['arc_diagrams']
262
+ )
263
+
264
+ if iteration_id:
265
+ # Actualizar el estado de iteraci贸n en session_state
266
+ st.session_state.arc_analysis_state.update({
267
+ 'iteration_text': iteration_text,
268
+ 'iteration_analysis': analysis_iter
269
+ })
270
+ # Mostrar diagrama de iteraci贸n
271
+ display_arc_diagram(doc_iter, analysis_iter)
272
+
273
+ except Exception as e:
274
+ st.error("Error procesando iteraci贸n")
275
+ logger.error(f"Error en iteraci贸n: {str(e)}")
276
+
277
+ except Exception as e:
278
+ st.error("Error procesando an谩lisis base")
279
+ logger.error(f"Error base: {str(e)}")
280
+
281
+ # -------------------- Subtab 1: An谩lisis de Categor铆as ----------------
282
+ with subtabs[1]:
283
+ st.info("An谩lisis de Categor铆as en desarrollo...")
284
+
285
+ # -------------------- Subtab 2: An谩lisis Morfol贸gico ------------------
286
+ with subtabs[2]:
287
+ st.info("An谩lisis Morfol贸gico en desarrollo...")
288
+
289
+ except Exception as e:
290
+ st.error("Error en la interfaz de morfosintaxis")
291
+ logger.error(f"Error general en la interfaz: {str(e)}")
292
+
293
+
294
+ def display_morphosyntax_results(result, lang_code, morpho_t):
295
+ """
296
+ Muestra solo el diagrama de arco.
297
+ Args:
298
+ result: Diccionario con el documento procesado y su an谩lisis
299
+ lang_code: C贸digo del idioma
300
+ morpho_t: Diccionario de traducciones (opcional)
301
+ """
302
+ if result is None:
303
+ return
304
+ try:
305
+ doc = result['doc']
306
+ sentences = list(doc.sents)
307
+ for i, sent in enumerate(sentences):
308
+ try:
309
+ st.subheader(f"{morpho_t.get('sentence', 'Sentence')} {i+1}")
310
+ svg_html = displacy.render(
311
+ sent,
312
+ style="dep",
313
+ options={
314
+ "distance": 100,
315
+ "arrow_spacing": 20,
316
+ "word_spacing": 30
317
+ }
318
  )
319
+ svg_html = svg_html.replace('height="375"', 'height="200"')
320
+ svg_html = re.sub(
321
+ r'<svg[^>]*>',
322
+ lambda m: m.group(0).replace('height="450"', 'height="300"'),
323
+ svg_html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  )
325
+ svg_html = re.sub(
326
+ r'<g [^>]*transform="translate\((\d+),(\d+)\)"',
327
+ lambda m: f'<g transform="translate({m.group(1)},50)"',
328
+ svg_html
 
 
 
 
 
329
  )
330
+ svg_html = f'<div class="arc-diagram-container">{svg_html}</div>'
331
+ st.write(svg_html, unsafe_allow_html=True)
332
+ except Exception as exc:
333
+ logger.error(f"Error mostrando diagrama de la oraci贸n {i}: {str(exc)}")
334
+ continue
335
+ except Exception as e:
336
+ logger.error(f"Error en display_morphosyntax_results: {str(e)}")