Évolution des étoiles et catalogues accessibles en ligne

Lectures

  • Wikipedia : L'évolution d'une étoile, ou évolution stellaire, désigne l'ensemble des phénomènes allant de la formation à la "mort" d'une étoile. Elle peut être décomposée en plusieurs phases principales dont la formation de l'étoile, son séjour sur la séquence principale et sa phase finale.
  • Cours de l'université de Strasbourg : Un document de 32 pages sur l'évolution stellaire et le diagramme HR. (en français).

Premier catalogue utilisé

Comment aborder ce catalogue avec Python ?

1. Charger les bibliothèques scientifiques nécessaires

In [1]:
import numpy as np
import matplotlib.pyplot as plt
from astropy.modeling import models, fitting
from astroquery.vizier import Vizier
import scipy.optimize
WARNING: WrongDBMModuleWarning: Existing astropy cache is in an unsupported format, either install the appropriate package or use astropy.utils.data.clear_download_cache() to delete the whole cache; db type is dbm.gnu, but the module is not available [astropy.utils.data]

2. Charger le catalogue et lister l'en-tête

In [2]:
catalog = Vizier.get_catalogs('V/50')
print(catalog)
TableList with 2 tables:
	'0:V/50/catalog' with 11 column(s) and 50 row(s) 
	'1:V/50/notes' with 4 column(s) and 50 row(s) 

Noms et type de contenus des deux tables accessibles par ce catalogue.

D'abord le catalogue.

In [3]:
catalog[0].dtype
Out[3]:
dtype([('HR', '<i2'), ('Name', 'S10'), ('HD', '<i4'), ('ADS', 'S5'), ('VarID', 'S9'), ('RAJ2000', 'S10'), ('DEJ2000', 'S9'), ('Vmag', '<f4'), ('B-V', '<f4'), ('SpType', 'S20'), ('NoteFlag', 'S1')])

Ensuite les notes associées aux données précédentes.

In [4]:
catalog[1].dtype
Out[4]:
dtype([('HR', '<i2'), ('Count', '<i2'), ('Category', 'S4'), ('Remark', 'S120')])

3. Informations sur certains champs du premier catalogue

  • Vmag : magnitude visuelle dans le vert (entre 500 et 600 nm) Note (1) : These fields are all blanks for stars removed from the Bright Star Catalogue (see notes).
  • B-V : indice de couleur dans le système UBV. Différence entre la magnitude dans le Bleu (400 à 500 nm) et le vert (500 à 600 nm).
  • SpType : type spectral.

Le type spectral

Lectures de référence

  • L'article destiné aux enfants de 8-13 ans a le grand mérite d'être très clair et de ne pas rebuter le lecteur dès les premières lignes.
  • Une page plus technique mais rédigée en français qui contient en particulier le codes des diverses variantes spectrales. De nombreux tableaux. Probablement à mettre de côté.

Premier parcours dans le catalogue

Première interrogation : à quoi ressemblent les données contenues dans ce catalogue ? Chargeons les cinq premières lignes en sélectionnant trois champs : type spectral, indice de couleur et magnitude visuelle.

In [5]:
cinq = catalog[0]['SpType', 'B-V','Vmag']
cinq[0:5]
Out[5]:
Table length=5
SpTypeB-VVmag
magmag
bytes20float32float32
A1Vn0.076.70
gG91.106.29
K0IIIbCN-0.51.044.61
G5III0.905.51
G5V0.675.96
In [6]:
print(cinq[0:5])
   SpType     B-V   Vmag
              mag   mag 
------------ ----- -----
        A1Vn  0.07  6.70
         gG9  1.10  6.29
K0IIIbCN-0.5  1.04  4.61
       G5III  0.90  5.51
         G5V  0.67  5.96

Remarques :

  • Deux présentations pour les mêmes données.
  • SpType de type string contient 20 caractères et est aligné à droite. Cela a pour conséquence :
    • Que si l'on veut faire un test sur le premier caractère (qui contient la lettre définissant le type principal), on ne pourra le faire par champ[0] : le premier caractère peut être un espace.
    • Dans ce cas, il va falloir éliminer les espaces inutiles par champ.strip().

Exemple d'application : élimination des espaces devant le type spectral de la première ligne.

In [7]:
catalogue= catalog[0]['SpType', 'B-V','Vmag']
premier = catalogue[0][0] # premier champ de la première ligne
premier.strip() # on élimine les espaces inutiles
Out[7]:
'A1Vn'

Exemple de recherche du type spectral particulier

Prenons les dix premières lignes du catalogue et recherchons les étoiles de type G et listons les trois mêmes champs, mais sans les en-têtes.

In [8]:
for i in range(10):
    spectre = catalogue[i]['SpType']
    if 'G' == spectre.strip()[0]:
        print(catalogue[i][0], catalogue[i][1], catalogue[i][2])
G5III 0.9 5.51
G5V 0.67 5.96
G1IV 0.52 5.7

Coup de sonde : type spectral et indice B-V

Les lectures conseillées nous ont appris que :

  • Les étoiles de type O sont très bleues. On pourrait penser que leur indice B-V serait positif.
  • Les étoiles de type G sont jaunes. On pourrait penser que leur indice B-V serait autour de zéro.
  • Les étoiles de type M sont rouges. On pourrait penser que leur indice B-V serait négatif.

Comment vérifier ces affirmations ? Nous allons réaliser la moyenne des valeurs de B-V pour chacun de ces types.

Exemple de code réalisant ce travail

