El diagrama de Hertzsprung-Russell es un gráfico de dispersión de estrellas indicando la relación entre las magnitudes absolutas o luminosidades de las estrellas en comparación con sus clasificaciones espectrales o las temperaturas efectivas. El diagrama fue creado alrededor del año 1910 por Ejnar Hertzsprung y Henry Norris Russell y representa un paso importante hacia la comprensión de la evolución estelar o «la forma en que las estrellas pasan por secuencias de cambios dinámicos y radicales a través del tiempo».
El diagrama de Hertzsprung mostraba la luminosidad de las estrellas en función de su color, mientras que el diagrama inicial de Russell mostraba la luminosidad en función del tipo espectral.
Empezamos el programa cargando las librerías necesarias para este ejercicio las cuales son pandas para cargar los datos y matplotlib para la parte de gráficas.
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
from matplotlib.animation import FuncAnimation
Utilizando pandas cargamos los 4 archivos de datos y unimos los 3 archivos que en nuestra gráfica deben ir difuminados de azul a rojo los cuales son ms.csv, giants.txt y supergiants.txt
dwarfs=pd.read_csv('data/dwarfs.csv')
ms=pd.read_csv('data/ms.csv')
giants=pd.read_csv('data/giants.txt',sep=' ')
supergiants=pd.read_csv('data/supergiants.txt',sep=' ')
color = pd.concat([ms,giants,supergiants])
#Ahora si procedemos a graficar estos datos, tenemos que empezar por definir el tamaño de la figura
#con el plt.figure
factor=50
plt.figure(figsize=(15,10))
#Se plotean tanto el DataFrame "color" como "dwarfs", para este primero tenemos que definir los ejes deseados y
#se toma además el valor radius para definir el tamaño de cada uno de los puntos, se pone un borde gris para
#poder observar las estrellas blancas, adicional se tiene que usar la propiedad cmap de el plt.scatter para hacer
#el difuminado de azul-amarillo-rojo pasando el cmap='RdYlBu'
plt.scatter(color['temp'],color['lum'],s=factor*color['radius'],c = color['temp'],cmap='RdYlBu',edgecolors='grey')
plt.scatter(dwarfs['temp'],dwarfs['lum'],s=factor*dwarfs['radius'],c='w',edgecolors='black')
plt.yscale('log')
plt.xscale('log')
plt.ylim(10**(-5),10**8)
plt.xlim(14000,3300)
#Se añaden los nombres de los ejes
plt.xlabel('Temperature (K)',fontsize=17)
plt.ylabel('Luminosity ($L_{sun}$)',fontsize=17)
#Se agregan los textos que hay en la gráfica de referencia
plt.text(5000,10**7.5,'Red Supergiants',fontsize=17)
plt.text(5000,4,'Red Giants',fontsize=17)
plt.text(10500,10**6.5,'Blue Giants',fontsize=17)
plt.text(11000,3,'Main Sequence',fontsize=17)
plt.text(6000,10**-2,'Main Sequence',fontsize=17)
plt.text(9000,10**-2,'White Dwarfs',fontsize=17)
plt.show()
#Iniciamos definiendo los mismos ejes y escalas del punto anterior.
fig = plt.figure(figsize=(15,10))
ax = plt.subplot()
plt.yscale('log')
plt.xscale('log')
plt.ylim(10**(-5),10**8)
plt.xlim(14000,3300)
plt.xlabel('Temperature (K)',fontsize=17)
plt.ylabel('Luminosity ($L_{sun}$)',fontsize=17)
#Declaramos el valor de nuestro plot para iniciar
plot = plt.scatter(color['temp'].iloc[0],
color['lum'].iloc[0],
s=color['radius'].iloc[0],
c = 'r',
edgecolors='k')
#Definimos la función animation que nos entregará nuestro plot secuencialmente
def animation(i):
#Para los primeros 100 valores vamos ploteando los valores en el rango [0:i]
x = color['temp'].iloc[:i]
y = color['lum'].iloc[:i]
size = color['radius'].iloc[:i]*factor
col = color['temp'].iloc[:i]
plot = plt.scatter(x, y, s=size, c=col,cmap='RdYlBu',edgecolors='k')
#Para los valores iguales o mayores a 100 debemos empezar a graficar las estrellas sin color que son las
#white dwarfs por o tanto usamos un condicional para agregarlo
if i>=100:
xd = dwarfs['temp'].iloc[:i-99]
yd = dwarfs['lum'].iloc[:i-99]
sized = dwarfs['radius'].iloc[:i-99]*factor
plot = plt.scatter(xd, yd, s=sized, c='w',edgecolors='k')
#Añadimos las leyendas que van en el interior de la imagen secuencialmente para que aparezcan junto con
#las estrellas que representan
plt.text(6000,10**-2,'Main Sequence',fontsize=17)
if i>60:
plt.text(11000,3,'Main Sequence',fontsize=17)
if i>90:
plt.text(5000,4,'Red Giants',fontsize=17)
if i>95:
plt.text(5000,10**7.5,'Red Supergiants',fontsize=17)
if i>100:
plt.text(10500,10**6.5,'Blue Giants',fontsize=17)
if i>105:
plt.text(9000,10**-2,'White Dwarfs',fontsize=17)
return plot,
#Utilizamos un intervalo de tiempo superior al número de puntos para poder observar la figura un poco una vez
#terminado el gif y que no se reinicie automáticamente
N_points = 130
#Cargamos la animación
anim= FuncAnimation(fig,animation,frames=N_points,interval=100,blit=True)
#Guardamos
anim.save('Hertzsprung-Russell.gif')
#Cerramos
plt.close(fig)
MovieWriter ffmpeg unavailable; trying to use <class 'matplotlib.animation.PillowWriter'> instead.