Un tableau périodique avec le module Python “mendeleev”

Le module mendeleev fournit une grande quantité de données numériques sur les éléments chimiques (électronégativité, rayon atomique,…).

Je l’ai utilisé pour tracer un tableau périodique personnalisé (avec le module matplotlib pour le graphique) :

Code Python compressé :


La principale différence avec le code présenté dans un précédent article : les données ne sont pas stockées initialement dans un fichier .csv associé.

Vous aurez besoin d’installer le module mendeleev sur votre ordinateur.

Je cherchais à rédiger mon propre code afin d’obtenir un tableau périodique dans lequel je peux modifier moi-même les réglages suivants :

  • affichage optionnel de la masse molaire.
  • affichage de la masse molaire avec un nombre de chiffres significatifs cohérent.
  • noms des éléments en français (ce que ne propose pas le module mendeleev).
  • affichage optionnel des couleurs par bloc.

Vous pourrez donc facilement ajuster ces réglages, dans le code commenté en téléchargement ci-dessus. Quelques commentaires du code :

def chiffSignif(n):#renvoie un nombre n avec 3 chiffres significatifs
    if n<10:
        valeur='{:.2f}'.format(n)
    elif n<100:
        valeur= '{:.1f}'.format(n)
    else:
        valeur= '{:.0f}'.format(n)
    return valeur.replace('.',',')#virgule à la place du point

Cette fonction renvoie un nombre sous forme de chaîne de caractères, avec 3 chiffres significatifs. En effet, je n’ai pas trouvé de fonction native dans Python pour ce résultat. Cette fonction remplace également le point décimal par la virgule.

Une autre fonction affiche la masse molaire avec une seule décimale, plutôt qu’un nombre fixé de chiffres significatifs.

def decimale(n):
    """
    renvoie un nombre avec une décimale, sous forme de chaîne
    de caractère, avec virgule décimale.
    """
    return str(round(n,1)).replace('.', ',')

Réflexions sur le format d’affichage de la masse molaire :

La pratique usuelle au lycée en France consiste à utiliser un nombre fixé de chiffres significatifs pour les résultats. Comme les masses molaires varient de l’unité à plusieurs centaines, cela occasionne un nombre différent de décimales, par exemple “1.01” pour H, et “35.5” pour Cl.

Toutefois, cette méthode est justifiée pour des multiplications/divisions, alors que les masses molaires sont destinées à être additionnées, afin de calculer des masses molaires moléculaires. On peut par conséquent opter pour le choix d’un nombre fixe de décimales, ce qui donnerait par exemple “1.0” pour H et “35.5” pour Cl.

C’est pourquoi j’ai finalement opté pour ce choix. Ce tableau périodique étant destiné à être distribué aux élèves dès la Seconde, ces derniers peuvent se concentrer sur les calculs de masses molaires atomiques sans être déconcentrés par la gestion des chiffres significatifs.


Une confusion légitime peut apparaître entre le nombre de masse et la masse molaire. Je fais afficher de façon optionnelle le nombre de masse de l’isotope naturel le plus abondant, ou du seul nucléide connu, pour les éléments artificiels, conformément à ce que le module mendeleev propose.

noms=['Hydrogène','Hélium','Lithium','Béryllium','Bore','Carbone','Azote','Oxygène',
      'Fluor','Néon','Sodium','Magnésium','Aluminium','Silicium','Phosphore','Soufre',
      'Chlore','Argon','Potassium','Calcium','Scandium','Titane','Vanadium','Chrome',
      'Manganèse','Fer','Cobalt','Nickel','Cuivre','Zinc','Gallium','Germanium',
      'Arsenic','Sélénium','Brome','Krypton','Rubidium','Strontium','Yttrium',
      'Zirconium','Niobium','Molybdène','Technétium','Ruthénium','Rhodium',
      'Palladium','Argent','Cadmium','Indium',
'Étain','Antimoine','Tellure','Iode','Xénon','Césium','Baryum','Lanthane','Cérium',
'Praséodyme','Néodyme','Prométhium','Samarium','Europium','Gadolinium','Terbium',
'Dysprosium','Holmium','Erbium','Thulium','Ytterbium','Lutetium','Hafnium','Tantale',
'Tungstène','Rhénium','Osmium','Iridium','Platine','Or','Mercure','Thallium','Plomb',
'Bismuth','Polonium','Astate','Radon','Francium','Radium','Actinium','Thorium','Protactinium',
'Uranium','Neptunium','Plutonium','Americium','Curium','Berkelium','Californium','Einsteinium',
'Fermium','Mendelevium','Nobelium','Lawrencium','Rutherfordium','Dubnium','Seaborgium','Bohrium',
'Hassium','Meitnerium','Darmstadtium','Roentgenium','Copernicium','Nihonium','Flerovium',
'Moscovium','Livermorium','Tennesse','Oganesson',
]