Remarques sur ce code :

  • Il permet de réaliser des moyennes sur les indices de couleur, mais prépare aussi le tracé de diagrammes HR.
  • Il faut marquer les colonnes qui ne contiennent pas d'information. C'est la raison de .filled(np.nan).
  • Il faut ensuite laisser de côté les lignes qui ne contiennent pas les trois éléments. C'est la raison de la fonction non_vide.
  • Trois listes sont constituées (une par type spectral : arrO, arrG, arrM) qui sont ensuite converties en numpy.array. Cela permettra par la suite de tracer un diagramme HR par type spectral.

Remarque : ce site en français m'a aidé.

In [9]:
Vizier.ROW_LIMIT = -1
recup = Vizier.get_catalogs('V/50')[0]
nb = len(recup) # nombre d'enregistrements
# ~ nb = 20
catalog = recup['SpType', 'B-V','Vmag']
autres = 0 # étoiles qui ne sont ni O, ni G, ni M
catalog['B-V'].filled(np.nan)  # une valeur connue dans ...
catalog['Vmag'].filled(np.nan) # ... les colonnes masquées
arrO, arrG, arrM = [], [], []

def non_vide(ligne):
    """ une ligne utilisable contient
        trois éléments non vides """
    if len(ligne[0].strip()) > 0:
        if ligne[1]!= np.nan and ligne[2]!= np.nan:
            return True
        else:
            return False
    else:
        return False

for i in range(nb):
    if non_vide(catalog[i]):
        spectre = catalog[i]['SpType'].strip()
        element = [catalog[i]['B-V'],catalog[i]['Vmag']]
        if 'O' == spectre[0]:
            arrO.append(element)
        elif 'G' == spectre[0]:
            arrG.append(element)
        elif 'M' == spectre[0]:
            arrM.append(element)
        else:
            autres += 1
            
# transformation en numpy.arrays
o = np.array(arrO)            
g = np.array(arrG)
m = np.array(arrM)
# Affichage des moyennes
print("Type O :", np.mean(o,0)[0])
print("Type G :", np.mean(g,0)[0])
print("Type M :", np.mean(m,0)[0])
Type O : 0.007058832
Type G : 0.880135
Type M : 1.6245964
  • Je n'avais pas compris l'ordre B-V. Il faudrait dire :
    • Les étoiles de type O sont très bleues. Leur indice B-V est négatif ou proche de zéro.
    • Les étoiles de type G sont jaunes. Leur indice B-V est positif (> 0.5)
    • Les étoiles de type M sont rouges. Leur indice B-V est positif (> 1.5).

En fait, cela peut se comprendre : dans les étoiles rouges, la part de vert est réduite et, donc bleu - vert tend à augmenter.

Un diagramme couleur/magnitude avec les données du catalogue

  • L'ensemble des étoiles du catalogue est marqué par des points noirs.
  • Les étoiles de type O sont marquées d'un point bleu.
  • Les étoiles de type G sont marquées d'un point jaune.
  • Les étoiles de type M sont marquées d'un point rouge.
In [10]:
tout = recup['B-V','Vmag']

xo = [arrO[i][0] for i in range(len(arrO))]
yo = [arrO[i][1] for i in range(len(arrO))]

xg = [arrG[i][0] for i in range(len(arrG))]
yg = [arrG[i][1] for i in range(len(arrG))]

xm = [arrM[i][0] for i in range(len(arrM))]
ym = [arrM[i][1] for i in range(len(arrM))]

fig = plt.figure(1, figsize=(5,6)) # dimensions du cadre
plt.plot(tout['B-V'], tout['Vmag'], linestyle='none', marker = 'o', c = 'black', markersize = 1)
plt.plot(xo, yo, linestyle='none', marker = 'o', c = 'blue', markersize = 2)
plt.plot(xg, yg, linestyle='none', marker = 'o', c = 'yellow', markersize = 1)
plt.plot(xm, ym, linestyle='none', marker = 'o', c = 'red', markersize = 1)
axes = plt.gca()
axes.set_xlim(-0.5,2.5) # échelle des températures
axes.set_xlabel("Couleur : B-V")
axes.set_ylim(-2, 9)   # échelle des magnitudes
axes.set_ylabel("Magnitudes")
# affiche les points dans l'ordre du diagramme HR
axes.invert_yaxis()

Commentaires sur ce diagramme

  1. Cela ne ressemble pas à un diagramme HR. Pourquoi ? Les magnitudes utilisées sont les magnitudes visuelles apparentes et non pas absolues. La notion de distance n'intervient donc pas et, au lieu de s'étirer de haut en bas, notre représentation est verrouillée entre les magnitudes -2 et 8.

  2. Les types spectraux s'alignent bien sur les indices de couleur. Le graphique ci-dessus montre distinctement trois barres verticales de couleur. Si l'on regarde les moyennes calculées précédemment, la barre bleue s'aligne sur x=0, la jaune autour de 0,9, la rouge autour de 1,6.

Conclusions

  • Ce catalogue permet (sur trois couleurs pour le moment) de montrer la cohérence entre le type spectral et l'indice de couleur.
  • N'ayant pas accès aux magnitudes absolues, nous n'avons pu tracer un vrai diagramme HR.
  • Découverte et expérimentation de certains outils Python.

Il sera utile de refaire ces manipulations avec un catalogue qui fournit la manitude absolue, tel le V/137D (Extended Hipparcos Compilation (XHIP) (Anderson+, 2012))