Modelo de agentes activos de Vicsek

Hace algunos meses me enteré de la existencia del Núcleo Milenio de Materia Activa, el cual se especializa en el estudio de la dinámica de un gran número de miembros o "agentes", los cuales son unidades independientes que interaccionan con otros agentes vecinos a través de reglas simples y empíricas, por lo menos en sus fundamentos. De esta forma es posible describir el movimiento espontáneo y coherente de ciertos sistemas biológicos, como las bandadas de los pájaros. En el año 1995, el Biólogo físico Tamás Vicsek publicó un estudio llamado NOVEL TYPE OF PHASE TRANSITION IN A SYSTEM OF SELF-DRIVEN PARTICLES donde describe un modelo para describir el movimiento coherente de los cardúmenes y de las bandadas de pájaros en el vuelo.

wikipedia lo describe de la siguiente forma:

La materia activa está compuesta de un gran número de «agentes activos», cada uno de los cuales consume energía para moverse o para ejercer fuerzas mecánicas. Debido al consumo de energía, estos sistemas están intrínsecamente fuera de equilibrio térmico. Ejemplos de materia activa son los bancos de peces, bandadas de aves, bacterias, partículas autopropulsadas artificiales, y la auto-organización de los bio-polímeros tales como los microtúbulos y la actina, siendo parte ambos del citoesqueleto de las células vivas. La mayoría de los ejemplos de materia activa son de origen biológico; sin embargo, una gran cantidad del trabajo experimental está dedicado a los sistemas sintéticos.

Sin duda es una definición muy interesante, tomada o inspirada desde la mecánica estadística y aplicada elegántemente en los sistemas complejos biológicos fuera de equilibrio.

El modelo de Vicsek pretende cuantificar matemáticamente la interacción de un miembro del grupo, considerando su vecindad dentro de un rango o distancia de interacción. En este caso, para cada pájaro dentro de la bandada tanto como su posición, velocidad y ángulo del camino serán determinadas por la cantidad de vecinos dentro de una distancia particular, y con eso se creará la "materia activa", generando dichas estructuras coherentes o "materia blanda" que se observan en muchas configuraciones a nuestro alrededor.

Dado que el sistema describe la evolución temporal de cada pájaro miembro de la bandada, dada su posición inicial $\vec{r}(t=0)$ o en cualquier momento $\vec{r}(t)$, la posición cambiará en el siguiente instante $t + \Delta t$ siguiendo la ecuación itinerario (considerando la aceleración $\vec{a}=\vec{0}$):

$$ {\displaystyle \vec{r}(t+\Delta t)=\vec{r}(t)+\vec{v}(\theta) \Delta t}, $$

donde la velocidad $\vec{v}(\theta) = v_0 \left( \cos(\theta)\ \hat{i} + \sin(\theta)\ \hat{j}\right)$ es constante para cada individuo, y la dirección dependerá completamente del ángulo $\theta(t)$, la que a su vez es definida por los agentes en la vecindad local, la que en instante siguiente $t + \Delta t$ es definido de la forma:

$$ {\displaystyle \theta(t+\Delta t)=\langle \theta \rangle _{|r_{i}-r_{j}|<R}+\eta\ (t)}, $$

donde $\langle \theta \rangle$ representa el valor promedio de todas las direcciones del movimiento de cada vecino dentro del radio de acción ${|r_{i}-r_{j}|<R}$. En la siguiente imagen se grafica la configuración y la cuantificación matemática del modelo de materia activa. El agente azul se está moviendo hacia la izquierda, y su dirección se modificará teniendo en cuenta los agentes dentro de la circunferencia al rededor del agente azul.

Imagen 1: Planteamento del modelo matemático del Vicsek. El agente central azul es influenciado por cada uno de los agentes cercanos (agentes verdes), y su cercanía es cuantificada por la circunferencia de radio $R$. Imagen tomada desde un frame de un video de youtube (ver referencias).

El ángulo de cada ave dentro del círculo es considerado y el valor promedio del ángulo es obtenido de la forma:

$$ \displaystyle \langle \theta \rangle = \arctan{ \left( \frac{\sum_{k=1}^{N} \sin{(\theta_k)} }{\sum_{k=1}^{N} \cos{(\theta_k)}} \right) } $$

Además, el término $\eta\ (t)$ agrega una perturbación aleatoria en la dirección de movimiento, para así incluir algo de realismo al modelo. Todo lo anterior debe ser calculado para cada uno de los pájaros dentro de la bandada, por lo que la complejidad de este modelo recae en el poder de cómputo disponible para calcular cada uno de los anteriores parámetros a través de todos los momentos (o épocas) necesarios para ver la evolución temporal de la bandada.

Todo el procedimiento anterior es explicado a continuación en forma de pseudo-algoritmo de la ejecución del modelo de Vicsek:

Para cada uno de los pájaros dentro de la bandada:

  1. Definir de forma aleatoria las posiciones $\vec{r}_i=(x,y)$ y el angulo inicial $\theta_i$.
  2. Contamos cuántos vecinos están alrededor, dentro del radio $R$, y sus ángulos son considerados.
  3. Calculamos el valor promedio de los ángulos $\langle \theta \rangle$.
  4. Actualizamos la dirección de la la velocidad $\vec{v}$ utilizando el nuevo ángulo $\langle \theta \rangle$.
  5. Agregamos el término de perturbación random $\eta$.
  6. Finalmente, actualizamos la posición de cada pájaro usando la ecuación itinerario en el instante $t + \Delta t$.
  7. Repetir por cada época deseada.

Todo lo anterior es implementado en el siguiente script de python, usando como base la implementación de Philip Mocz (ver referencias). Para la siguiente simulación, se considerará una bandada de 3000 pájaros, en 200 épocas que se diferencian entre ellas por un tiempo $\Delta t=0.01$ segundos. No se diga más.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
import sys
plt.style.use('dark_background')

#Parámetros básico del modelo de Vicsek
#velocidad inicial:
v0 = 2.0
#Número de pájaros:
N = 3000
#Parámetro de ruido angular:
eta = 0.9       
#Tamaño de la caja:
Lx = 4           
Ly = 5
#Radio de interacción:
R  = 0.1        
#paso temporal Delta t:
dt = 0.01
Dt=dt
#Número de épocas:
Nt = 200     

np.random.seed(N)

#Se eligen las posiciones y velocidades de forma random:
x = np.random.rand(N)*Lx
y = np.random.rand(N)*Ly
v_init = np.random.rand(N)*v0
theta = 2*np.pi*np.random.rand(N)

#Calculamos las componentes individuales
vx = v_init * np.cos(theta)
vy = v_init * np.sin(theta)

#Iniciamos el plot y método quiver para visualizar:
fig, ax = plt.subplots(figsize=(4, 5), dpi=100)
quiver = ax.quiver(x, y, vx, vy, color='yellow',linewidth=3.9, headwidth=10, headlength=10)

#Función para crear el video:
def dibujar_plot(frame, quiver):
    #Iniciamos los valores para modificiarlos:
    global x, y, Lx, Ly, theta, vx, vy, Dt
    
    #Limpiamos el gráfico:
    ax.clear()
    ax.set_title('Simulación del modelo Vicsek')
    ax.set_xlim(0, Lx)
    ax.set_ylim(0, Ly)

    #Actualizamos la posicion de cada integrante
    x += vx * dt
    y += vy * dt

    #Condiciones de borde periódicas:
    #(esto me voló la cabeza)
    #https://pythoninchemistry.org/sim_and_scat/important_considerations/pbc.html
    x = x % Lx
    y = y % Ly

    #Contamos cuántos agentes están dentro del radio R:
    mean_theta = theta[:]
        
    for b in range(N):
        neighbors = np.sqrt((x - x[b])**2 + (y - y[b])**2) < R
        sx = np.mean(np.cos(theta[neighbors]))
        sy = np.mean(np.sin(theta[neighbors]))
        mean_theta[b] = np.arctan2(sy, sx)

    #Añadimos el ruido, hay que restar 0.5 porque los valores random van entre 0 y 1:
    theta = mean_theta + eta*(np.random.rand(N)-0.5)

    #Actualizamos la velocidad:
    vx = v_init * np.cos(theta)
    vy = v_init * np.sin(theta)
    #Llevamos la cuenta del tiempo:
    Dt += dt

    #Actualizamos el plot con la nueva época:
    quiver = ax.quiver(x, y, vx, vy, color='yellow',linewidth=3.9, headwidth=10, headlength=10)
    ax.set_aspect('equal')
    ax.tick_params(axis="x", labelsize=0)
    ax.get_yaxis().set_visible(False)
    ax.set_xlabel('tiempo t=%.1f [s]' %Dt)

#Guardamos la simulación:
ani = animation.FuncAnimation(fig, dibujar_plot, fargs=(quiver,), frames=Nt, interval=100)
ani.save('simulation_vicsek.mp4', writer='ffmpeg', fps=100)
plt.close()

Un video extendido de esta simulación puede ser encontrado en mi en mi canal de youtube o en mi cuenta de instagram @nicomediap

¡Gracias por la atención!

Referencias;

Simulate Active Matter: Viscek model for flocking birds: Una gran fuente de inspiración, implementado por Philip Mocz (2021). Básicamente tomé este código y le agregé cosas de mi cosecha.

Active Matter: Modelling swarming behaviour using the Vicsek model: Una exposición en Youtube sobre el tema.

Visualizando el campo eléctrico

He vuelto a la teoría electromagnética, de revisar sus postulados, leyes y aritmética y tengo algunas ideas para ver si es posible mejorar en la visualización y coomprensión de algunos postulados básicos de esta teoría que sin duda alguna ha revolucionado a la humanidad a un nivel aún desconocido.

En un viaje de casi 300 años se pasó de entender las cargas estáticas a los circuitos digitales integrados, y no pocas cosas han ocurrido entre medio. Hitos gigantes han debido ocurrir para que se integraran a las matemáticas conceptos fundamentales como el campo vectorial, su superposición y algunas propiedades fundamentales como el potencial vectorial.

Por supuesto, estas palabras tienen como objetivo el acercamiento de la teoría electromagnética, particularmnete al campo eléctrico y la visualización del campo eléctrico en una región del espacio. Trataré de ser lo más riguroso posible en el tono coloquial con el que tomó vuelo esté escrito.

Además de discutir y experimentar con el uso del campo escalar del potencial electrostático.

El concepto de campo eléctrico;

Los y las científicas creemos que los campos físicos existen, que el espacio tiene propiedades y pueden ser cuantificados por la medición de ciertas cantidades fundamentales. Por supuesto, ya estamos acostumbrados a la idea de que existen entidades invisibles a nuestro alrededor: el WIFI, la señal del teléfono, etc; o también por su uso en la ciencia ficción con sus "campos de fuerzas" que sirven de escudos.

Pero si logramos bajar la velocidad de la vida, y racionalizamos el hecho de la acción a distancia que caracteriza a algunos campos físicos, resulta increible pensar en esta entidad invisible donde interaccionan la materia que posee carga eléctrica $q$. Pero evidencia de su existencia hay por montones, y no queda más que aceptar la idea.

La teoría electrostática nos dice que el campo eléctrico $\vec{E}(\vec{x})$ en cada punto del espacio 2D $(x,y)$ caracterizado por el vector $\vec{x}=(x,y)$, en el cual actúan una distribución de cargas puntuales $q$ cada una de ellas con posición $\vec{x}^{*}$ es cuantificado por la siguiente ley física:

$$\vec{E}(\vec{x}-\vec{x}^{*}) = \frac{q}{4\pi \epsilon_{0}}\frac{(\vec{x}-\vec{x}^{*})}{\|\vec{x}-\vec{x}^{*}\|^3}, $$

donde $\epsilon_0$ es la constante conocida como la "permitividad del vacío", estréchamente relacionada con la velocidad de la luz $c$ y la "permeabilidad magnética del vacío" $\mu_0$, y se define de la forma:

$$\displaystyle \epsilon_0 = \frac{1}{c^2\mu_0} = 8.8541\times10^{-12} \left[\frac{\mbox{F}}{\mbox{m}}\right],$$

donde F expresa las unidades de Faradios, y m los metros de toda la vida. Todo lo anterior puede sonar intimidante, pero esto sólo es la generalidad del comienzo. Básicamente, el campo eléctrico es proporcional del cuadrado de la distancia, entonces en principio bastaría calcular la distancia $d = \sqrt{x^2 + y^2}$ a cada punto y calcular el campo en dicho punto. Por lo tanto, la geometría del problema ha hablado, y podemos considerar coordenadas polares $(r,\theta)$ para así facilitar los cálculos.

Si consideramos el el vector cartesiano $\vec{x} = x \hat{i} + y \hat{j}$, utilizando un cambio de variable tal que:

$$x= r \cos \theta, y= r \sin \theta\, $$

tenemos que el vector cartesiano $\vec{x}$ puede ser descrito por:

\begin{align*} \vec{x} \>&=\> x \hat{i} + y \hat{j} \\ \>&=\> r \cos \theta\ \hat{i} + r \sin \theta\ \hat{j} \\ \>&=\> r \left( \cos \theta\ \hat{i} + \sin \theta\ \hat{j}\right) \\ \>&=\> r\ \hat{r}(\theta) \\ \end{align*}

Así, podemos simplificar un problema de dos variables $(x,y)$ en solo una $r$, por lo tanto nos enfrentamos a un problema que depende nétamente de la distancia $r$ de cada carga $q$ que interaccione en este campo eléctrico. Como el vector $\vec{x}$ depende sólo de la distancia a las fuentes $\vec{x}^{*}$, el vector que apunta a cada elemento en este espacio será $\left( \vec{x} - \vec{x}^{*} \right)$. Ya con esto podemos usar diréctamente el teoréma de pitágoras para calcular la distancia de la fuente a cada punto del espacio, pero empezaremos por una carga puntual en el origen.

El caso más simple: carga en el origen;

Considerando una carga puntual en el origen (es decir, $(x^{*}, y^{*})=(0,0)$), se puede demostrar que la expresión del campo eléctrico en todo punto es de la forma:

$$\vec{E}(\vec{r}) = \frac{q}{4\pi \epsilon_{0}}\frac{\hat{r}}{r^2},$$

donde cada carga $q$ presentes y considerados en el problema tiene similares propiedades. El vector $\vec{r}=r\ \hat{r}$ es un vector polar el cual debe ser expresado en las coordenadas cartesianas que usaremos para visualizar los efectos. Considerando la distancia desde el origen a cualquier punto del espacio:

$$r = \sqrt{x^2 + y^2}$$

Y además, considerando la descomposición

