|
|
import streamlit as st
|
|
|
import pandas as pd
|
|
|
import networkx as nx
|
|
|
from pyvis.network import Network
|
|
|
from PIL import Image
|
|
|
import base64
|
|
|
import io
|
|
|
import json
|
|
|
import streamlit.components.v1 as components
|
|
|
|
|
|
|
|
|
|
|
|
if 'mapa_mental' not in st.session_state:
|
|
|
st.session_state['mapa_mental'] = {
|
|
|
'nombre': '',
|
|
|
'imagen': '',
|
|
|
'ramas': []
|
|
|
}
|
|
|
|
|
|
|
|
|
categoria_colores = ['#1f77b4', '#2ca02c', '#9467bd', '#bcbd22', '#ff7f0e', '#d62728']
|
|
|
|
|
|
|
|
|
def get_image_base64(image_data):
|
|
|
"""
|
|
|
Convierte una imagen en base64.
|
|
|
Puede manejar im谩genes en formato base64, objetos PIL o bytes.
|
|
|
"""
|
|
|
if isinstance(image_data, str) and image_data.startswith("data:image"):
|
|
|
return image_data
|
|
|
elif isinstance(image_data, Image.Image):
|
|
|
buffered = io.BytesIO()
|
|
|
image_data = image_data.resize((150, 150))
|
|
|
image_data.save(buffered, format="PNG")
|
|
|
return "data:image/png;base64," + base64.b64encode(buffered.getvalue()).decode("utf-8")
|
|
|
elif isinstance(image_data, bytes):
|
|
|
buffered = io.BytesIO(image_data)
|
|
|
image = Image.open(buffered).resize((150, 150))
|
|
|
buffered = io.BytesIO()
|
|
|
image.save(buffered, format="PNG")
|
|
|
return "data:image/png;base64," + base64.b64encode(buffered.getvalue()).decode("utf-8")
|
|
|
return None
|
|
|
|
|
|
|
|
|
def agregar_rama(nodo):
|
|
|
"""
|
|
|
A帽ade una nueva rama a un nodo dado.
|
|
|
"""
|
|
|
nueva_rama = {
|
|
|
'nombre': '',
|
|
|
'imagen': '',
|
|
|
'ramas': []
|
|
|
}
|
|
|
nodo['ramas'].append(nueva_rama)
|
|
|
|
|
|
|
|
|
def renderizar_ramas(nodo, ruta):
|
|
|
"""
|
|
|
Renderiza un formulario en el sidebar para una rama espec铆fica.
|
|
|
Permite ingresar el nombre y la imagen, y agregar sub-ramas.
|
|
|
"""
|
|
|
for idx, rama in enumerate(nodo['ramas']):
|
|
|
nueva_ruta = f"{ruta} -> Rama {idx + 1}"
|
|
|
st.sidebar.markdown(f"### Nodo: {nueva_ruta}")
|
|
|
|
|
|
|
|
|
nombre = st.sidebar.text_input(f"Nombre de la idea en {nueva_ruta}", value=rama['nombre'], key=f"nombre_{nueva_ruta}")
|
|
|
rama['nombre'] = nombre
|
|
|
|
|
|
|
|
|
imagen = st.sidebar.file_uploader(f"Cargar imagen para {nueva_ruta}", type=["png", "jpg", "jpeg"], key=f"imagen_{nueva_ruta}")
|
|
|
if imagen:
|
|
|
imagen_base64 = get_image_base64(imagen.read())
|
|
|
rama['imagen'] = imagen_base64
|
|
|
elif not rama['imagen']:
|
|
|
rama['imagen'] = ''
|
|
|
|
|
|
|
|
|
if st.sidebar.button(f"Agregar rama a {nueva_ruta}", key=f"boton_agregar_{nueva_ruta}"):
|
|
|
agregar_rama(rama)
|
|
|
|
|
|
|
|
|
renderizar_ramas(rama, nueva_ruta)
|
|
|
|
|
|
|
|
|
def agregar_nodos_recursivamente(G, nodo, datos, color, edge_width_dict):
|
|
|
"""
|
|
|
A帽ade nodos y edges al grafo de manera recursiva.
|
|
|
"""
|
|
|
nombre = datos["nombre"]
|
|
|
imagen = datos.get("imagen", None)
|
|
|
G.add_node(nombre, type='central' if nodo == "root" else 'ramificado', image=imagen if imagen else None, color=color)
|
|
|
|
|
|
if nodo != "root":
|
|
|
G.add_edge(nodo, nombre, color=color, width=edge_width_dict.get(nodo, 1))
|
|
|
|
|
|
ramas = datos.get("ramas", [])
|
|
|
num_ramas = len(ramas)
|
|
|
edge_width = max(1, 5 - num_ramas)
|
|
|
edge_width_dict[nombre] = edge_width
|
|
|
|
|
|
|
|
|
if color in categoria_colores:
|
|
|
color_index = (categoria_colores.index(color) + 1) % len(categoria_colores)
|
|
|
nuevo_color = categoria_colores[color_index]
|
|
|
else:
|
|
|
nuevo_color = 'gray'
|
|
|
|
|
|
for rama in ramas:
|
|
|
agregar_nodos_recursivamente(G, nombre, rama, nuevo_color, edge_width_dict)
|
|
|
|
|
|
|
|
|
def crear_grafico_mind_map(datos_entrada):
|
|
|
"""
|
|
|
Crea y visualiza el grafo del mapa mental usando Pyvis.
|
|
|
"""
|
|
|
G = nx.Graph()
|
|
|
edge_width_dict = {}
|
|
|
|
|
|
if not datos_entrada['nombre']:
|
|
|
st.warning("Por favor, ingresa la idea principal.")
|
|
|
return
|
|
|
|
|
|
|
|
|
raiz = datos_entrada["nombre"]
|
|
|
raiz_imagen = datos_entrada.get("imagen", None)
|
|
|
G.add_node(raiz, type='central', image=raiz_imagen if raiz_imagen else None, color=categoria_colores[0])
|
|
|
|
|
|
ramas = datos_entrada.get("ramas", [])
|
|
|
for rama in ramas:
|
|
|
agregar_nodos_recursivamente(G, raiz, rama, categoria_colores[0], edge_width_dict)
|
|
|
|
|
|
|
|
|
person_net = Network(
|
|
|
height='600px',
|
|
|
width='100%',
|
|
|
bgcolor='#222222',
|
|
|
font_color='white',
|
|
|
notebook=False
|
|
|
)
|
|
|
|
|
|
|
|
|
for node, data in G.nodes(data=True):
|
|
|
node_categoria = data.get('type', 'central')
|
|
|
color = data.get('color', 'gray')
|
|
|
|
|
|
node_options = {
|
|
|
"label": node,
|
|
|
"shape": "circularImage" if data.get('image') else "circle",
|
|
|
"image": data.get('image', ''),
|
|
|
"color": color,
|
|
|
"size": 80 if node_categoria == 'central' else 20,
|
|
|
"fixed": {"x": False, "y": False}
|
|
|
}
|
|
|
person_net.add_node(node, **node_options)
|
|
|
|
|
|
|
|
|
for source, target, edge_data in G.edges(data=True):
|
|
|
person_net.add_edge(source, target, color=edge_data.get('color', 'gray'), width=edge_data.get('width', 1))
|
|
|
|
|
|
|
|
|
person_net.repulsion(
|
|
|
node_distance=200,
|
|
|
central_gravity=0.33,
|
|
|
spring_length=100,
|
|
|
spring_strength=0.10,
|
|
|
damping=0.95
|
|
|
)
|
|
|
|
|
|
|
|
|
person_net.set_options("""
|
|
|
var options = {
|
|
|
"physics": {
|
|
|
"stabilization": {
|
|
|
"enabled": true,
|
|
|
"iterations": 1000
|
|
|
},
|
|
|
"minVelocity": 0.75
|
|
|
},
|
|
|
"interaction": {
|
|
|
"dragNodes": true,
|
|
|
"zoomView": true
|
|
|
}
|
|
|
}
|
|
|
""")
|
|
|
|
|
|
|
|
|
path = '/tmp'
|
|
|
person_net.save_graph(f'{path}/pyvis_graph.html')
|
|
|
|
|
|
with open(f'{path}/pyvis_graph.html', 'r', encoding='utf-8') as HtmlFile:
|
|
|
graph_html = HtmlFile.read()
|
|
|
|
|
|
|
|
|
components.html(graph_html, height=600, width=800)
|
|
|
|
|
|
|
|
|
def main():
|
|
|
st.set_page_config(layout="wide")
|
|
|
|
|
|
st.image('Mind Mapp.jpg', use_column_width=True)
|
|
|
st.title("Generador de Mapas Mentales")
|
|
|
|
|
|
tabs = st.tabs(["Rese帽a del Libro", "Mapa Mental", "Acerca de m铆"])
|
|
|
|
|
|
|
|
|
with tabs[0]:
|
|
|
resumen = """
|
|
|
## Resumen del libro: "Mapas Mentales" de Tony Buzan
|
|
|
|
|
|
"Mapas Mentales" de Tony Buzan es una gu铆a completa sobre la creaci贸n y uso de mapas mentales como herramienta para el pensamiento creativo, la organizaci贸n de ideas y la mejora de la memoria. Tony Buzan, reconocido como el padre de los mapas mentales, introduce en este libro t茅cnicas probadas para maximizar la eficiencia mental y potenciar el aprendizaje.
|
|
|
|
|
|
### **Conceptos Clave del Libro**
|
|
|
|
|
|
1. **Estructura de los Mapas Mentales:**
|
|
|
- **Idea Central:** Comienza con una idea o concepto principal en el centro de la p谩gina.
|
|
|
- **Ramas Principales:** Se extienden desde la idea central, representando las ideas principales relacionadas.
|
|
|
- **Palabras Clave:** Cada rama est谩 etiquetada con palabras clave que representan conceptos importantes.
|
|
|
- **Im谩genes y Colores:** El uso de im谩genes y colores ayuda a estimular el cerebro y facilita la memorizaci贸n y comprensi贸n.
|
|
|
|
|
|
2. **Beneficios de los Mapas Mentales:**
|
|
|
- **Mejora la Memoria:** La estructura visual facilita la retenci贸n de informaci贸n.
|
|
|
- **Fomenta la Creatividad:** Permite explorar m煤ltiples conexiones y asociaciones de ideas.
|
|
|
- **Organizaci贸n Eficiente:** Ayuda a estructurar pensamientos de manera l贸gica y coherente.
|
|
|
- **Resoluci贸n de Problemas:** Facilita la identificaci贸n de soluciones mediante el an谩lisis visual de situaciones complejas.
|
|
|
|
|
|
3. **Aplicaciones Pr谩cticas:**
|
|
|
- **Educaci贸n:** Para tomar apuntes, planificar estudios y resumir informaci贸n.
|
|
|
- **Negocios:** En la planificaci贸n de proyectos, brainstorming y presentaciones.
|
|
|
- **Desarrollo Personal:** En la definici贸n de metas, planificaci贸n de carrera y organizaci贸n de ideas personales.
|
|
|
|
|
|
4. **T茅cnicas Avanzadas:**
|
|
|
- **Asociaciones Liberadas:** Estimula la generaci贸n de ideas sin restricciones.
|
|
|
- **Uso de S铆mbolos y Dibujo:** Potencia la creatividad y hace que los mapas sean m谩s atractivos visualmente.
|
|
|
- **Integraci贸n de Informaci贸n:** Combina diferentes fuentes de informaci贸n en un solo mapa mental para una visi贸n hol铆stica.
|
|
|
|
|
|
### **M茅todos de Creaci贸n de Mapas Mentales**
|
|
|
|
|
|
- **Inicio Central:** Colocar la idea principal en el centro y dibujar ramas radiales hacia las ideas secundarias.
|
|
|
- **Palabras Clave:** Utilizar palabras breves que capturen la esencia de cada idea.
|
|
|
- **Colores y S铆mbolos:** Aplicar diferentes colores para categorizar informaci贸n y s铆mbolos para representar conceptos.
|
|
|
- **Jerarqu铆a Visual:** Utilizar tama帽os de fuente y grosor de l铆neas para indicar la importancia relativa de las ideas.
|
|
|
|
|
|
### **Conclusi贸n**
|
|
|
|
|
|
"Mapas Mentales" de Tony Buzan es una herramienta poderosa para cualquier persona que busque mejorar su capacidad de pensar, organizar ideas y aprender de manera m谩s efectiva. El libro no solo explica la teor铆a detr谩s de los mapas mentales, sino que tambi茅n proporciona instrucciones pr谩cticas para su implementaci贸n en diversas 谩reas de la vida personal y profesional.
|
|
|
"""
|
|
|
st.markdown(resumen)
|
|
|
|
|
|
|
|
|
with tabs[1]:
|
|
|
st.header("Mapa Mental")
|
|
|
st.sidebar.subheader("Ingresar Datos del Mapa Mental:")
|
|
|
|
|
|
|
|
|
st.sidebar.markdown("## Idea Principal")
|
|
|
nombre_principal = st.sidebar.text_input(
|
|
|
"Ingrese el nombre de la idea principal:",
|
|
|
st.session_state['mapa_mental']['nombre'],
|
|
|
key="nombre_principal"
|
|
|
)
|
|
|
|
|
|
imagen_principal = st.sidebar.file_uploader(
|
|
|
"Cargue una imagen para la idea principal",
|
|
|
type=["png", "jpg", "jpeg"],
|
|
|
key="imagen_principal"
|
|
|
)
|
|
|
if imagen_principal:
|
|
|
imagen_base64 = get_image_base64(imagen_principal.read())
|
|
|
st.session_state['mapa_mental']['imagen'] = imagen_base64
|
|
|
elif not st.session_state['mapa_mental']['imagen']:
|
|
|
st.session_state['mapa_mental']['imagen'] = ''
|
|
|
|
|
|
st.session_state['mapa_mental']['nombre'] = nombre_principal
|
|
|
|
|
|
st.sidebar.markdown("---")
|
|
|
|
|
|
|
|
|
if st.sidebar.button("Agregar rama a la idea principal"):
|
|
|
agregar_rama(st.session_state['mapa_mental'])
|
|
|
|
|
|
|
|
|
if st.session_state['mapa_mental']['nombre']:
|
|
|
renderizar_ramas(st.session_state['mapa_mental'], "Idea Principal")
|
|
|
|
|
|
st.sidebar.markdown("---")
|
|
|
|
|
|
|
|
|
if st.sidebar.button("Resetear Mapa Mental"):
|
|
|
st.session_state['mapa_mental'] = {
|
|
|
'nombre': '',
|
|
|
'imagen': '',
|
|
|
'ramas': []
|
|
|
}
|
|
|
st.experimental_rerun()
|
|
|
|
|
|
|
|
|
if st.sidebar.button("Generar Mapa Mental"):
|
|
|
crear_grafico_mind_map(st.session_state['mapa_mental'])
|
|
|
|
|
|
|
|
|
with tabs[2]:
|
|
|
st.header("Acerca de m铆")
|
|
|
acerca_de_mi = """
|
|
|
隆Hola! Soy Migue, desarrollo herramientas para facilitar la visualizaci贸n y organizaci贸n de ideas mediante mapas mentales interactivos. Esta aplicaci贸n est谩 dise帽ada para ayudarte a estructurar tus pensamientos de manera eficiente y creativa, utilizando tecnolog铆as como Streamlit, Pyvis y NetworkX.
|
|
|
|
|
|
**Caracter铆sticas de la Aplicaci贸n:**
|
|
|
- **Interfaz Intuitiva:** Agrega ideas principales y sus ramas de forma sencilla.
|
|
|
- **Visualizaci贸n Interactiva:** Explora tus mapas mentales de manera din谩mica y visualmente atractiva.
|
|
|
- **Personalizaci贸n:** Asigna im谩genes y colores a tus nodos para una mejor organizaci贸n y est茅tica.
|
|
|
|
|
|
**Contacto:**
|
|
|
- **Correo Electr贸nico:** [mail](mailto:josemiguelaguilart.com)
|
|
|
- **LinkedIn:** [LinkedIn](https://www.linkedin.com/in/josemaguilar/)
|
|
|
|
|
|
"""
|
|
|
st.markdown(acerca_de_mi)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
main()
|
|
|
|