Cette liste de noms d’éléments en français vient pallier l’impossibilité de traduire en français les noms fournis par le module mendeleev. Je l’ai obtenue par copier-coller depuis un jeu de données obtenu sur www.datastro.eu, que j’ai traduits en français.

En début de code, des variables booléennes sont créées pour personnaliser l’affichage :

blocs=False # True : cases colorées selon les blocs. False : incolores
masses_molaires=True # affichage ou pas
nombre_masse=True # affichage ou pas
legende=True # affichage ou pas

Une boucle parcourt les éléments en remplissant des listes de leurs coordonnées x,y dans le document. Pour éviter que ce calcul ne soit répété inutilement lors de compilations ultérieures, un fichier de tableau (DataFrame, du module Pandas) est créé puis les valeurs sont insérées dans un fichier csv qui apparaîtra dans le dossier du fichier .py. Si le fichier csv n’existe pas (par exemple, lors de la première compilation, il est généré ; sinon ses données sont importées dans un tableau.

À partir des listes de coordonnées établies dans le code ci-dessus, le programme affiche tour à tour, pour chaque élément :

  • la case rectangle (avec une couleur soumise à condition : booléen “blocs”).
  • le symbole
  • le numéro atomique
  • le nom
  • la masse molaire (soumise à condition : booléen “masses_molaires”)
  • le nombre de masse (optionnel également)
  • la légende (optionnel)
fig=plt.figure(figsize=(29.7/2.54,21 /2.54),tight_layout=True,facecolor='slateblue')

Création d’une figure au format A4 (avec 1 pouce = 2.54 cm)

Pour les noms les plus longs, la case n’est pas assez large… Mais je ne voulais pas choisir une taille trop faible. Je crée donc une condition sur la taille de la police pour certains éléments chimiques :

 if N in [91,101,104,110,111,116]:#éléments aux noms longs
        tailleDuNom=6
    else:tailleDuNom=taille_nom

Le remplissage des cases d’une couleur selon le bloc de l’élément est rendu possible par la donnée fournie par le module mendeleev : la commande element(26).block fournit la lettre ‘d’, par exemple. Cependant, le module mendeleev affecte par défaut les éléments 57 et 89 dans le bloc d, et les éléments 71 et 103 dans le bloc f. Puisque mon choix est différent, j’insère une condition particulière pour ces éléments :

def couleur_case(Z):
    """
    Renvoie la couleur de la case.
    """
    elem = element(int(Z))
    if blocs==True:
        if elem.block=='s':
            couleur =c_bloc_s
        elif elem.block=='p':
            couleur =c_bloc_p
        elif int(Z) in [57,89]:couleur = c_bloc_f
        elif int(Z) in [71,103]:couleur = c_bloc_d
        elif elem.block=='d':
            couleur =c_bloc_d
        else : couleur =c_bloc_f
    else: couleur ='lavender'
    return couleur

Enfin, un mot sur la police de caractères : je conseille une police Serif (avec empattements) pour les symboles (risque de confusion entre I majuscule et l minuscule).

J’ai inséré dans le code un réglage optionnel pour utiliser la police LaTeX. Dans ce cas, l’affichage des noms en très petits caractères étant peu esthétique, j’ai fait le choix d’écrire les noms en format sans Serif :

    plt.text(colonne[N-1]+x_offset_nom*a,-ligne[N-1]+y_offset_nom*b,r'\textsf{%s}'%(noms[N-1]),c=c_nom,fontsize=tailleDuNom,ha='center')#nom

Il est facile de modifier ce réglage selon vos préférences.


Tendances dans le tableau périodique

En choisissant une grandeur fournie par le module mendeleev (l’électronégativité, par exemple), et avec l’aide d’un colormap (carte de couleur), on peut visualiser d’un coup d’oeil les tendances dans le tableau périodique :

Le principe d’un colormap est d’associer une gamme de couleurs à une gamme de valeurs. On crée une liste de valeurs d’électronégativités pour l’ensemble des éléments chimiques ; puis on normalise le colormap en associant les valeurs extrêmes (ici, 0 et 4) aux couleurs extrêmes du colormap choisi (ici, de blanc à vert foncé).

Les données atomiques sont à choisir parmi (liste non exhaustive) :
abundance_crust (mg/kg)
abundance_sea (mg/L)
atomic_volume
boiling_point
melting_point
evaporation_heat
fusion_heat
heat_of_formation
ionenergy
is_radioactive (booléen)
lattice_constant
metallic_radius
specific_heat
thermal_conductivity (W/(mK))
vdw_radius

Attention, il faut absolument se référer à la documentation du module mendeleev, car selon la grandeur choisie les données fournies peuvent prendre des formes différentes (flottants, tuples…) ce qui nécessite quelques aménagement pour le code.

Quelques exemples : sélection de l’électronégativité, ou de l’énergie d’ionisation, ou encore de la conductivité thermique.

symbole=[]
grandeur=[]
for N in range(1,Zmax+1):
    symbole.append(element(N).symbol)
    # valeur=element(N).electronegativity('pauling') # CHOIX DE LA GRANDEUR 
    # valeur=element(N).ionenergies[1]#énergie d'ionisation (eV)(Zmax=108)
    valeur=element(N).thermal_conductivity
    if valeur is None:
        valeur=np.nan
    grandeur.append(valeur)

Il arrive qu’aucune valeur ne soit définie (comme l’électronégativité de la plupart des gaz nobles, selon Pauling). Le module renvoie ‘None’, ce qui entraîne une erreur pour la normalisation du colormap ensuite. Il faut alors remplacer ‘None’ par l’indication ‘NaN’, ce que le colormap tolère.

La couleur associée est alors par défaut celle de la valeur la plus faible.

Plus loin dans le code, au moment de tracer les cases colorées, on passe comme couleur la commande c=cmap(norm(grandeur[Z-1])) : ainsi l’association est faite entre la valeur contenue dans grandeur[Z-1] et la couleur.

Dans mon code, j’ai attribuée une couleur gris clair (‘gainsboro’) si la donnée est ‘NaN’.

for Z in range(1,Zmax+1):
    plt.text(colonne[Z-1], -ligne[Z-1], symbole[Z-1], fontsize=taille_symbole, va='center', ha='center')
    plt.text(colonne[Z-1]+x_offset_Z*a,-ligne[Z-1]+y_offset_Z*b,Z,c=c_Z,fontsize=taille_Z,ha='left')#numéro atomique
    plt.text(colonne[Z-1]+x_offset_nom*a,-ligne[Z-1]+y_offset_nom*b,r'\textsf{%s}'%(noms[Z-1]),c=c_nom,fontsize=taille_nom,ha='center')#nom
    if grandeur[Z-1] is np.nan:
        couleur_case='gainsboro'
    else:
        couleur_case=cmap(norm(grandeur[Z-1]))
    rectangle=plt.Rectangle((colonne[Z-1]-0.5*a,-(ligne[Z-1]+0.5*b)),a,b,facecolor=couleur_case,edgecolor='k')#case
    ax1.add_patch(rectangle)

Les valeurs d’électronégativité n’étant pas affichées ici, j’ajoute une ‘colorbar‘ servant de légende pour une lecture approximative de la valeur selon la couleur :

#tracé de la barre de couleurs :
divider = make_axes_locatable(ax1)
cax = divider.append_axes('bottom', size='6%', pad=0.3)
cb=cbar.ColorbarBase(cax, cmap=cmap, norm=norm, orientation='horizontal')

Si vous préférez afficher l’électronégativité, inspirez-vous de la ligne affichant le numéro atomique pour afficher la valeur contenue dans grandeur[Z-1] (en limitant les décimales !).

Le code complet :

Un document PDF reprenant tous ces tableaux :


Le nombre d’isotopes par élément chimique, avec un colormap :

Le code Python :


Ajout juillet 2022 :

Tableau périodique indiquant la configuration électronique des atomes, telle que proposée par le module mendeleev :

Code Python :


Une version plus récente :

Le script Python :


Abondance des éléments dans le corps humain :

Les données sont issues du Handbook of Chemistry and Physics, 83e édition.

Script Python :

Jeux de données utilisés :

Soyez le premier à commenter

Laisser un commentaire