\begin{align*} \vec{E}(r,\theta) \>&=\> \frac{q}{4\pi \epsilon_{0}}\frac{\hat{r}}{r^2} \\ \>&=\> \frac{q}{4\pi \epsilon_{0}}\frac{ \left[\cos \theta\ \hat{i} + \sin \theta\ \hat{j} \right]} {r^2} \\ \>&=\> \frac{q}{4\pi \epsilon_{0}}\frac{ r \left[\cos \theta\ \hat{i} + \sin \theta\ \hat{j} \right]} {r^3} \\ \>&=\> \left( \frac{q}{4\pi \epsilon_0}\frac{r \cos \theta}{r^3}\right) \hat{i} + \left(\frac{q}{4\pi \epsilon_0} \frac{r \sin \theta}{r^3}\right) \hat{j} \end{align*}

Podemos obtener una expresión que será útil para convertir a coordenadas cartesianas. Vean que, de hecho, agregamos un término "$r$" en el tercer paso para manipular la expresión. Entonces, usando el cambio de variable de coordenadas de cartesianas a polares:

\begin{align*} \vec{E}(x,y) \>&=\> E_x \hat{i} + E_y\hat{j} \\ \>&=\> \left( \frac{q}{4\pi \epsilon_0}\frac{r \cos \theta}{r^3}\right) \hat{i} + \left(\frac{q}{4\pi \epsilon_0} \frac{r \sin \theta}{r^3}\right) \hat{j} \\ \>&=\> \left( \frac{q}{4\pi \epsilon_0}\frac{x}{(x^2 + y^2)^{\frac{3}{2}}}\right) \hat{i} + \left(\frac{q}{4\pi \epsilon_0} \frac{y}{(x^2 + y^2)^{\frac{3}{2}}}\right) \hat{j} \end{align*}

Por ende en coordenadas cartesianas el campo eléctrico y las componentes se calculan de la siguiente forma:

$$E_x = \frac{q}{4\pi \epsilon_0}\frac{x}{(x^2 + y^2)^{\frac{3}{2}}} $$$$E_y = \frac{q}{4\pi \epsilon_0}\frac{y}{(x^2 + y^2)^{\frac{3}{2}}} $$

La verdad de las cosas no he hemos hecho nada nuevo hasta aquí, yo diría que todo lo anterior se sabe desde hace más de 100 años. Lo realmente interesante es la libertad de la implementación experimental que nos dan los lenguales de programación, que nos permite calcular todo lo anterior de forma iterativa.

Entonces, primero definimos las constantes físicas y luego definimos la función que calculará el campo eléctrico de una carga $q$ en el origen:

#Definimos constantes físicas:
#Permeatividad del vacío:
epsilon = 8.854e-12
#Carga fundamental del electrón:
q = 1.602e-19

#Definimos la función que calcula el campo eléctrico desde las coordenadas:
def E_origen(q, x, y):
    """Retorna el campo de una carga puntual en el origen, de la forma E=(Ex,Ey)."""
    r = np.sqrt(x**2+ y**2)
    Ex = (q/4*np.pi*epsilon) * x / r**(3/2)
    Ey = (q/4*np.pi*epsilon) * y / r**(3/2)
    return Ex,Ey 

Lo primero que haremos será iniciar una región para poder calcular la influencia de las fuentes de carga $q$ que están presentes:

import sys
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Rectangle

plt.style.use('dark_background')

#Grilla de puntos que se utilizarán en estos experimentos
plt.figure(figsize=(4,5))
nx, ny = 100, 100
x = np.linspace(-2, 2, nx)
y = np.linspace(-4, 4, ny)
X, Y = np.meshgrid(x, y)
plt.scatter(X, Y, s=1.0, color='w', marker='.')
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.show()

Entonces, lo que haremos es cada punto (i,j) de la siguiente matriz, será evaluadaa la función E_origen, luego calculamos el campo eléctrico $\vec{E}(x,y)$ desde la suma independiente de sus componentes individuales $E_{x}$ y $E_{y}$

# Iniciamos los valores de cada componente:
Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

# Calculamos las componentes del campo eléctrico:
Ex, Ey = E_origen(q, x=X, y=Y)

fig = plt.figure(figsize=(4,5))
#Usamos "streamlines" para visualizar el campo eléctrico:
color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.2, cmap=plt.cm.jet,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#Dibujamos la carga y su nombre:
plt.scatter(0, 0, zorder=1, s=600,edgecolor='k', facecolor='red')
plt.text(-0.1, -0.08, '$q$', fontsize=18, c='k')

plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.show()

Un hito: la visualización del campo eléctrico más simple que existe!! Desde acá podemos ver que cargas positivas emite líneas de campo eléctrico. También puede decirse que es fuente de campo eléctrico, aunque puede ser algo redundante ya que el hecho de poseer carga ya posee interacción en el campo. Cargas negativas $-q$ recibe líneas de campo eléctrico, también conocido como un "sumidero", término que es prestado de otros campos de la física. Más adelante está el ejemplo de la interacción de una carga $-q$ que interacciona en el espacio.

Desplazando y agregando cargas:;

Como nos enfrentamos a un problema que depende nétamente de la distancia $r$ de cada carga $q$ que interaccione en este campo eléctrico, el vector que apunta a cada elemento en este espacio, considerando la influencia de las cargas presentes será $\left( \vec{x} - \vec{x}^{*} \right)$.

Por suerte, podemos seguir usando nuestro querido teoréma de pitágoras y calcular la distancia a cada punto del espacio de la forma:

$$r = \sqrt{ (x-x^{*})^2 + (y-y^{*})^2}$$

De la misma forma anterior, considerando la descomposición:

\begin{align*} \vec{E}(\vec{x} - \vec{x}^{*}) \>&=\> E_x \hat{i} + E_y\hat{j} \\ \>&=\> \left( \frac{q}{4\pi \epsilon_0}\frac{r \cos \theta}{r^3}\right) \hat{i} + \left(\frac{q}{4\pi \epsilon_0} \frac{r \sin \theta}{r^3}\right) \hat{j} \\ \>&=\> \left( \frac{q}{4\pi \epsilon_0}\frac{(x-x^{*})}{\left[(x-x^{*})^2 + (y-y^{*})^2\right]^{\frac{3}{2}}}\right) \hat{i} + \left(\frac{q}{4\pi \epsilon_0} \frac{(y-y^{*})}{\left[(x-x^{*})^2 + (y-y^{*})^2\right]^{\frac{3}{2}}}\right) \hat{j} \end{align*}

Por ende en coordenadas cartesianas el campo eléctrico y las componentes se calculan de la siguiente forma:

$$E_x = \frac{q}{4\pi \epsilon_0}\frac{(x-x^{*})}{ \left[(x-x^{*})^2 + (y-y^{*})^2\right]^{\frac{3}{2}}}$$$$E_y = \frac{q}{4\pi \epsilon_0}\frac{(y-y^{*})}{ \left[(x-x^{*})^2 + (y-y^{*})^2\right]^{\frac{3}{2}}}$$

Con esto, podemos localizar una carga $q$ en cualquier lugar de este espacio de dos dimensiones.

def E_puntual(q,posx, posy, x, y):
    """Retorna el campo de una carga puntual, de la forma E=(Ex,Ey), informada su posición."""
    r = np.sqrt((x-posx)**2+ (y-posy)**2)
    Ex = (q/4*np.pi*epsilon) * (x-posx) / r**(3/2)
    Ey = (q/4*np.pi*epsilon) * (y-posy) / r**(3/2)
    return Ex,Ey 

Usaremos la función antes descrita para colocar una carga $q$ en la posición $(x^*,y^*)=(0,2)$

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

posicion = [0,2]

#Calculamos el campo eléctrico de una carga en (0.2)
Ex, Ey = E_puntual(q,posx=posicion[0],posy=posicion[1], x=X, y=Y)

fig = plt.figure(figsize=(4,5))

#Usamos "streamlines" para visualizar el campo eléctrico:
color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.2, cmap=plt.cm.jet,
              density=1.5, arrowstyle='->', arrowsize=1.5, zorder=0)

#Dibujamos la carga y su nombre:
plt.scatter(posicion[0], posicion[1], zorder=1, s=800,edgecolor='k', facecolors='red')
plt.text(-0.1, 1.95, '$q$', fontsize=18, c='k')

plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.show()

Usaremos la misma función antes descrita para colocar una carga de signo contrario $-q$ en la posición $(x^*,y^*)=(0,-2)$

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

posicion = [0,-2]

#Calculamos el campo eléctrico de una carga en (0.2)
Ex, Ey = E_puntual(-q,posx=posicion[0],posy=posicion[1], x=X, y=Y)

fig = plt.figure(figsize=(4,5))

#Usamos "streamlines" para visualizar el campo eléctrico:
color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.2, cmap=plt.cm.jet,
              density=1.5, arrowstyle='->', arrowsize=1.5, zorder=0)

#Dibujamos la carga y su nombre:
plt.scatter(posicion[0], posicion[1], zorder=1, s=800,edgecolor='k', facecolors='blue')
plt.text(-0.25, -2.07, '$-q$', fontsize=16, c='w')
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)

plt.show()

Veamos que esta carga es negativa, por lo que atrae líneas de campo eléctrico. Las cargas positivas emiten líneas de campo eléctrio, las cargas negativas atraen líneas de campo, es por esto que el dicho popular dice: "los opuestos de atraen".

Superposición del campo eléctrico;

Otra gran propiedad aplicable al campo eléctrico es el principio de superposicion, es decir que es posible calcular el campo eléctrico total $\vec{E}_{total}$ en una región es igual a la suma individual del campo eléctrico provocado por cada fuente. La suma individual de cada componente del sistema dará como resultado el campo total.

En general, podríamos tener $N$ cargas puntuales y el campo eléctrico total en cada punto será las sumas individuales de cada campo eléctrico en ese punto. Dicho de forma matemática:

$$ \vec{E}_{total} = \vec{E}_{q_1} + \vec{E}_{q_2} + ... + \vec{E}_{q_N} = \sum_{k=i}^{N} \vec{E}_{k}$$

Usaremos esta propiedad en las dos cargas antes creadas: la carga positiva $q$ creada en los puntos (x,y)=(0,2) y la carga negativa $-q$ que hemos cread en los puntos (x,y)=(0,-2). Así, podemos expresar la superposición de la forma:

$$ \vec{E}_{total} = \sum_{k=1}^{2} \vec{E}_k = \vec{E}_{q_1} + \vec{E}_{q_2} $$

En el caso de dos cargas opuestas, alineadas en el eje x, se forma el patrón de un dipolo eléctrico:

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Ponemos una carga en las coordenadas (x,y)=(0,2) y calculamos su campo:
ex_q1, ey_q1 = E_puntual(q,posx=0,posy=2, x=X, y=Y)

#Ponemos otra carga en las coordenadas (x,y)=(0,-2) y calculamos su campo:
ex_q2, ey_q2 = E_puntual(-q,posx=0,posy=-2, x=X, y=Y)

#Sumamos la contribución al campo general, usando la propiedad de superposición:
Ex = ex_q1 + ex_q2
Ey = ey_q1 + ey_q2

fig = plt.figure(figsize=(4,5))

color = np.log(np.hypot(Ex, Ey))

plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.2, cmap=plt.cm.jet,
              density=1., arrowstyle='->', arrowsize=1.5, zorder=0)

#Dibujamos las cargas
plt.scatter(0, 2, zorder=1, s=600, facecolors='red', edgecolor='k', label = '$q$')
plt.text(-0.08, 1.95, '$q$', fontsize=16, c='k')
plt.scatter(0,-2, zorder=1, s=600, facecolors='blue',edgecolor='k', label = '$-q$')
plt.text(-0.2045, -2.07, '$-q$', fontsize=14, c='w')

plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title('Dipolo eléctrico', fontsize=14)
plt.show()

Ya, todo esto fue lo básico: lo mínimo que debes saber para poder meter las manos en un mundo donde el que prueba es el que avanza. De aquí en adelante dependerá de tu ingenio y cómo puedes construir estructuras usando esta lógica.

Una de las formas efectivas que existen es demostrada en este link del libro Learning Scientific Programming with Python, es el de "crear" un grupo de cargas en posiciones espefícicas, y luego se itera sobre ellas para agregar sus contribuciones individuales de campo eléctrico sobre la región de interés. Dicho de forma estructurada:

  1. Definir un contenedor $\mathtt{cargas}$ donde se agregarán cargas puntuales.
  2. Definir cómo se distribuirán las cargas, y su signo (q o -q).
  3. Agregar la carga al contenedor $\mathtt{cargas}$.
  4. Hacer un loop sobre cada carga, y que su contribución se haga individualmente.
  5. Visualización del campo $\vec{E}(x,y)$

Construiré estructuras sencillas, seguidas en la lógica de las funciones que hemos creado. Por ejemplo podemos crear una "barra" cargada positivamente, hecha por una fila de cargas puntuales positivas y evaluaremos cada campo eléctrico por separado. Para esto, usaremos 100 cargas individuales, equiespaciadas entre -5 a 5 en el eje $y$. También, vamos a considerar que las estructuras de color roja están cargadas positivamente (fuentes de campo eléctrico), y las estructuras azules serán cargas negativas (receptoras de campo eléctrico).

#Definimos el número de cargas a usar
nq = 100

#Creamos un contenedor vacío de cargas a evaluar
cargas = []

#Línea recta a lo larga del eje Y:
coords_y = np.linspace(-5,5,nq)

#Iteramos sobre las coordenadas en el eje y
for coordenada in coords_y:
    #Agregamos una carga q, con coordenada x=0, y coordenada y=coordenada
    cargas.append((q,0,coordenada))
#Grilla de puntos que se utilizarán en estos experimentos
plt.figure(figsize=(4,5))
x = np.linspace(-4, 4, nx)
y = np.linspace(-8, 8, ny)
X, Y = np.meshgrid(x, y)

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual 
#se usa para calcular el campo final:
#Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    #En cada iteración, se le agrega ex a Ex.
    Ex += ex
    Ey += ey

color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.3, cmap=plt.cm.hot,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#pintamos los objetos 
plt.gca().add_patch(Rectangle((-0.15, -5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'red',
             fill=True,
             lw=2))
    
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title(r'${\vec{E}(x,y)}$', fontsize=14, color='yellow')
plt.show()

Una barra super saiyajin jajaja. Ahora, agregaremos dos barras pero de cargas diferentes, buscando la configuración de "placas paralelas". Para esto limpiaremos el contenedor $\mathtt{cargas}$ y agregaremos dos estructuras similares, separadas en el eje x. No se diga más!

#Definimos el número de cargas a usar
nq = 200

#Creamos un contenedor vacío de cargas a evaluar
cargas = []

#Línea recta a lo larga del eje Y:
coords_izq_y = np.linspace(-5,5,nq)

for coordenada in coords_izq_y:
    cargas.append((-q,-1,coordenada))
    
#Línea recta a lo larga del eje Y:
coords_der_y = np.linspace(-5,5,nq)

for coordenada in coords_der_y:
    cargas.append((q,1,coordenada))

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual se usa 
#para calcular el campo final. Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    Ex += ex
    Ey += ey

fig = plt.figure(figsize=(4,5))

color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.4, cmap=plt.cm.hot,
              density=1., arrowstyle='->', arrowsize=1.1, zorder=0)

