#v3/modules/studentact/current_situation_analysis.py import streamlit as st import matplotlib.pyplot as plt import networkx as nx import seaborn as sns import logging logger = logging.getLogger(__name__) def display_current_situation_visual(doc, metrics): """ Crea y muestra las visualizaciones del análisis de situación actual. Aprovecha los componentes visuales existentes del sistema. """ try: # Contenedor principal para visualizaciones with st.container(): # 1. Red de Vocabulario st.subheader("Riqueza de Vocabulario") vocabulary_graph = create_vocabulary_network(doc) st.pyplot(vocabulary_graph) # 2. Complejidad Sintáctica st.subheader("Estructura de Oraciones") syntax_graph = create_syntax_complexity_graph(doc) st.pyplot(syntax_graph) # 3. Cohesión Textual st.subheader("Cohesión del Texto") cohesion_map = create_cohesion_heatmap(doc) st.pyplot(cohesion_map) except Exception as e: logger.error(f"Error mostrando visualizaciones: {str(e)}") st.error("Error al generar visualizaciones") def analyze_text_dimensions(doc): """ Analiza las diferentes dimensiones del texto. Args: doc: Documento procesado por spaCy Returns: dict: Métricas del análisis """ try: # Analizar claridad (basado en longitud de oraciones) clarity_score = analyze_clarity(doc) # Analizar vocabulario (diversidad léxica) vocabulary_score = analyze_vocabulary_diversity(doc) # Analizar cohesión (conexiones entre oraciones) cohesion_score = analyze_cohesion(doc) # Analizar estructura (complejidad sintáctica) structure_score = analyze_structure(doc) # Generar gráficos sentence_graphs = generate_sentence_graphs(doc) word_connections = generate_word_connections(doc) connection_paths = generate_connection_paths(doc) return { 'clarity': clarity_score, 'vocabulary': vocabulary_score, 'cohesion': cohesion_score, 'structure': structure_score, 'sentence_graphs': sentence_graphs, 'word_connections': word_connections, 'connection_paths': connection_paths } except Exception as e: logger.error(f"Error en analyze_text_dimensions: {str(e)}") raise def analyze_clarity(doc): """Analiza la claridad basada en longitud de oraciones""" sentences = list(doc.sents) avg_length = sum(len(sent) for sent in sentences) / len(sentences) return normalize_score(avg_length, optimal_length=20) def analyze_vocabulary_diversity(doc): """Analiza la diversidad del vocabulario""" unique_lemmas = {token.lemma_ for token in doc if token.is_alpha} total_words = len([token for token in doc if token.is_alpha]) return len(unique_lemmas) / total_words if total_words > 0 else 0 def analyze_cohesion(doc): """Analiza la cohesión textual""" sentences = list(doc.sents) connections = 0 for i in range(len(sentences)-1): sent1_words = {token.lemma_ for token in sentences[i]} sent2_words = {token.lemma_ for token in sentences[i+1]} connections += len(sent1_words.intersection(sent2_words)) return normalize_score(connections, optimal_connections=5) def analyze_structure(doc): """Analiza la complejidad estructural""" root_distances = [] for token in doc: if token.dep_ == 'ROOT': depths = get_dependency_depths(token) root_distances.extend(depths) avg_depth = sum(root_distances) / len(root_distances) if root_distances else 0 return normalize_score(avg_depth, optimal_depth=3) def get_dependency_depths(token, depth=0): """Obtiene las profundidades de dependencia""" depths = [depth] for child in token.children: depths.extend(get_dependency_depths(child, depth + 1)) return depths def normalize_score(value, optimal_value=1.0, range_factor=2.0): """Normaliza un valor a un score entre 0 y 1""" return 1 / (1 + abs(value - optimal_value) / range_factor) # Implementación de las funciones de visualización def generate_sentence_graphs(doc): """Genera visualizaciones de estructura de oraciones""" fig, ax = plt.subplots(figsize=(10, 6)) # Implementar visualización plt.close() return fig def generate_word_connections(doc): """Genera red de conexiones de palabras""" fig, ax = plt.subplots(figsize=(10, 6)) # Implementar visualización plt.close() return fig def generate_connection_paths(doc): """Genera patrones de conexión""" fig, ax = plt.subplots(figsize=(10, 6)) # Implementar visualización plt.close() return fig def create_vocabulary_network(doc): """ Genera el grafo de red de vocabulario. """ G = nx.Graph() # Crear nodos para palabras significativas words = [token.text.lower() for token in doc if token.is_alpha and not token.is_stop] word_freq = Counter(words) # Añadir nodos con tamaño basado en frecuencia for word, freq in word_freq.items(): G.add_node(word, size=freq) # Crear conexiones basadas en co-ocurrencia window_size = 5 for i in range(len(words) - window_size): window = words[i:i+window_size] for w1, w2 in combinations(set(window), 2): if G.has_edge(w1, w2): G[w1][w2]['weight'] += 1 else: G.add_edge(w1, w2, weight=1) # Crear visualización fig, ax = plt.subplots(figsize=(12, 8)) pos = nx.spring_layout(G) # Dibujar nodos nx.draw_networkx_nodes(G, pos, node_size=[G.nodes[node]['size']*100 for node in G.nodes], node_color='lightblue', alpha=0.7) # Dibujar conexiones nx.draw_networkx_edges(G, pos, width=[G[u][v]['weight']*0.5 for u,v in G.edges], alpha=0.5) # Añadir etiquetas nx.draw_networkx_labels(G, pos) plt.title("Red de Vocabulario") plt.axis('off') return fig def create_syntax_complexity_graph(doc): """ Genera el diagrama de arco de complejidad sintáctica. Muestra la estructura de dependencias con colores basados en la complejidad. """ try: # Preparar datos para la visualización sentences = list(doc.sents) if not sentences: return None # Crear figura para el gráfico fig, ax = plt.subplots(figsize=(12, len(sentences) * 2)) # Colores para diferentes niveles de profundidad depth_colors = plt.cm.viridis(np.linspace(0, 1, 6)) y_offset = 0 max_x = 0 for sent in sentences: words = [token.text for token in sent] x_positions = range(len(words)) max_x = max(max_x, len(words)) # Dibujar palabras plt.plot(x_positions, [y_offset] * len(words), 'k-', alpha=0.2) plt.scatter(x_positions, [y_offset] * len(words), alpha=0) # Añadir texto for i, word in enumerate(words): plt.annotate(word, (i, y_offset), xytext=(0, -10), textcoords='offset points', ha='center') # Dibujar arcos de dependencia for token in sent: if token.dep_ != "ROOT": # Calcular profundidad de dependencia depth = 0 current = token while current.head != current: depth += 1 current = current.head # Determinar posiciones para el arco start = token.i - sent[0].i end = token.head.i - sent[0].i # Altura del arco basada en la distancia entre palabras height = 0.5 * abs(end - start) # Color basado en la profundidad color = depth_colors[min(depth, len(depth_colors)-1)] # Crear arco arc = patches.Arc((min(start, end) + abs(end - start)/2, y_offset), width=abs(end - start), height=height, angle=0, theta1=0, theta2=180, color=color, alpha=0.6) ax.add_patch(arc) y_offset -= 2 # Configurar el gráfico plt.xlim(-1, max_x) plt.ylim(y_offset - 1, 1) plt.axis('off') plt.title("Complejidad Sintáctica") return fig except Exception as e: logger.error(f"Error en create_syntax_complexity_graph: {str(e)}") return None