#pintamos los objetos 
plt.gca().add_patch(Rectangle((-1.2, -5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'blue',
             fill=True,
             lw=2))

plt.gca().add_patch(Rectangle((1, -5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'red',
             fill=True,
             lw=2))
    
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title(r'${\vec{E}(x,y)}$', fontsize=14, color='yellow')
plt.show()

Interesante, se ve el efecto de las placas paralelas en la uniformidad del campo eléctrico entre ellas!. Genial. Esta aproximación de cargas puntuales puestas espacialmente una al lado de la otra funciona bien.

Hagamos un zoom al uno de los bordes de las placas paralelas:

#Grilla de puntos que se utilizarán en estos experimentos
x = np.linspace(-2, 2, nx)
y = np.linspace(-4, 4, ny)
X, Y = np.meshgrid(x, y)

#Definimos el número de cargas a usar
nq = 150

#Creamos un contenedor vacío de cargas a evaluar
cargas = []

#Línea recta a lo larga del eje Y:
coords_izq_y = np.linspace(-0.5,8,nq)

for coordenada in coords_izq_y:
    cargas.append((-q,-1,coordenada))
    
#Línea recta a lo larga del eje Y:
coords_der_y = np.linspace(-0.5,8,nq)

for coordenada in coords_der_y:
    cargas.append((q,1,coordenada))

plt.figure(figsize=(4,5))
Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual se usa para calcular el campo final:
#Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    Ex += ex
    Ey += ey

# Plot the streamlines with an appropriate colormap and arrow style
color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=2, cmap=plt.cm.hot,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#pintamos los objetos 
plt.gca().add_patch(Rectangle((-1.13, -0.5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'blue',
             fill=True,
             lw=2))

plt.gca().add_patch(Rectangle((0.88, -0.5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'red',
             fill=True,
             lw=2))
    
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.xlim(-2,2)
plt.ylim(-2,3)
plt.title(r'${\vec{E}(x,y)}$', fontsize=14, color='yellow')
plt.show()

Como dije, de aquí en adelante la verdad sólo depende de cómo se agregenen las coordenadas de las cargas y sus magnitudes. Una de las cosas que se me ocurrió construir fue una elipse, que cada una de sus mitades tiene diferente signo. Lo que si, tuve que improvisar en el dibujo de las cargas en el plot, porque no sé aún cómo representar superficies arbitrarias con los bordes delineados. Con las barras fue fácil, pero ahora ya no hay tiempo.

#Definimos el número de cargas a usar
nq = 200

#Creamos un contenedor vacío de cargas a evaluar
cargas = []

escala1, escala2=1,2

#Semi circulo derecho
#puntos entre angulos -pi/2 y + pi/2
coords_y = np.linspace(-np.pi/2,np.pi/2,nq)

for coordenada in coords_y:
    cargas.append((q,escala1*np.cos(coordenada),escala2*np.sin(coordenada)))
    
#Semi circulo izquierdo 
#puntos entre angulos pi/2 y + 3pi/2
coords_y = np.linspace(np.pi/2,3*np.pi/2,nq)

for coordenada in coords_y:
    cargas.append((-q,escala1*np.cos(coordenada),escala2*np.sin(coordenada)))
x = np.linspace(-4, 4, nx)
y = np.linspace(-8, 8, ny)
X, Y = np.meshgrid(x, y)

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual se usa para calcular el campo final:
#Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    Ex += ex
    Ey += ey

fig = plt.figure(figsize=(4,5))

# Plot the streamlines with an appropriate colormap and arrow style
color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.3, cmap=plt.cm.hot,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#pintamos los objetos 
for q, posx,posy in cargas:
    if q < 0 :
        plt.scatter(posx,posy,zorder=1, s=90, facecolors='blue' )
    else:
        plt.scatter(posx,posy,zorder=1, s=90, facecolors='red' )

plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title(r'${\vec{E}(x,y)}$', fontsize=14, color='orange')
plt.show()

Y si seguimos intruseando en los parámetros de estas estructuras, podemos crear visualizaciones cada vez más interesantes y estéticas, como la siguiente que logré al rotar el eje de simetría de la epilse polarizada:

x = np.linspace(-4, 4, nx)
y = np.linspace(-8, 8, ny)
X, Y = np.meshgrid(x, y)

#Definimos el número de cargas a usar
nq = 200

#Creamos un contenedor vacío de cargas a evaluar
cargas = []

escala1, escala2=3,7
angulo = 80

#Semi circulo derecho
#puntos entre angulos -pi/2 y + pi/2
coords_y = np.linspace(-np.pi/2,np.pi/2,nq)

for coordenada in coords_y:
    cargas.append((q,escala1*np.cos(coordenada+angulo),escala2*np.sin(coordenada)))
    
#Semi circulo izquierdo 
#puntos entre angulos pi/2 y + 3pi/2
coords_y = np.linspace(np.pi/2,3*np.pi/2,nq)

for coordenada in coords_y:
    cargas.append((-q,escala1*np.cos(coordenada+angulo),escala2*np.sin(coordenada)))

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual se usa para calcular el campo final:
#Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    Ex += ex
    Ey += ey

fig = plt.figure(figsize=(4,5))

# Plot the streamlines with an appropriate colormap and arrow style
color = np.log(np.hypot(Ex, Ey))

plt.streamplot(x, y, Ex, Ey, color=color, linewidth=1.2, cmap=plt.cm.hot,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#pintamos los objetos 
for q, posx,posy in cargas:
    if q < 0 :
        plt.scatter(posx,posy,zorder=1, s=90, facecolors='blue' )
    else:
        plt.scatter(posx,posy,zorder=1, s=90, facecolors='red' )

plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title(r'${\vec{E}(x,y)}$', fontsize=14, color='orange')
plt.show()

Potencial electrostático;

Ya para finalizar, una cantidad aún más fudamental que el campo eléctrico es el potencial electrostático. Para una carga puntual, el potencial está definido por:

$$\phi(\vec{x}-\vec{x}^{*}) = \frac{1}{4\pi \epsilon_{0}}\frac{q}{\|\vec{x}-\vec{x}^{*}\|}. $$

Es una cantidad fundamental, ya que es un campo escalar, es decir que para cada punto (x,y) existe un valor $\phi(\vec{x})$ asociado. Por consecuencia, el potencial eléctrico es una distribución en el espacio, y no dos o más valores asociadas, como es el caso del campo eléctrico $\vec{E}$. Por supuesto que el vínculo entre el potencial y el cámpo es estrecha, dado que el Campo eléctrico es el gradiente del potencial eléctrico:

$$\vec{E} = -\vec{\nabla}\phi(\vec{x}),$$

es decir, el campo eléctrico en realidad sigue la dirección donde el potencial $\phi$ cambiará más rapidamente, generando superficies equipotenciales en lugares que sean perpendiculares a las líneas de campo eléctrico.

El potencial es definido en la siguiente función llamada $\mathtt{P\_ puntual}$:

def P_puntual(q,posx, posy, x, y):
    """Retorna el potencial eléctrico de una carga puntual"""
    r = np.sqrt((x-posx)**2+ (y-posy)**2)
    Pot = (1/(4*np.pi*epsilon))*(q/r)
    return Pot

Usaremos algunas de las configuraciones anteriores y visualizaremos el potencial $\phi(\vec{x}-\vec{x}^{*})$ en conjunto con los campos eléctricos. Hasta usaremos el mismo bucle para calcular el campo escalar:

x = np.linspace(-2, 2, nx)
y = np.linspace(-4, 4, ny)
X, Y = np.meshgrid(x, y)

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Ponemos una carga en las coordenadas (x,y)=(0,-2) y calculamos su campo:
ex_q1, ey_q1 = E_puntual(-q,posx=0,posy=-2, x=X, y=Y)

#Ponemos otra carga en las coordenadas (x,y)=(0,2) y calculamos su campo:
ex_q2, ey_q2 = E_puntual(q,posx=0,posy=2, x=X, y=Y)

#Sumamos la contribución al campo general, usando la propiedad de superposición:
Ex = ex_q1 + ex_q2
Ey = ey_q1 + ey_q2

fig = plt.figure(figsize=(4,5))
# Plot the streamlines with an appropriate colormap and arrow style
color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=0.8, cmap=plt.cm.hot,
              density=1., arrowstyle='->', arrowsize=1.5, zorder=0)

#Ponemos una carga en las coordenadas (x,y)=(0,-2) y calculamos su campo:
P_1 = P_puntual(-q,posx=0,posy=-2, x=X, y=Y)

#Ponemos otra carga en las coordenadas (x,y)=(0,2) y calculamos su campo:
P_2 = P_puntual(q,posx=0,posy=2, x=X, y=Y)

#Sumamos la contribución al campo general, usando la propiedad de superposición:
P_tot = P_1 + P_2

contornos = np.linspace(np.min(P_tot),np.max(P_tot),45)
cset = plt.contour(X, Y, P_tot,contornos, colors='w')

#Dibujamos las cargas
plt.scatter(0, 2, zorder=1, s=800, facecolors='red', edgecolor='k', label = 'q')
plt.scatter(0,-2, zorder=1, s=800, facecolors='blue',edgecolor='k',label = '-q')

#plt.legend(loc='right',fontsize=20)
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)

plt.title(r'${\phi(x,y)}$', fontsize=14)
plt.show()
#Grilla de puntos que se utilizarán en estos experimentos
plt.figure(figsize=(4,5))
nx, ny = 100, 100
x = np.linspace(-2, 2, nx)
y = np.linspace(-2, 12, ny)
X, Y = np.meshgrid(x, y)

#Definimos el número de cargas a usar
nq = 150

#Creamos un contenedor vacío de cargas a evaluar
cargas = []
P_tot = 0

#Línea recta a lo larga del eje Y:
coords_izq_y = np.linspace(-0.5,10,nq)

for coordenada in coords_izq_y:
    cargas.append((-q,-1,coordenada))
    
#Línea recta a lo larga del eje Y:
coords_der_y = np.linspace(-0.5,10,nq)

for coordenada in coords_der_y:
    cargas.append((q,1,coordenada))

# Electric field vector, E=(Ex, Ey), as separate components
Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual se usa para calcular el campo final:
#Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    Ex += ex
    Ey += ey
    P_tot += P_puntual(*carga, x=X, y=Y)

color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=0.6, cmap=plt.cm.hot,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#pintamos los objetos 
plt.gca().add_patch(Rectangle((-1.13, -0.5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'blue',
             fill=True,
             lw=2))

plt.gca().add_patch(Rectangle((0.88, -0.5), 0.3, 10,
             edgecolor = 'black',
             facecolor = 'red',
             fill=True,
             lw=2))
    
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)

contornos = np.linspace(np.min(P_tot),np.max(P_tot),20)
plt.contour(X, Y, P_tot,contornos, colors='w')
plt.title(r'${\phi(x,y)}$', fontsize=14)
plt.show()
x = np.linspace(-4, 4, nx)
y = np.linspace(-8, 8, ny)
X, Y = np.meshgrid(x, y)

#Definimos el número de cargas a usar
nq = 200

#Creamos los contenedores vacíos de los campos:
cargas = []
P_tot = 0

escala1, escala2=2,5

#Semi circulo derecho
#puntos entre angulos -pi/2 y + pi/2
coords_y = np.linspace(-np.pi/2,np.pi/2,nq)

for coordenada in coords_y:
    cargas.append((q,escala1*np.cos(coordenada),escala2*np.sin(coordenada)))
    
#Semi circulo izquierdo 
#puntos entre angulos pi/2 y + 3pi/2
coords_y = np.linspace(np.pi/2,3*np.pi/2,nq)

for coordenada in coords_y:
    cargas.append((-q,escala1*np.cos(coordenada),escala2*np.sin(coordenada)))

Ex = np.zeros((ny, nx))
Ey = np.zeros((ny, nx))

#Hacemos el loop final donde el campo de cada carga individual se usa para calcular el campo final:
#Por cada carga dentro de la lista de cargas:
for carga in cargas:
    ex, ey = E_puntual(*carga, x=X, y=Y)
    Ex += ex
    Ey += ey
    P_tot += P_puntual(*carga, x=X, y=Y)

fig = plt.figure(figsize=(4,5))

color = np.log(np.hypot(Ex, Ey))
plt.streamplot(x, y, Ex, Ey, color=color, linewidth=0.7, cmap=plt.cm.hot,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

#pintamos los objetos 
for q, posx,posy in cargas:
    if q < 0 :
        plt.scatter(posx,posy,zorder=1, s=90, facecolors='blue' )
    else:
        plt.scatter(posx,posy,zorder=1, s=90, facecolors='red' )

contornos = np.linspace(np.min(P_tot),np.max(P_tot),20)
plt.contour(X, Y, P_tot,contornos, colors='w')
        
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title(r'${\phi(x,y)}$', fontsize=14)
plt.show()

Finalmente, construiremos una última forma de visualizar el potencial y las líneas de campo eléctrico, dado que las últimas imágenes contienen demasiada información. Como el potencial $\phi(x,y)$ es básicamente una imagen, usamos el método $\mathtt{imshow}

plt.figure(figsize=(4,5))

cmap = sns.diverging_palette(255,5, s=105, l=40, n=90, center="dark", as_cmap=True)
plt.imshow(P_tot, extent=(-4, 4, -8, 8), cmap=cmap,aspect='auto')
cbar = plt.colorbar()
cbar.set_label(r'${\phi(x,y)}$',size=14)

plt.streamplot(x, y, Ex, Ey, color=color, linewidth=0.8, cmap=plt.cm.cividis,
              density=1.3, arrowstyle='->', arrowsize=1.5, zorder=0)

plt.ylim(-8,8)
plt.xlim(-4,4)
plt.xlabel(r'${X}$', fontsize=15)
plt.ylabel(r'${Y}$', fontsize=15)
plt.title(r'${\vec{E}(x,y)}$', fontsize=14, color='yellow')
plt.show()

Como siempre, agradecido por su tiempo y atención!

Links a enlaces de referencia:

  1. Learning Scientific Programming with Python
  2. Aeropython
  3. Apuntes de Electrodinamica de G. Rubilar.

La nebulosa oscura LDN1527

Oculta a plena luz visible se encuentra una solitaria nebulosa oscura llamada LDN1527:, una región interestelar de polvo y gas densa y fría que no permite el paso de la luz visible; son objetivos interesantes de estudiar dado los objetos que se pueden refugiar por detrás del material en algunas longuitudes de onda más pequeñas.

Y ya sabemos que el telescopio espacial James Webb (JWST) anda suelto, así que apuntó su avanzada óptica a las coordenadas Ascension Recta y declinación $(RA,Dec) = (69.9708^{\circ},+25.7500^{\circ})$ del hemisferio norte, su cámara infrarroja NIRCAM consiguió obtener información de la luz infrarroja que emitía por detrás del polvo y vaya sorpresa que nos llevamos.

Imagen 1: La vista del JWST de la nebulosa oscura LDN1527. Imagen tomada Galeria del JWST, muestra la escala y las imágenes usadas para la composición.

Una estrella que nace:

En las etapas iniciales de la formación estelar son caóticas: Hay muchos componentes identificables como disco de acreción o el material circundante que se mueven a diferentes velocidades, en constante movimiento y atadas gravitatoriamente al objeto joven del centro. En general las estrellas tampoco nacen aisladas, sino que en ambientes densos y frios, el cual justamente es el caso de LDN1527, por lo tanto, se sospechaba que habría objetos estelares jóvenes (YSOs por sus siglas en inglés) detrás de su material interestelar.

La estructura de LDN1527 es como la de un reloj de arena. En el centro está el objeto estelar jóven, rodeado de un disco de acreción (un disco de polvo y gas que rodea a la protostrella y se encuentra en proceso de caer hacia ella) que obscurece la fuente central en ciertos lugares. Pareciera que el disco se observa “de canto”, o también se dice edge-on, es mas cool.

Como si eso ya no bastara, este YSO posee flujo bipolar, donde el material es expulsado de la protostrella en direcciones contrarias, dada la prescencia de un disco de acreción o un fuerte campo magnético. Hacia arriba y abajo del reloj de arena, se ven filamentos brillantes e iluminados desde el centro, lo que ejecta la materia. La masa expulsada podría llegar a formar nubes de polvo y gas en su camino (Ejemplos de esto son objetos Herbig-Haro (HH) numero 30: HH 30:, el HH 34: o HH 111:. Estos lanzamientos de material enriquecen el ambiente, lo que podría afectar la formación de planetas en el disco protoplanetario alrededor del YSO, interfiriendo en la acumulación de masa.

Hay muy pocas imágenes detalladas de este tipo de objetos. Esta imágen representa muy bien por qué algunas de sus series de tiempo son estocásticas, dada la inmensa cantidad de componentes que forman la medición de su luz.

También, es una linda imagen, y como los datos son publicos, vamos a componer nuestra propia versión :D. Primero, hay que descargar los datos disponibles de LDN1527 tomados con la NIRCAM, que son:

  1. f335m: Filtro de banda “mediana”, sensible a los Hidrocarburos aromáticos policíclicos (o PAH) y al metano CH4.
  2. f444w: Filtro de banda ancha de uso general.
  3. f444w-f470n: Imagen definida entre las restas de las imágenes descritas. Desde la documetanción de los filtros:, el filtro f444w bloquea los filtros estrechos, entre ellos el f470n. En esta longuitud de onda, el filtro f470n es sensible a la presencia de hidrógeno molecular.

Mejor todo en una tabla:

ID tipo filtro longuitud de onda Especialidad
f335m median 3.35 μm PAH, CH4
f444w wide 4.44 μm General
f470n narrow 4.7 μm Hidrogeno molecular

Tenemos entonces que hay tres filtros involucrados en la composición de esta imagen, y en la original (Imagen 1) hay 4, así que quedará un poco diferente, que es algo de lo que queríamos lograr. La siguiente imágen revela cómo se ven las imágenes en escalas de grises antes de ser compuestas a color falso:

Imagen 2: imágenes infrarrojas usadas para componer el color falso. Diferentes imágenes mapean la presencia de variedades de elementos en el complejo sistema de formación estelar.

Nuestro interés es tomar estas imágenes FITS y usarlas para poder componer imágenes de color falso, buscando los parámetros necesarios para visualizar los datos correctamente, y además con un fin estético.

Imagen 3: LDN1527 desde mi punto de vista. Se asignó el canal rojo R $\rightarrow$ f335m, el canal verde G $\rightarrow$ f444w, y el azul B $\rightarrow$ (f444w-f470n).

Ahora sabemos por ejemplo, en qué lugares espefícicamente hay más presencia de PAH, dados los clores que esté pintado. Por ejemplo en la siguiente imagen, la codificación de colores es la siguiente:

  • R $\rightarrow$ f335m
  • G $\rightarrow$ f444w
  • B $\rightarrow$ (f444w-f470n)

Por lo tanto, los tonos rojos de la imagen 3 corresponden a la presencia de PAH y CH4, muy comunes de encontrar en el material expulsado. Los filamentos azules corresponde a la presencia de hidrógeno molecular o H2 que es iluminado por la radiación UV del objeto central. Los otros colores son el resultado de la suma. Interesante y bonito :D

Existen 5 composiciones más, si simbolizamos los canales rgb como (i,j,k) = (0,1,2), podemos formar las siguientes imágenes usanda cada uno de sus órdenes:

(0,1,2) (0,2,1)
(1,0,2) (1,2,0)
(2,0,1) (2,1,0)

¿Cuál es su favorita? La mía es la (2,1,0) y la (0,1,2). Si hacen click sobre cada una de las nebulosas, pueden descargar la imágenes ;)

Gracias por leer!

Ajustando una distribución normal

Como el teorema del límite central es tan común en la naturaleza y aparece con tanta frecuencia cuando se levantan grandes cantidades de datos disponibles en nuestra era, que tener una función para ajustar una distribución gaussiana o normal no es una mala idea.

Me explico: supongamos que tenemos un set de datos que es de nuestro interés, y al visualizarlo notamos que podría ser descrito por un perfíl gaussiano. ¿Cómo obtenemos o extraemos los valores de dicha distribución, con el fin de estudiar sus parámetros?

Creemos una distribución artificial y veamos cómo entender dicha distribución, usando un puñado de puntos (100 mediciones) para poder caracterizar la muestra:

from numpy.random import seed
from numpy.random import normal
import matplotlib.pyplot as plt
import numpy as np

#celda magica
%matplotlib inline

#semilla para reproduccion
seed(40)

#generamos datos con media cero, dispersion 1 y de tamaño 100
centro = 0
desviacion = 1

plt.figure(figsize=(6,3))
data = normal(loc=centro, scale=desviacion, size=100)
_,_,_ = plt.hist(data, 18, label='distribucion generada')
plt.legend(loc='best')
plt.show()

Estos datos podrían corresponder a variados fenómenos físicos y/o describir el funcionamiento de algún proceso conocido de antemano. Supongamos que son reales y es imperante entenderlos y caracterizarlo adecuadamente.

Entonces, usaremos la librería scipy, particularmente la función optimize para crear una función que ajuste un perfil gaussiano descrito explicitamente, y los restos (la comparación entre la distribución y el modelo gaussiano) serán minimizados en el sentido de los mínimos cuadrados. Esto será logrado (ajustado o fiteado) usando una función de bondad de ajuste llamada chi cuadrado $\chi ^2$.

Vamos a ello:

def fit_gauss(X,guess,plot=False,large=[6,4],normed=True,xlabel='',Nbins=None,lw=3,fontsize=15,points=False):
    """
    Ajusta una función gaussiana a una distribucion dada.
    Entrada: 
    X: Distribucion.
    guess: Valores iniciales para realizar el ajuste (guess=[mu,sigma,amplitud])
    plot: mostrar el ajuste.
    large: tamaño del plot.
    normed: Si se normaliza el histograma y la funcion.
    
    Salida:
    mu: Valor medio de la gaussiana.
    sigma: desviacion estandar del ajuste.
    amplitud: amplitud de la funcion.
    """
    from scipy import optimize
    import numpy as np
    import matplotlib.pyplot as plt 
    
    #Entendemos la distribución de entrada:
    (altura, bins) = np.histogram(X, bins=Nbins, density=normed)
    hist = np.array([ (bins[i]+bins[i+1])/2. for i in range(len(bins)-1)])
    
    #describimos explicitamente la función gaussiana:
    def gaussian(val, x):
        return (val[2])*np.exp(-0.5*((x - val[0])/val[1])**2)

    #describimos explicitamente la métrica de bondad de ajuste, chi cuadrado (chi2)
    def chi2(val,x,y):
        return (y-gaussian(val, x))**2 #Asumiendo que los errores son 1
    
    x = np.linspace(np.min(X),np.max(X),Nbins)
    xi = np.linspace(np.min(X),np.max(X),1000)

    #realizamos el ajuste usando los minimos cuadrados.
    fit = optimize.leastsq(chi2,guess,args=(hist,altura))

    #obtenemos los parámetros calculados.
    mu = fit[0][0]
    sigma = abs(fit[0][1])
    ampl = abs(fit[0][2])
        
    #agregamos algunas funciones de visualización:
    if plot==True:
        plt.figure(figsize=large)
        if normed == True:
            plt.ylabel(r'${\rm Normalized\ Amplitude }$',fontsize=fontsize)
        else:
            plt.ylabel(r'${\rm Amplitude }$',fontsize=fontsize)

        plt.xlabel(r'${\rm %s }$' %xlabel,fontsize=fontsize)    
        a,b,c=plt.hist(X,Nbins,density=normed, label='distribucion generada')

        if points==True:
            plt.plot(hist,altura,'o--',color='black', label='datos ajustados')

        plt.plot(xi,gaussian(fit[0],xi),'-',color='red',linewidth=lw, label=' modelo gaussiano')

    #listoco
    return mu,sigma,ampl

Para ayudar a la convergencia de nuestro fit, "adivinaremos" los parámetros que podrían llegar a describir la distribución gaussiana, esto es normalmente llamado "guess". Usaremos los promedios de la distribución para obtener el $\mu$, la desviación estandar para obtener el $\sigma$, y la altura es el parámetro más laxo, usualmente lo fijo en 10 sin ningun análisis previo.

#Obtenemos el guess
guess = [np.mean(data), np.std(data),10]

#Aplicamos la función y obtenemos los parámetros de la distribución:
mu,sigma,ampl = fit_gauss(data,guess=guess,plot=True,large=[8,4],normed=True,xlabel='distribucion\ generada',Nbins=18, points=True)

#Definimos el factor de threshold:
factor = 2

#preparamos el gráfico y ploteamos:
plt.axvline(x= mu, color='red',)
plt.axvline(x= mu+factor*sigma)
plt.text( mu+factor*sigma,0.33,'$\mu+2\sigma$',rotation=90,fontsize=20)
plt.axvline(x= mu-factor*sigma)
plt.text( mu-factor*sigma - 0.27 ,0.33,'$\mu-2\sigma$',rotation=90,fontsize=20)
plt.legend(loc='best', fontsize=6)

print('Valor mu original:    ',centro)
print('Valor sigma original: ',desviacion)

print('Valor mu extraido:    ',mu)
print('Valor sigma extraido: ',sigma)
print('Amplitud gaussiana:    ',ampl)
plt.show()
Valor mu original:     0
Valor sigma original:  1
Valor mu extraido:     0.06000778854169946
Valor sigma extraido:  0.9555102876405009
Amplitud gaussiana:     0.3969734189747305

Entonces, desde la función hemos obtenido parámetros similares desde los que fueron creados los datos sintéticos desde una media $\mu=0$ ($\mu_{fit} = 0.06$), con $\sigma=1$ ($\sigma_{fit} = 0.95$), y una altura de 0.39.

Se ve que los puntos negros que describen cada bin por separado, difieren bastante del modelo gaussiado utilizado (en rojo). Aún así, en promedio, los restos se minimizan y el ajuste se logra con cierto éxito. De hecho, es comprobable (¿tarea para el/la revisor/a?) que la distribución de los restos entre los datos y el modelo generan una nueva distribución gaussiana, y es por esto que el fit funciona. De hecho si los restos no fueran gaussianos, me preocuparía mucho el fit, independiente del aspecto que tenga.

Estas funciones se podrían hacer recursivas para caracterizar distribuciones aún más complejas dependiendo de los requerimientos, y por supuesto que, al generar datos con más puntos, la estimación será aun más precisa.

Veamos esto y finalicemos el caso de uso:

#usamos diferentes parámetros de entrada sólo para comprobar la función:

centro = 43245.567
desviacion = 200
Ndatos = 10000

data = normal(loc=centro, scale=desviacion, size=Ndatos)

#adivinamos dónde están, aproximadamente, los valores de ajuste.
guess = [np.mean(data), np.std(data),10]

#Aplicamos la función y obtenemos los parámetros de la distribución:
mu,sigma,ampl = fit_gauss(data,guess=guess,plot=True,large=[8,3],normed=True,xlabel='distribucion\ generada',Nbins=30, points=True)

plt.legend(loc='best')

print('Valor mu original:    ',centro)
print('Valor sigma original: ',desviacion)

print('Valor mu extraido:    ',mu)
print('Valor sigma extraido: ',sigma)
print('Amplitud gaussiana:    ',ampl)

plt.show()
Valor mu original:     43245.567
Valor sigma original:  200
Valor mu extraido:     43245.03269244447
Valor sigma extraido:  199.7365006428819
Amplitud gaussiana:     0.0019831333256458026

Bueno, y si hasta aquí ya no resolviste tu duda, quizá lo que buscabas era una forma de tomar una distribución dada, y luego probar diferentes modelos, cosa que lo haga rápido y sin tantas preguntas, que me lo haga ahora yaaaaaa.

Se pueden usar librerias especializadas, como Fitter, veamos un ejemplo.

from fitter import Fitter
from fitter import get_common_distributions 

plt.figure(figsize = (10,3))
modelos = Fitter(data, distributions=get_common_distributions())

#Ejecutamos el analisis 
modelos.fit()
modelos.summary()
Fitting 10 distributions: 100%|█████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 10.79it/s]
sumsquare_error aic bic kl_div ks_statistic ks_pvalue
norm 4.650659e-07 1717.208623 -237895.850968 inf 0.006754 7.490394e-01
gamma 4.679681e-07 1719.209409 -237824.430144 inf 0.007067 6.973603e-01
cauchy 6.981665e-06 1618.923735 -210807.213759 inf 0.072172 9.670889e-46
rayleigh 2.729263e-05 1513.967525 -197173.921135 inf 0.235971 0.000000e+00
powerlaw 4.852419e-05 1480.130788 -191410.254295 inf 0.322050 0.000000e+00

Vemos que existe un sumario visual de las estadísticas y modelos posibles de generación de una distribución. Los mejores indicadores son una distribución normal, para sorpresa de nadie, pero no se ve porque está debajo del siguiente modelo que ajusta a la perfección: la distribución gamma. Interesante, podríamos indagar en esto, pero lástima que está fuera de mis intereses justo ahora. Pero antes de irnos, asegurémoos de que los parámetros son correctos:

#Usando el método de minimización de la diferencia cuadrada de los errores y obtenemos el mejor modelo
f.get_best(method = 'sumsquare_error')
{'norm': {'loc': 43243.15074834227, 'scale': 201.2707994709006}}

Como vemos, el mejor modelo es la distribución normal (norm), usando una media (loc) de $\mu=43243.15$ [alguna unidad], y un sigma (scale) de $\sigma=201.27$. Me parece suficiente para mis propósitos.

Gracias por leer!.

La primera Nebulosa Planetaria del telescopio James Webb

El telescopio espacial James Webb (JWST para los amiguis) ya está calibrado y apuntando a los objetos más interesantes e icónicos que su predecesor, el telescopio espacial Hubble (lanzado en el 1990) logró identificar y elevó imágenes con un misterioso atractivo hacia la cultura popular. Y las primeras imágenes que ha liberado hace ya algunos días ha establecido ciertas espectativas para los curiosos de estas verdaderas máquinas del tiempo llamadas telescopios.

Mucha gente en redes sociales ha esperado y replicado las imágenes que ha liberado la NASA de las bandas infrarrojas de su nuevo telescopio favorito. Así que me propuse obtener estos nuevos datos y ver qué era posible hacer con ellos. Luego de un rato, llegué al servicio de imágenes de misiones satelitales, desde donde pude obtener algunas de las imágenes de su cámara infrarroja cercana (NIRCAM). Ahora, sólo había que elegir un objetivo.

Una estrella moribunda

Una nebulosa planetaria es una nebulosa de emisión, un objeto astronómico emite luz dada la proximidad de un objeto central evolucionado (Una Enana Blanca) muy caliente, que calienta e ioniza el medio; y así expulsa o empuja las capas posteriores. En general son objetos simétricos alrededor de un eje. Su origen ilustra la muerte de una estrella y el abandono de sus capas más externas para dar paso al enriquecimiento del medio interestelar con elementos más pesados.

Justo como podriamos caracterizar la estructura de NGC 3132, por su estructura en forma de elipse cruzada por otra estructura de forma circular. Para comprender su origen, los elementos que la componen y su dinámica, este objeto ha sido observado por muchos telescopios y en variadas longuitudes de onda.

Con estas imágenes se confirma la naturaleza binaria de este sistema, donde la enana blanca (la estrella moribunda) ha ido expulsando masa de forma periodica mientras su compañera ayuda a mezclar los elementos, y produce simetría (en este caso).

Y es así como el JWST ha apuntado sus instrumentos a este objeto sideral, produciendo así varias imágenes científicas, y aquí hemos considerado tres de estás imágenes, obtenidas usando los filtros de la cámara NIRCam:

Filtros infrarrojos del JWST
Fig 1, - Caracteristicas de los filtros montados en la NIRCam del JWST.
  1. F090w, filtro de banda “mediana” (entre narrow y broad), centrada en los 0,9$\mu$m.
  2. F187n, filtro estrecho centrado en los 1,87$\mu$m.
  3. F212n, filtro estrecho centrado en los 2,12$\mu$m.
Imagen F090w Imagen F187n Imagen F212n

Nuestro interés es tomar estas imágenes FITS y usarlas para poder componer imágenes de color falso. Pero ¿Cuál sería la forma “correcta” de ensamblar una imagen de color? Mirando la Figura 1, podemos ver que en primera instancia, podríamos considerar seguir la lógica de longuitudes de ondas más largas al rojo, mientras que las longuitudes de onda más cortas al azul, lo que da el resultado de la figura 2.

Fig 2, - NGC 3132 usando F212n $\rightarrow$ rojo, F187n $\rightarrow$ verde, F090w $\rightarrow$ azul.

Las capas externas de la estrella moribunda se muestran en rojo, mientras que la emisión verde es gas ionizado por la gran temperatura de la enana blanca central. Por otro lado, los anillos amarillos con forma elíptica representa las áreas donde el gas interno empuja las capas externas de este verdadero cadaver estelar.

Pero en realidad, ésta seria sólo una forma de visualizar estas imágenes para que nosotros, humanos con sentidos limitados, podamos entender los diversos matices y radiación que una compleja fuente de luz como esta puede emitir. Si consideramos que para crear imágenes de colores falsos se necesitan tres mapas de intensidad, podemos generar hasta 6 diferentes combinaciones. Todas válidas cuando se busca lo estético.

Entonces, si simbolizamos los canales rgb como (i,j,k) = (0,1,2), podemos formar las siguientes imágenes usanda cada uno de sus órdenes:

(0,1,2) (0,2,1)
(1,0,2) (1,2,0)
(2,0,1) (2,1,0)

¿Cuál es su favorita? La mía es la (1,2,0) y la (1,0,2). Si hacen click sobre cada una de las nebulosas, pueden descargar la imágenes ;)

Gracias por leer!

Ateo agnostico

¿Saben? El asunto con escribir aquí es, en realidad, una forma de recordar las cosas que opino sobre materias específicas, y luego olvido porque, bueno, yo soy así.

Uno de mis pasatiempos más cuestionables (diría quizá algun psicólogo) es el repasar constantemente las cosas que di como ciertas o les tengo algo de confianza. Esto es necesario cada cierto tiempo porque las personas cambiamos a través de los años, maduramos, y nos damos cuenta que nuestra evaluación de ciertos parámetros necesitan ser repasados en función de la perspectiva que vamos ganando. Además, me interesan tantas cosas en este universo observable que muchas veces es necesario tomar desiciones apresuradas para poder seguir adelante (lo anterior no aplicar a los efectos de la cerveza sobre el cuerpo humano).

Es necesario seguir leyendo, estudiando, conversando, identificando sesgos cognitivos y ver cómo nos afectan de forma parcialmente invisible. Lamentablemente, ésta no es la conclusión de gran parte de la gente que he podido conocer. Mucha gente se queda con lo que le dicen en la infancia y son obligados a decir sostenidamente a lo largo de su vida, sin posibilidad a duda ni explicación alternativa. O si bien pueden superar esta barrera, saltan a la siguiente y quedan ahí, porque la segunda o las siguientes parecieran ser diferentes. Cuando alguien proclama que sabe algo, reniegan de las dudas y las tildan de malas, que la ignorancia es ser débil, vulnerable; siendo muchas veces exactamente lo contrario.

Entonces, acá escribiré un poco sobre por qué me considero Ateismo Agnóstico.

Después de pasar toda mi infancia y parte de mi adolescencia siendo un ferviente cristiano, de aquellos que pasaba su tiempo libre en la casa parroquial de Lorenzo Arenas (Concepción) y Hualpén; creo que era cosa de tiempo solamente para llegar individualmente a la conclusión del ateismo, o que no creo en la existencia de dioses. En ese entonces, mi ateismo provino de la experimentación de la realidad dentro de las iglesias y su desconexión con lo real: Se canta sobre un dios que vive entre nosotros y se manifiesta en todos los aspectos de la vida. Traté de verlo en todas partes, pero su ausencia siempre fue una constante. ¿Acaso era una mala persona por no percibirlo? ¿Cómo un dios tan poderoso puede confiar su existencia a la interpretación humana y no en la evidencia explicita de su existencia? Raro por lo bajo.

Fue complejo, pero confié en la conclusión que había llegado: no existía el dios del que me habían contado. Al principio fue dificil, ya que el cristianismo (y en particular el catolicismo) inserta en los creyentes la culpa como uno de los mecanismos fundamentales para no separarse del “camino de dios”. Se desarrolla la idea del infierno eterno y obviamente uno no quiere eso ni para uno ni para sus cercanos.

Además, esta decisión tampoco solucionaba el vacío existencial, esa angustia de sentir que nuestra existencia no es, potencialmente, fundamental ni destinada a algo. Esto último sólo se logra evitar con estudio y reflexión. Y vaya que es necesaria la reflexión, porque la realidad es aún más abrumadora cuando no crees que exista un dios.

Las proposiciones ateas y agnósticas.

Al conversar con otros autodenominados “ateos” se entendía que, en realidad, muchas veces era sólo otro nicho de apariencias, donde interesaba ir en contra de la iglesia o cualquer cosa que tuviera tintes sacros; o que simplemente les gustaba agredir las creencias de otras personas porque les parecían estúpidas. Esas personas se sentían “superiores” por no creer, pero bastaba cruzar algunas palabras para darse cuenta que no les interesaba comprender la realidad. Afirmar que no existen dioses era, de alguna forma, parte importante de su personalidad rebelde. Lo que siempre me llamó la atención de ellos era ¿cómo afirman algo sin evidencia? ¿Acaso los ateos son igual de dogmáticos que los cristianos?

Pero resulta que no es así, porque el ateismo no es dogmático, no es la declaración o afirmación de que no existen dioses, sino la negación de una creencia injustificada ante la falta de evidencia. ¿Por qué yo debería creer en dios? ¡demuestrenme ustedes que existe, luego les creo! Esto, en el pensamiento crítico, es llamado la carga de la prueba. Parafraseando a Carl Sagan: “Afirmaciones extraordinarias requieren evidencia extraordinaria”.

Por otro lado, están los agnosticos, que son personas que consideran que no puede ser demostrada la existencia o la no-existencia de deidades, ya que no existen evidencia suficiente para concluir alguna de las anteriores. El agnóstico cree que la existencia o no existencia de deidades no puede ser demostrada o no hay suficientes evidencias para confirmar una u otra posición. Ante la pregunta: ¿Sabes si existe dios? Un agnóstico dice: no sé; podrian ser muchos, uno, o no existir. Ésta afirmación les da a los agnosticos fama de despreocupados o de ser algo hippies.

Existen diversas corrientes filosóficas con definiciones bien detalladas sobre qué es el ateismo, el agnosticismo y sobre un sin fin de corrientes alternativas. Pero bajo mi perspectiva, lo fundamental aquí es entender que el saber y el creer son cosas y planos diferentes del conocimiento, y depende de nuestra honestidad intelectual averiguar cuál es el dominio en el que estamos inmersos.

El siguiente gráfico tomado de la página el diferenciador resulta ilustrador:

Cuadro comparativo
Figura 1: Plano cartesiando de las variables (saber,creer). Cuatro posibilidades se abren paso y el universo se complejiza, para variar.

Ambas dimensiones independientes (saber, creer) pueden ser representados en el plano cartesiano y cuantificarse a lo menos 4 zonas diferentes independientes; por ende ser ateo agnóstico es una respuesta plausible ante la vida. Yo me considero Ateo agnóstico porque considero que el ateísmo y el gnosticismo son planos diferentes de un mismo suceso.

Ante la pregunta ¿CREES en dios? Yo digo no, no creo. No veo evidencia de él ni ninguna manifestación en toda la historia, por lo que me considero ateo. Mi ateismo proviene desde la experimentación de la realidad. Ante la pregunta ¿SABES si existe dios? Yo respondo no sé, no tengo cómo comprobar que existe, o que no existe, por lo que me considero agnóstico.

El ateismo es una opinión, pero el agnostiscimo es la conclusión de vivir en un mundo sin fronteras claras, por lo menos para un simple humano.

La estrella Lucy_1

Lucy no tenía nombre, pero merecía uno. La encontré justo dentro de una nube oscura infrarroja (IRDC en inglés), las cuales son regiones muy densas y frías dentro de regiones masivas de formación estelar. Estas nubes son de gran interés dado que porque se piensa que las estrellas masivas (sobre 8 masas solares :o ) se forman en regiones con estas condiciones.

Es posible ver en las imágenes de color falso la densidad de estas nubes dado que esconden las estrellas que están por detrás. Todo el campo está poblado, menos donde están distribuidas estas nubes negras. Hasta las estrellas que están cerca de estas nubes parecen más enrojecidas o extintas de lo normal.

Está localizada a 1 grado de distancia de la nebulosa Trífida, la cual he estudiado bastante ultimamente, y famosa además por aparecer en la portada del disco Islands de la banda británica King Crimson.

En los alrededores de esta estrella existen varias fuentes con indicadores de formación estelar, como Masers. así que tiene sentido pensar que se trata de un objeto joven estelar (YSO en inglés).

Esta estrella está en etapas tempranas de formación, es por eso que dada su gravedad, atraerá a toda la masa circundante y peleará por conseguir más masa del medio que sus posibles hermanas estrellas, en un proceso que se llama acreción competitiva. Pero aún no están claros los mecanismos de formación ni el método con el cual alcanzan su masa final.

09 de Abril del 2010 23 de Septiembre del 2015

En su serie de tiempo se puede apreciar que en el año 2010 aparece muy débil dentro de la IRDC y va subiendo su magnitud aparecen muy lentamente hasta alcanzar el 14.5 [mag], provocando una gran amplitud total $\Delta K_s = 2.416\pm0.092$, digno de una estrella tan alborotada como lo son las fuentes estelares en sus etapas tempranas.

Dado el gradual incremento en el brillo de esta estrella, ha sido clasificada en la categoría fader, del cual imagino que debo hacer una descripción dada la carencia de información sobre esa terminología hasta el momento.

Serie de tiempo de la estrella Lucy

Propiedades básicas conocidas:

  • Coordenadas: Ra=$270.18408^{\circ}$, Dec=$-22.84910^{\circ}$
  • Magnitud promedio en banda $\overline{K}_s=16.361\pm0,033$ [mag]
  • Amplitud fotométrica: $\Delta K_{s}=2.416\pm0.092$ [mag]
  • Tipo asociado: Estrella jóven tipo Fader.

Gracias por leer!!

BRC89v12

Modificación: 10 Mayo 2021.

Ésta fue la fuente estelar que me desconsertó en los primeros momento de investigar el vasto campo de las estrellas variables: BRC89v12. Su nombre es debido a que es la estrella variable número 12 de la Nube de bordes brillantes 89 (Bright-Rimmed Cloud, BRC89), perteneciente a un grupo de Regiones de formación estelar muy conocido, el grupo de la nebulosa de La Laguna.

Las llamadas Bright-Rimmed Clouds son regiones de gas que están asociadas a Regiones de formación estelar (SFR en inglés) masivas y son producidas frecuentemente por frentes de choque producto del viento estelar que proviene de estrellas masivas OB a su alrededor. Otros mecanismos con los que podrían ser producidos es por explosion de Super Novas u otra interacción que produzcan formación estelar dada la compresión del medio interestelar superando los parámetros de Jean.

Esta estrella no era desconocida para la literatura, ya que ha sido estudiada y clasificada como una estrella con líneas de emisión de H$_\alpha$ por allá en el 2002, en un artículo publicado por (Ogura et al. 2002), esto significa que esta estrella sigue en proceso de formación y actualmente está proceso de acreción.

Su amplitud fotométrica es GIGANTE y hay muchas más del mismo tipo alrededor de esta nube, por lo que pensé que encontrarse con este tipo de variabilidad era normal entre las estrella. Ay de mi que pensé eso en el pasado. Pero no, esta variabilidad no es normal, y es una señal clara del proceso llamado Acreción episódica, donde el disco de acreción de la proto-estrella se desprende en trozos y la acreción no es constante. Los cambios drásticos de su brillo suceden cuando el proceso de acreción comienza y se detiene.

10 de Enero del 2010 12 de Marzo del 2015

Serie de tiempo de BRC89v12

Propiedades básicas conocidas:

  • Coordenadas: Ra=$272.378^{\circ}$, Dec=$-24.09553^{\circ}$
  • Magnitud promedio en banda $\overline{K}_s=$14.23 [mag]
  • Amplitud fotométrica: $\Delta K_{s}=$ 3.813 [mag]
  • Tipo asociado: Estrella jóven Eruptiva

Variación de brillo en las estrellas

Cuando logras apartarte de la contaminación lumínica, las estrellas que habitan el cielo son abrumadoras. Muchos, incontables puntos brillantes que ostentan tenues y centellantes colores se posicionan dispersas en el centro galáctico y a lo largo del disco de nuestra Vía Láctea. Luego de algunos días ya será posible reconocer estructuras y constelaciones (la gente dice que hasta escorpiones es posible ver). Hasta que de pronto un puntito particular del cielo cambia su brillo, aumentando o disminuyendo de forma dramática: ¿Qué ha pasado?

Sea lo que sea que haya pasado, la explicación menos probable siempre será que fue un alien, un OVNI o vida extraterrestre. Resulta que el universo esta lleno de luces extrañas que cambian su brillo a lo largo del tiempo, y lo más probable es que nos hayamos topado con una estrella variable, una fuente estelar que cambia su brillo superficial mientras el tiempo pasa. La verdad que son muy comunes, existen de muchos tipos y hoy explicaré cómo podemos llegar a saber tantas cosas sobre estos puntitos luminosos.

Figura 1: Animación que muestra el evidente brillo variable de la candidata a estrella Nova Del2013 (PNVJ20233073+2046041). La imagen muestra dos fotos del mismo campo estelar, antes y después del misterioso episodio.

Bolas de gas en equilibrio quemándose a millones de kilómetros de aquí

Una estrella es una gigantezca esfera de gas, la cual ha alcanzado las condiciones físicas necesarias para que en su centro se desencadenen una serie de reacciones nucleares a través de la fusión nuclear, las cuales liberan y transmiten energía hacia el exterior en forma de radiación electromagnética (luz y calor). Las estrellas poseen su característica forma esférica dado que existe un balance entre dos fuerzas fundamentales: Primero está la gravedad, la cual es generada por la masa de la estrella y actua atrayendo y comprimiendo el gas hacia el centro. Y luego está la presión provocada por el mismo gas, que al estar a una temperatura elevada se expande y genera presión sobre su entorno, como en un globo de aire caliente (asumiendo que han visto uno, personalmente yo no). Cuando una estrella cumple esta condición de equilibrio, se dice que está en equilibrio hidrostático y la estrella adoptará una forma esférica estable. Usando flechas de colores, la figura 2 muestra que la presión se genera del centro hacia afuera, y la gravedad desde la superficie hacia el centro. Ambas llegarán a un punto donde se contrarrestarán hasta alcanzar su LOGICA geometría.

Figura 2: Esquema del balance de la presión con la gravedad. La gravedad tratará de comprimir todo el material hacia el centro del sistema, y la presión tratará de expandirlo, generando esta esfera de gas incandescente.

La estrella del sistema solar

El Sol es nuestra estrella, y es la fuente de energía que sostiene la vida en la tierra. Es el objeto que contiene más masa y produce mayor cantidad de radiación en estas vecindades galácticas. Pero no es sólo por su luz que es reconocido, sino que también por su gravedad, haciendo que polvo, piedras y bolas de gas cercanas giren a su alrededor e interactuen entre ellas para la formación de diferentes estructuras, como planetas o asteroides.

La raza humana tempranamente entendió que el sol jugaba un papel principal en su día a día, siendo elevado a la categoría de dios en gran parte de las culturas originarias, llegando al punto de provocar pánico colectivo cuando su brillo disminuía sin previo aviso, como en un eclipse de luna. Que lata ser un maya y de repente pum, eclipse.

La observación prolongada de la posición relativa del sol en el cielo, y ver cómo afectaba a la naturaleza permitió distinguir las estaciones, y con ello a los cultivos selectivos, los pueblos sedentarios, las grandes ciudades y de un momento a otro la explosión demográfica. Pasando por toda clase de invenciones relevantes y avances científicos para desvanecer la incomodidad de no saber qué era lo que realmente pasaba en el cielo, buscando explicación a ese conjunto de fenómenos regulares que se apreciaban en el movimiento de los planetas, y qué tenían que ver todos esos otros puntos que no parecían para nada soles.

from IPython.lib.display import YouTubeVideo
from datetime import timedelta
start=int(timedelta(hours=0, minutes=0, seconds=2).total_seconds())
YouTubeVideo("wxmSlrI8DGM", start=start, autoplay=0, theme="light", color="red")
Video 1: Pumba le pregunta a Timón qué son las estrellas. Como Timón no sabe, pero le incomoda la ignorancia, decide inventar una historia antes que asumir la verdad.

¿Todas las estrellas son como el sol? (spoilert alert: nope)

Toda la cultura y las aventuras de la humanidad están confinadas en nuestro sistema solar y aún así, siento ser yo el que te lo diga, pero el sol es una estrella promedio, una más del montón de estrellas del grupo de baja masa. Nuestra estrella tiene un radio de 697.000 [Km], a una distancia de 149.597.870.700 [metros] = 1,49$\times$10$^{8}$ [Km], y una masa de 1,99$\times$10$^{30}$ [Kg] (un uno seguido de 30 ceros), casi el 99,8% de la masa de todo nuestro sistema planetario, y aún así, es un cuerpo de baja masa D:

Esta afirmación es el resultado del gran número de estrellas que se han observado a lo largo de los años, tanto dentro de nuestra galaxia como en galaxias vecinas. Hemos comparado todas estas estrellas con el sol y nos hemos dado cuenta que en el universo hay estructuras casi inimaginablemente más grandes. Aún así, la humanidad valora al Sol, y lo usaremos como referencia. Has demostrado ser una estrella tranquila y calurosa, así que te usaremos como una regla cósmica y usaremos como unidad básica:

  1. la Masa Solar $M_{\odot} := 1,99\times10^{30}\ [Kg]$
  2. El Radio Solar $R_{\odot} := 697.000\ [Km]$
  3. la Luminosidad Solar $L_{\odot} := 3,82\times10^{26}\ [Watts]$
  4. La unidad astronómica $[UA]:= 1,49\times10^{8}\ [Km]$

Sabiendo esto, ahora podremos hablar de otras estrellas usando como referencia las proporciones del sol ${M_{\odot}, R_{\odot}, L_{\odot}}$.

Entonces, en esta búsqueda de estudiar y comparar estrellas, se han encontrado toda una gama de diferentes escenarios, y se han definido distintas formas de clasificación, siendo la más importante la clasificación por tipo espectral, donde las estrellas se arreglan en base a sus temperaturas superficiales (o efectivas), y se les asigna una clase de tipo espectral ('O', 'B', 'A', 'F', 'G', 'K', 'M'). Diferentes clases poseerán diferentes temperaturas efectivas, las cuales también tiene relación con el color superficial. Si se preguntan por qué se eligieron esas letras, es porque este tipo de clasificación estelar está basado en la llamada clasificación de Harvard.

La siguiente tabla compara las propiedades de estrellas clasificadas en distintas clases espectrales, usando como base las unidades solares:

Clase Temperatura Color Masa Radio Luminosidad bolométrica
O ≥ 33.000 K azul ≥ 16 M☉ ≥ 6,6 R☉ ≥ 30.000 L☉
B 10.000–33.000 K azul a blanco azulado 2,1–16 M☉ 1,8–6,6 R☉ 25–30.000 L☉
A 7.500–10.000 K blanco 1,4–2,1M☉ 1,4–1,8 R☉ 5–25 L☉
F 6,000–7,500 K blanco amarillento 1,04–1,4 M☉ 1,15–1,4 R☉ 1,5–5 L☉
G 5.200–6,000 K amarillo 0,8–1,04 M☉ 0,96–1,15 R☉ 0,6–1,5 L☉
K 3.700–5.200 K naranja 0,45–0,8 M☉ 0,7–0,96 R☉ 0,08–0,6 L☉
M ≤ 3.700 K rojo ≤ 0,45 M☉ ≤ 0,7 R☉ ≤ 0,08 L☉

Además, a modo de comparación visual, la figura 3 muestra estrellas clasificadas en diferentes tipos espectrales. De forma visual es posible relacionar sus propiedades, como el tamaño, la masa y su color superficial, este último es muy importante para definir la temperatura superficial de la estrella, que se mide en Kelvins, por eso la letra [K] que la acompaña.

Figura 3: Relación entre el color y el tamaño de estrellas de diferentes tipos espectrales. El sol pertenece al tipo G, o también llamada Enana Amarilla.
Por ejemplo, la estrella que ostenta el record de más masiva habita la Nebulosa de la Tarántula, en la Gran Nube de Magallanes, y se llama R136a1, con una masa estimada $M=265M_{\odot}$, o sea que esta estrella tiene 265 veces la masa de nuestro humilde Sol. R136a1 es una de las estrellas 'O', las más grandes, azules, luminosas y de corta vida (algunos millones de años).

¿Cuál sería el tipo espectral del sol? ¿Y dónde estaría posicionado aproximadamente en la figura 3?

Lo interesante de esta clasificación es que si construimos una representación visual (aka, un gráfico) donde ordenamos las estrellas con respecto a su color (de azules a rojas) y luminosidad (más brillantes a menos brillantes), podemos ver que existe una coherencia, la cual nos habla del estado evolutivo de estas estrellas. El siguiente video toma un campo estelar muestra este orden de una manera magistral:

start=int(timedelta(hours=0, minutes=0, seconds=15).total_seconds())
YouTubeVideo('jiSN95WX1NA', start=start, autoplay=0, theme="light", color="red")
Video 2: Un campo estelar muestra muchas estrellas aparentemente no relacionadas entre si, pero cuando las estrellas se ordenan, primero por color y luego por lo brillante, nos damos de cara con el diagrama HR.

El diagrama antes mostrado, se conoce popularmente como el Diagrama de Hertzsprung-Russell o diagrama HR para no gastar tanto lápiz. Hay diferentes versiones del diagrama HR, pero todos apuntan a la caracterización del estado evolutivo de las estrellas en estudio. Dependiendo de las características de las estrellas (principalmente la masa), éstas recorrerán diferentes lugares del diagrama HR.

La figura 4 es muestra un diagrama HR, el cual ilustra en qué posición del diagrama se localizan estrellas con diferentes colores, luminosidades, masas, tipo espectral, y también se estima el tiempo aproximado de vida que poseen cada uno de esos puntitos luminosos. Es posible ver que la mayor parte de las estrellas están distribuidas a lo largo de la llamada Secuencia principal. Esta secuencia se caracteriza por contener estrellas que, en ese momento de sus vidas, están fusionando hidrógeno (el elemento más abundante en las estrellas) para convertirlo en Helio a través de la fusión nuclear, particularmente usando la cadena protón-protón. Justamente aquí, en esta secuencia es donde vive nuestro Sol, por lo que se puede deducir que hay muchas, muchísimias estrellas similares a nuestra querida bola nuclear.

Figura 4: Diagrama Hertzsprung-Russell comparando los parámetros físicos de estrellas. Las estrellas han sido ordenadas en Temperatura en el eje horizonral, y por su brillo en el eje vertical.

Las estrellas cambian a través del tiempo

Conforme pasa el tiempo, las estrellas van evolucionando y moviéndose por el diagrama HR. Esto implica que sufrirán diferentes procesos físicos que provocarán cambios en sus propiedades (cambios de temperatura, tamaño, luminosidad, pérdida de masa, etc) mientras se aproxima su muerte. Cuando una estrella particular sufre estos cambios, es donde se puede romper la condición de equilibrio hidrostático, haciendo que las estrellas puedan hacer visibles sus inestabilidades a través del cámbio de su brillo. Una de las grandes misiones de la astronomía del siglo XXI es caracterizar los cambios de brillo que pueden sufrir mientras las estrellas se mueven por el diagrama HR, para así poder entender qué le pasa.

Supongamos que cada uno tiene a disposición un telescopio para explorar el cielo. Si en vez de observar directamente con él, montamos una cámara fotográfica, podríamos tomar susesivas fotos a lo largo del cielo y unirlas para construir un mapa nocturno, o también se podrían tomar muchas fotos de una misma región celeste y ver cómo las fuentes luminosas se comportan a través del tiempo. Al comparar esas imágenes, es posible que veamos fuentes que cambien su luminosidad, de manera regular, irregular o que sencillamente que aparezcan y desaparezcan.

A modo de ejemplo, en la figura 5 se muestra un campo estelar que ha sido observado en 4 oportunidades diferentes. Dentro del círculo rojo se señala una estrella que cambia su brillo.

Figura 5: Ejemplo de un mismo campo estelar observado en diferentes fechas (épocas). En el círculo rojo del centro se muestra una fuente que cambia su brillo a lo largo del tiempo. Las imágenes fueron tomadas con el telescopio VISTA, ubicado en Paranal. Archivo personal (siempre quise escribir esto).

¿Qué le pasa a esta estrella? Imposible saberlo sin información adicional. Pero partamos simplificando el problema con una pregunta fundamental: ¿Es normal que la luminosidad de las fuentes astronómicas cambie a lo largo del tiempo? Para tener una pista, podemos examinar nuestra estrella más cercana, y ver si sufre de algún tipo de cambio de luminosidad, que no sea provocado por un eclipse.

De nuevo el sol: ¿una estrella variable?

El sol no es una bola de gas tan estable como nosotros la percibimos. Está muy bien documentado que en la superficie del sol aparecen manchas oscuras o manchas solares con regularidad, que obecede el llamado ciclo solar. Este ciclo se caracteriza por tener una duración de alrededor de 11 años, donde las manchas solares aparecen progresivamente, alcanzando un número máximo en la superficie y luego desaparecen, comenzando nuevamente el ciclo. Esta aparición/desaparición de manchas está asociado a la variación del campo magnético de nuestra estrella.

Contraintuitivamente, se conoce que el máximo de brillo del sol aparece cuando el número de manchas es máximo. Y es mínimo cuando desaparecen casi por completo. Esa variación de intensidad, medida en energía emitida por superficie ([Watts/metro cuadrado]) sin embargo, es de tan sólo un 0.1% (1365,5-1367 $[W / m^2]$, en relación a la constante solar $K=1366\ [W / m^2]$) por lo que la variación producida por las manchas es casi despreciable. La figura 6 muestra la evolución de la superficie de nuestro sol a lo largo de 11 años.

Figura 6: El ciclo solar muestra la evolución de las manchas solares a lo largo de los años.

Además, nuestra querida bola de gas incandescente es la protagonista de diferentes eventos eruptivos y explosiones que emanan grandes cantidades de materia al espacio circundante. Gran parte de estos eventos suceden en las regiones activas asociadas a manchas solares, donde emergen intensos campos magnéticos de la superficie del Sol, eyectando masa coronal. Estas fulguraciones solares tiene una escala de tiempo muy cortas (astronómicamente hablando) de tan solo minutos. En el siguiente video, es posible ver un evento eruptivo en nuestro sol.

start=int(timedelta(hours=0, minutes=0, seconds=27).total_seconds())
YouTubeVideo('HFT7ATLQQx8', start=start, autoplay=0, theme="light", color="red")
Video 3: Un timelapse del sol muestra la magnitud que éstas repentinas erupciones pueden tener.

Las escala de distancias y la detección de la variabilidad

Todas esas manchas solares sólo modificaron la luminosidad del sol en un 0.1%. Y la mala noticia es que este mísero porcentaje sólo es detectable porque nosotros estamos cerca del sol. Recordemos que nosotros sólo a 149.597.870.700 metros = 1,49$\times$10$^{8}$Kilometros = 1 UA. Alfa Centauri, el sistema estelar más cercano, está sólo a unos pasos más allá, a 276.363,5 [UA], y así las distancias van aumentando exponencialmente hasta convertirse en números astronómicos. Ni siquiera es conveniente hablar ya de estas distancias en [UA], para eso se usa los años luz (lys) y el parsec (pc).

Aquí debemos hacer una pausa y pensar qué implica estar lejos de las fuentes. Destaco dos ideas principales:

  1. La variabilidad de una fuente puede deberse a un proceso físico que ocurre en la fuente. ¿Verdad? Algo pasó dentro del sol, y gatilló esos poderosos campos magnéticos. Esta fue la causa del cambio de su brillo.

  2. Por el hecho de estar muy lejos de las fuentes, es muy difícil poder medir con exactitud todos los procesos físicos involucrados.

Consideremos una Galaxia, como por ejemplo las galáxias de los ratones, las cuales se encuentran a una respetable distancia de 89 Megaparsecs $= 2,746\times10^{21} [Km]$ $= 1,83\times10^{13} [UA]$. A esa distancia, nos perderemos gran parte de los procesos estelares, sólo por mencionar algo.

Considerando todos estos aspectos, nuestra premisa será que todas las fuentes estelares son variables, pero si observamos lo suficiente. Es decir, si contamos con equipamiento con resolución y el tiempo necesario para registrar dicha fuente, se podrá caracterizar algún tipo de variación de luminosidad, dejándonos así inferir resultados a partir de dicha medición.

Ya bueno: ¿y cuántas fuentes luminosas variables existen?

A lo largo de la historia, muchos astrónomos, astrónomas e instituciones han observado toda clase de estrellas variables catalogado demasiados tipos como para ser nombrados aquí. Hay unas, por ejemplo, que se llaman estrellas RR Lyrae, las cuales sufren variaciones de brillo extremadamente regulares, y se estima que son estrellas relativamente viejas (). La siguiente imagen muestra cuántas de ellas conviven y centellean en un cúmulo globular.

Figura 7: Estrellas variables tipo RR Lyrae pulsando y cambiando su brillo mientras viven tranquilamente en el cúmulo globular Messier 3. Linda imagen tomada del blog sky&telescope

Cada sub-tipo de estrella variable es un potencial tema de estudio, y donde el dilucidar sus misterios, el mecanismo por el cual sufre estas variaciones y el momento evolutivo que se encuentra son preguntas que aún se discuten y esperamos que pronto se resuelvan dada la ola de datos que se están observando y que se obtendrán con la apertura de la nueva generación de telescopios, como el GMT (Observatorio Las Campanas, región de Atacama) y el ELT (Observatorio Paranal, region de Antofagasta).

Así que mejor consultaremos el arbol de la variabilidad y toda su complejidad :D, de aquí en adelante, usaré árbol para ir hablando de diferentes fuentes que cambian su brillo.

Figura 8: Árbol de la variabilidad", el cual fue sacado de L. Eyer & N. Mowlavi.

¡Gracias por visitar, y hasta entonces!

Los colores de las imágenes astronómicas

La astronomía es sinónimo de imágenes asombrosas y siderales, literalmente fuera de este mundo. Composiciones a todo color que nos recuerdan que el universo está lleno de estructuras increibles, y conduce a la reflexión sobre nuestra realidad así como también del lugar que nos corresponde en el universo conocido. El correcto análisis de estas imágenes nos permite extraer información crítica desde la luz que emiten esos puntitos brillantes que habitan el cielo. A través de la física y sus artilugios matemáticos somos capaces de leer la luz entre lineas, para así comprender los secretos de quienes producen esta radiación: estrellas, galaxias, sus grupos...además de burbujas y marañas de gas y polvo, como las piedras que las orbitan.

La estética de la astronomía explica a sus multitudinarios y curiosos seguidores, despertando una de las dudas más comunes: ¿los colores de las imágenes son reales? ¿o son parte del malvado fotochop de la NASA con el fin de controlar nuestra vida?. Colorear imágenes es un proceso bien conocido, teniendo bases en el proceso biológico de cómo los humanos percibimos el color y cómo se entiende esta información de forma digital. Desde esta premisa, en las siguiente líneas haré el esfuerzo de unir todos estos cabos, cómo (des)componer una imagen y mostrales la forma de colorear una imagen astronómica.

El ojito humano y el color RGB.

El ojo humano es el resultado de millones de años de evolución en los cuales su sistema óptico se adaptó a la luz del Sol, nuestra bola de gas favorita. Este sistema óptico recibe y canaliza la luz hasta unas celulas especializadas fotosensibles, llamadas conos y bastones. Según wikipedia Los bastones se activan en condiciones de baja luminosidad. Los conos, por su lado, se ven estimulados en entornos con mayor iluminación y nuestros ojos están poblados por tres variedades diferentes: conos rojos, verdes y azules; sensibles a la luz visible con la cual se apellidan.

Esta sensibilidad particular a ciertos colores no es (taan) antojadiza, pasa que el sol emite muchos tipos de luz, pero la radiación que alcanza la tierra con mayor intensidad contiene estos colores, y a esto se le llama *espectro visible*, luz visible, o simplemente luz. Pero hay muchas otras variedades de luz las cuales son representadas en el rango electromagnético, que va desde las ondas de radio a los rayos gamma. Pasó que el sol emite mucha luz en el rango visible, el ojo humano se adaptó a esta radiación lo largo de su existencia y por eso vemos los colores del arcoiris. Esta es una idea muy poderosa, que nos lleva a pensar cómo se desarrollarían los detectores de radiacion (a.k.a. ojos) de seres que podrían habitan planetas con estrellas que emiten diferente luz, o también como la inexistencia de luz hace que no se desarrollen tales detectores. La siguente imágen muestra el rango electromagénico y su comparación de la luz que existe versus la luz que podemos observar, la luz visible.

Cuando la luz de una fuente luminosa incide sobre un objeto, absorbe ciertos colores y refleja otros. Es esa luz que hace rebotar un cierto objeto la que alcanza nuestros ojos y activa los diferentes conos en proporciones establecidas por los nervios ópticos, lo que nuestro cerebro interpreta como "un color". Simplificando todo, nuestro cerebro tiene 3 colores básicos y todas sus posibles proporciones para colorear nuestra realidad: rojo, verde, azul y sus conocidos mundialmente como RGB (del acrónimo inglés Red, Green, Blue). Estos colores clásicamente se conocen como colores primarios, ya que a partir de esta triada es posible obtener por completo el rango de colores del arcoiris.

Y ya que estamos aquí, es interesante señalar que de hecho vemos aún más colores que los que viven en la luz visible. El color Magenta es un claro ejemplo de esto, ya que no existe luz de este color con una longuitud de onda asociada en el mundo real. Esto significa que este color existe solo en nuestros cerebros, y es la interpretación de la superposición de dos diferentes longuitudes de onda de luz incidente. El siguiente video retrata de mejor manera lo que acabo de explicar:

from IPython.lib.display import YouTubeVideo
from datetime import timedelta
start=int(timedelta(hours=0, minutes=1, seconds=9).total_seconds())
YouTubeVideo("s4I6zosOqpo", start=start, autoplay=0, theme="light", color="red")

Un mundo lleno de imágenes

Las imágenes son importantisimas en el día a día y ya son de uso cotidiano, al punto que ya no es necesario cuestionarse qué son en realidad y cómo pueden llegar a usarse para determinar misterios. Tan exitoso ha sido la integración de las imágenes a nuestro vertiginoso estilo de vida que muchas personas ignoran el hecho que son sólo un gran arreglo de números interpratados para que se parezcan lo más posible a lo que nosotros vemos: un instante congelado en el tiempo.

Las primeras imágenes se remontan al año 1839 gracias al daguerrotipo, el cual consistía en placas de cobre con películas de plata, que las convierte una superficie fotosensible, colectora de luz. Antes de esto había que ser buen dibujante para registrar los relieves y cráteres de la luna como hizo Galileo. Los métodos fotosensibles fueron perfecionandose a lo largo del tiempo, pasando por muchos formatos a lo largo de las décadas, como La placa fotográfica y cintas magnéticas. Hasta 1969, año en el que se desarrollaron los detectores electrónicos fotosensibles CCDs que cada uno de nosotros tiene en su teléfono, y que el 2009 (¡luego de 40 años!) les dio el novel de física a sus creadores Willard Boyle y George E. Smith.. Fue aquí donde se introdujo y popularizó el pixel como la undad básica de una imagen digital. Cada imagen, fotografía o contenido gráfico digital está hecho de pixeles, y de forma similar a los conos de nuestros ojos, cada uno de estos pixeles contiene 3 canales de color: rojo, verde y azul (o RGB). Combinando las intensidades de estos diferentes colores cada pixel puede motrar toda la gama de colores posibles, emulando así la lógica del ojo humano y creando la transición análogo/digital de la imagen.

En términos computacionales, podremos entender una imagen como un cubo de datos de (Pixeles$_{alto}\times$ Pixeles$_{largo}\times 3$). Para entrar un poco más en detalle y hagamos una biopsia a una imagen, usaremos el lenguaje de programación Python en su versión 3, que ya estamos usando pero no te diste ni cuenta. Para que funcione como corresponde, es necesario importar las funcionalidades básicas y librerías con las cuales visualizaremos todo:

#importamos librerias y cositas utiles
%matplotlib inline
import numpy as np
from matplotlib.pyplot import imread
from scipy.misc import *
from scipy import ndimage
import matplotlib.pyplot as plt
from PIL import Image
#definimos algunos parametros:
Dh = (6,4.5)
fz=12

Con todo esto ya funcionando, leeremos una imagen de la estructura de una nube; imagen que fue capturada mientras el sol se estaba poniendo, dándole su color rojizo:

plt.figure(figsize=Dh)
Nubes = imread('IMG_9164.JPG')

#Miramos las dimensiones de la imagen:
dimensiones = Nubes.shape
print("Dimensiones de la imagen:")
print("(alto, largo, canales) =",dimensiones)

plt.imshow(Nubes)
plt.xlabel('pixeles',size=12)
plt.ylabel('pixeles',size=12)
plt.show()
Dimensiones de la imagen:
(alto, largo, canales) = (2848, 4272, 3)

La información de las dimensiones arriba desplegada nos dice que la imagen tiene 2848 pixeles de alto, 4248 pixeles de largo y que está compuesta por tres arreglos de datos, que son los canales de color; cada uno de estos canales posee las mismas dimensiones antes estipuladas. Es así que la imagen desplegada, para cada valor Nubes[x,y] existen 3 valores de rojo, verde, y azul, los cuales en conjunto muestran el color. En el caso anterior supongo que el color rojo domina dadas las virtudes del arrebol de la tarde. Pero no nos quedemos en supuestos y veamos la contribución de cada canal en el color de nuestra nubecita roja. Seleccionaremos todas las filas de pixeles, y 900 columnas en la parte central de la imagen, así nuestra nueva imagen Nubecita[x,y] tendrá 2848x900 pixeles y sus 3 canales RGB. Seleccionaremos cada canal de color por separado para así visualizar la contribución de cada uno de estos colores ejerce en la imagen "Original":

#Separamos cada canal 0,1 y 2 de forma individual desde subImagen

Nubecita = Nubes[:,2000:2900]

dimensiones = Nubecita.shape
print("Dimensiones de la imagen:")
print("(alto, largo, canales) =",dimensiones)

r = Nubecita[:,:,0] #Canal rojo
g = Nubecita[:,:,1] #Canal verde
b = Nubecita[:,:,2] #Canal azul

f,ejes = plt.subplots(1,4,figsize=Dh,sharey=True)
ejes[0].imshow(Nubecita)
ejes[0].set_title("Nubecita")

ejes[1].imshow(r)
ejes[1].set_title("canal rojo R")

ejes[2].imshow(g)
ejes[2].set_title("canal verde G")

ejes[3].imshow(b)
ejes[3].set_title("canal azul B")
plt.tight_layout()
plt.savefig("Ver_canales.png", dpi=300)
plt.show()
Dimensiones de la imagen:
(alto, largo, canales) = (2848, 900, 3)

En el esquema anterior, las imágenes de cada canal están "coloreadas falsamente", esto quiere decir que sus colores representan un código y una escala para que podamos distinguir sus contribuciones (en este caso sería en las partes...¿amarillas, verdes?, lo más brillante), o donde no la hay (las partes azules y oscuras). Normalmente estas imágenes se les representa en escala de grises, pero bueno, ese era el color por defecto, ná que hacerle ¯\_(ツ)_/¯.

Ahora, podemos ver cuánto aporta a la imagen cada canal RGB de forma individual. Es fácil darse cuenta que la contribución del canal rojo R está en todas partes, domina las estructuras y los valores de la imagen Nubecita. Por otro lado, el canal azul mayoritariamente no aporta, y solo está presente en la parte central, donde casi no hay nubes y el cielo está de fondo. Desde aquí debo destacar dos aspectos:

  1. Desde la correcta suma de las imágenes R+G+B es posible obtener la imagen Nubecita de vuelta.
  2. Las imágenes de canal son ejemplos perfectos de una imagen producida por un "filtro optico", que muestra la contribución de luz en un rango definido.
  3. Hacer listas es mi pasión.

Una propiedad fundamental que se desprenden de los filtros es que ven cosas diferentes al observar la misma fuente de luz. Por ejemplo si quisieramos describir la forma de la nube imagen nubecita, sería mejor estudiar el canal rojo, ya que es más sensible a la luz que se emite desde las nubes. Por otro lado, podríamos usar el filtro azul para saber dónde no hay nube, por decir algo jajaja, el filtro malo.

Es por eso que una fuente luminosa se estudia en muchos filtos, ya que la cantidad y tipo de luz de cada filtro se pueden usar para resaltar distintos elementos de un mismo fenómeno.

¡Ya tenemos nuestras primeras herramientas! ¿Para qué podrían llegar a servir? Bueno, la manipulación de imágenes es una práctica recurrente en el día de hoy y muchas son sus aplicaciones, no solo para hacer memes. Lo importante aquí en mi humilde opinión, es darse cuenta que las imagenes sólo son números en un arreglo de datos dispuestos a ser ordenados como bloques, cual Legos. Entenderlos apropiadamente nos da muchas posibilidades, por ejemplo veamos una imagen de la luna que hice hace un tiempo cuando habia una conjunción con el planeta Júpiter, que se nota como un pequeño punto brillante al lado contrario de la luna y le haremos un corte (o un "Zoom digital" que le llaman a veces) al satélite natural:

plt.figure(figsize=Dh)
Luna = imread('IMG_9206.JPG')
plt.imshow(Luna)
plt.title("Imagen original",size=12)
plt.xlabel('pixeles',size=12)
plt.ylabel('pixeles',size=12)
plt.show()

subImagen = Luna[500:1050,650:1200]
dimensiones = subImagen.shape
print("Dimensiones de la imagen recortada:")
print("(alto, largo, canales) =",dimensiones)
plt.figure(figsize=(6.5,6.5))
plt.imshow(subImagen)
plt.title("Imagen recortada",size=12)
plt.xlabel('pixeles',size=12)
plt.ylabel('pixeles',size=12)
plt.show()
Dimensiones de la imagen recortada:
(alto, largo, canales) = (550, 550, 3)

O podríamos también crear nuevas imágenes a partir de otras. En gran parte de los casos esto será posible sólo si las imágenes a combinar poseen las mismas dimensiones. Si la condición anterios se cumple, podemos llegar y sumar las imágenes diréctamente. Por ejemplo, y sólo por capricho, agregaré otra imagen de la luna en fase menguante, además de rotar la imagen 1 en 180 grados, y sumaremos todo en una gran imagen. No se diga más.

#Leemos la nueva imagen de la luna para componer:
creciente = imread('IMG_7793.JPG')
plt.figure(figsize=Dh)
plt.imshow(creciente)
plt.title("Luna creciente",size=15)
plt.xlabel('pixeles',size=12)
plt.ylabel('pixeles',size=12)
plt.show()

#Rotamos la imagen original de la luna
Luna_rotada180 = Image.fromarray(np.rot90(Luna, 2))

#Sumamos todas las imágenes y componemos:
plt.figure(figsize=Dh)
plt.imshow(Luna+Luna_rotada180+creciente)
plt.title("Luna creciente + Luna1 + Luna1 rotada",size=15)
plt.xlabel('pixeles',size=12)
plt.ylabel('pixeles',size=12)
plt.show()

Bueno, hay algunos detalles de los cuales mejorar en esta composición; como esos puntos blancos sobre la luna creciente que posiblemente están sobre-expuesta dada la combinación de las 3 imagenes. Pero en realidad da igual, programas de edicion de datos como Photoshop o Gimp se especializa en esto y sin tener que saber tanto sobre la composicion, estructura de imágenes, ni de filtros gaussianos, etc.

Pero yo les prometí imágenes astronómicas, además en astronomía/astrofísica, a casi a nadie le importa la luna. Es más, nos cuidamos de su prescensia y apuntamos los telescopios cuando no está para que su terrible luz no opaque los escasos fotones que provienen de nuestras fuentes astronómicas favoritas. Esto es todo lo que tengo que decir con respecto a la luna.

El color de las imágenes astronómicas

Por si no lo sabían, la cantidad de información astronómica disponible en este momento es brutal, onda en el orden de Petabytes de información (1.000.000.000.000.000 bytes) se producen a diario, y en el futuro cercano esta tasa irá al alza, o bueno esa era la proyección antes de la pandemia y la desolación mundial del 2020. Mucha de estas imágenes hecha por telescopios en Tierra y el espacio, como la información que ha sido obtenido a lo largo de su análisis ya es de libre acceso, y algunos sets de datos están especialmente orientados a la divulgación científica, como las históricas imágenes de la Nebulosa del Aguila.

YouTubeVideo("4DoxwB5kWT4", autoplay=0, theme="light", color="red")

Hechas con la cámara WFPC2 montada en el telescopio espacial Hubble, las imágenes alojadas en la página de la NASA muestran los llamados "Pilares de la creación", las cuales componen parte de la nebulosa del Aguila, y son columnas de polvo desde donde la gravedad hace lo suyo y ensambla nuevas estrellas. Ya el hecho de que tenga nombre propio habla de la popularidad e impacto que tuvo esta imágen alrededor del mundo. Formalmente a este tipo de estructuras se les conoce como "pilares moleculares fríos", como también "*trompas de elefante*".

Estas imágenes están hechas usando filtros de banda estrecha (narrow filters), los cuales se encargan de medir la luz emitida por un elemento en particular, el cual emite radiación en una longuitud de onda específica del rango electromagnético. Las imágenes disponibles están en formato FITS, que es el formato por defecto en la astronomía actualmente.

Entonces, las imágenes disponibles para componer los pilares de la creación son:

  1. Filtro estrecho de Oxígeno doblemente ionizado (OIII), medido a 502 nanómetros.
  2. Filtro estrecho de Hidrógeno Alfa (H$_\alpha$), la cual posee $\lambda=656$ nanómetros, por supuesto.
  3. Y por ultimo, filtro estrecho de Azufre ionizado (SII), medido a 673 nanómetros

Los elementos anteriores se encuentran presentes en el medio estelar, y son emitidos por la composición e interacción de nebulosas como la que nos interesa. Entonces, descargaremos las imágenes, las leeremos de la misma forma como lo hicimos hace unos momentos más arriba, y luego usaremos la funcion sqrt disponible en astrobetter para ayudar en la visualización de las imágenes:

#Vamos a leer imágenes fits, así que nos preparamos
from astropy.io import fits

OxigenoIII = fits.getdata("502nmos.fits")
H_alpha    = fits.getdata("656nmos.fits")
AzufreII   = fits.getdata("673nmos.fits")
grados = 270
fz=(6.5,5.8)

plt.figure(figsize=fz)
rotated_img = ndimage.rotate(AzufreII, grados)
plt.title("banda de Azufre II")
plt.imshow(rotated_img, cmap='gray', vmin=0, vmax=120)
cbar = plt.colorbar()
cbar.set_label('cuentas',size=12)
plt.ylabel('pixeles',size=12)
plt.show()

plt.figure(figsize=fz)
rotated_img = ndimage.rotate(H_alpha, grados)
plt.title(r'banda de Hidrogeno $\alpha$')
plt.imshow(rotated_img, cmap='gray', vmin=20, vmax=800)
plt.ylabel('pixeles',size=12)
cbar = plt.colorbar()
cbar.set_label('cuentas',size=12)
plt.show()

plt.figure(figsize=fz)
rotated_img = ndimage.rotate(OxigenoIII, grados)
plt.title("banda de Oxigeno III")
plt.imshow(rotated_img, cmap='gray', vmin=0, vmax=20)
plt.ylabel('pixeles',size=12)
plt.xlabel('pixeles',size=12)
cbar = plt.colorbar()
cbar.set_label('cuentas',size=12)
plt.show()

Es posible ver las diferencias, sin dudas (¿verdad?). Por un lado la imagen de AzufreII remarca mucho más los bordes de las nubes, dado que este elemento se encuentra cuando gases a grandes velocidades colisionan. Por otro lado el OxigenoIII y H$_\alpha$ son elementos que se emiten y mapean la materia que está en nuestra querida nebulosa. El OxigenoIII también se ve difuso y marca mucho la absorción de dos de los tres pilares.

Ahora ¿Podemos crear una imágen con estas tres imágenes? Por supuesto, pero será una IMAGEN DE COLOR FALSO. Lo que quiere decir que imágenes realizadas con filtros que no tienen que ver con un color en sí, serán asignados al canal de color para que nuestros ojos puedan entender sus caracteristicas y complejas composiciones fuera de nuestro rango de visión.

Con esto en mente, usaremos python para crear un cubo de datos, y asignaremos cada imagen de filtro estrecho a un canal de color RGB: rojo al mapeo del AzufreII, verde para la emisión de Hidrógeno alfa y el canal azul será para la luz del Oxígeno doblemente ionizado. Con esto, podemos obtener la siguiente imagen.

#Creamos el cubo de datos a la fuerza
img = np.zeros((AzufreII.shape[0], AzufreII.shape[1], 3), dtype=float)
#Asignamos cada filtro a un canal: 
#Silicio al rojo:
img[:,:,0] = sqrt(AzufreII,  scale_min=0, scale_max=180)
#Hidrógeno al verde:
img[:,:,1] = sqrt(H_alpha,    scale_min=0, scale_max=1200)
#Oxígeno al azul:
img[:,:,2] = sqrt(OxigenoIII, scale_min=0, scale_max=120)

plt.figure(figsize=fz)
rotated_img = ndimage.rotate(img, grados)
plt.imshow(rotated_img)
plt.title(r'{rojo$\rightarrow$SII,  verde$\rightarrow$H$_\alpha$,  Azul$\rightarrow$OIII}')
plt.ylabel('pixeles',size=12)
plt.xlabel('pixeles',size=12)
plt.show()

Exito!! Estoy contento porque esta es la primera imángen de color falso que compongo :'). Se ve un poco más opaca que la oficial, habría que espejarla con respecto al eje y también, pero estoy conforme. Ahora sabemos cómo los diferentes elementos químicos presentes en los medios interestelares son representados a través de los colores, dándonos las hermosas y abstractas composiciones que el universo tiene para presentarnos.

Ahora, en esos canales de colores es posible poner cualquier imagen hecha con un filtro o escala de grises. Si esto de las bandas aún es un poco confuso, Javiera de Startres lo explica mucho mejor que yo. En su ejemplo, nuestra imagen compuesta correspondería a una imagen realzada.

start=int(timedelta(hours=0, minutes=3, seconds=4).total_seconds())
YouTubeVideo("YZDJ-K6FiuI", start=start, autoplay=0, theme="light", color="red")

Todo un universo por componer

Cada una de las imágenes a color que muestra la astronomía nos detalla diferentes aspectos de la realidad, muestra elementos complejos que afloran en el centro de las estrellas y emiten los destellos de procesos físicos que pueden llegar a ocurrir en estos ambientes. Cada color puede ser usado para mapear estos efectos, para colorear escalas útiles con el fin de cuantificar interacciones en el medio interestelar; o en general destacar un aspecto diferente de alguna fuente de información en dos dimensiones. Por ejemplo, la siguiente imagen muestra los pilares de la creación (izquierda) compuesta de forma muy similar a cómo nosotros lo hicimos, y a la derecha está compuesta con imágenes de luz infrarroja.

La diferencia es innegable. Ambas conservan la emisión en los bordes de las estructuras, pero la imagen infrarroja muestra incontables estrellas (los puntos brillantes) ¿Por qué? El polvo y las nubes de gas en bajas concentraciones son prácticamente invisibles para la luz infrarroja, por lo que las imágenes hechas en estas bandas nos muestran la luz de estrellas y estructuras escondidas detrás del polvo interestelar, demostrando uno de los grandes problemas de la astronomía: La extinción de la luz.

En mi caso, yo uso imágenes en el rango infrarrojo para así estudiar estrellas detrás de las nubes de polvo que existen en nuestra galaxia: La vía Láctea. El telescopio VISTA vive en el observatorio Paranal, en Antofagasta, y va por la vida recolectando luz infrarroja, invisible para nosotros pero no para la física. Para esto, tomaremos tres imágenes hechas con diferentes filtros desde la base de datos VVV para componer una imagen de color falsa de parte de la nebulosa NGC 6334, también conocida como pata de gato, por las estructuras esferoides que construyeron los vientos de las estrellas brillantes de sus centros.

YouTubeVideo("ni5LdzvLY7o", start=start, autoplay=0, theme="light", color="red")

Pero esas son cosas que uno puede ver en las bandas visibles! El infrarrojo nos ofrece todo lo que está detrás de la patita del gato. Los filtros escogidos para esta tarea son el filtro J, el H, y el Ks. Entonces leeremos las imágenes, las miraremos individualmente y le asignaremos colores raros a cada una de ellas para reforzar que estos colores son sólo un código útil.

from astropy.io import fits

#Acomodamos las dimensiones porque siempre falta o sobran píxeles:
J1 = fits.getdata("J.fits")
J = J1[1:,1:]
H1 = fits.getdata("H.fits")
H = H1[1:,:]
KS = fits.getdata("Ks.fits")
Ks = KS[:,2:]

#Separamos cada canal 0,1 y 2 de forma individual
f,ejes = plt.subplots(1,3,figsize=(7,7),sharey=True)
#Esta la pintamos en escala de grises.
ejes[0].imshow(J, cmap='gray', vmin=850, vmax=1000)
ejes[0].set_title("Filtro J")
ejes[0].set_ylabel("número de pixeles", size=14)
#Esta la pintamos con el color por defecto.
ejes[1].imshow(H, vmin=2900, vmax=3100)
ejes[1].set_title("Filtro H")
ejes[1].set_xlabel("número de pixeles", size=18)
#Y esta imagen, la pintamos de rojo.
ejes[2].imshow(Ks, cmap="Reds",  vmin=4200, vmax=4500)
ejes[2].set_title("Filtro Ks")
plt.tight_layout()
plt.show()

Podemos ver algunas estructuras, como así también algunas nubes de polvo y gas que han sido calentadas por las estrellas cercanas a tal materia. Entonces, creamos la imagen de falso color creando el cubo de datos con las tres imágenes anteriores:

img = np.zeros((J.shape[0], J.shape[1], 3), dtype=float)
img[:,:,0] = sqrt(Ks,scale_min=4200, scale_max=4500)
img[:,:,1] = sqrt(H, scale_min=2900, scale_max=3200)
img[:,:,2] = sqrt(J, scale_min=850, scale_max=1000)

plt.figure(figsize=(6,12))
plt.imshow(img, aspect='equal')
plt.title('NGC 6334',size=20)
plt.xlabel('pixeles',size=16)
plt.ylabel('pixeles',size=16)
plt.tight_layout()
plt.show()

Cada uno de los puntitos que vemos es una estrella distinta, y hay incontable número de ellas en una pequeña región del cielo, impactante. Donde está oscuro se localiza las llamadas Nubes oscuras infrarrojas, donde el polvo esta tan concentrado que ni la luz infrarroja puede pasar. Son negras porque no dejan pasar las estrellas que están de fondo, como en todo su alrededor. Las fuentes rojizas representan estrellas que están en su proceso de formación, con unos tiernos cientos de miles de años de vida, y por último, la emisión morado/azulada son nubes que han sido calentadas por sus estrellas calientes a sus alrededores.

Gracias por leerme!