Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 26/08/2014, à 15:04

melixgaro

[Python] Numéro atomique d'un élément à partir de son nom

Bonjour,

Je cherche à écrire une fonction en python pour déterminer le numéro atomique d'un élément (exemple : 1 pour l'hydrogène) à partir de son nom anglais (Hydrogen) ou son abbrévation symbole (H). J'ai pensé à l'utilisation de deux dictionnaires un pour les noms, un pour les abbrévations. Ça donne ceci


def get_atomic_number(element):

    AbbrIndex = {"H": 1, "He": 2, "Li": 3, "Be": 4, "B": 5, "C": 6, "N": 7, "O": 8, "F": 9, "Ne": 10, "Na": 11, "Mg": 12, "Al": 13, "Si": 14, "P": 15, "S": 16, "Cl": 17, "Ar": 18, "K": 19, "Ca": 20, "Sc": 21, "Ti": 22, "V": 23, "Cr": 24, "Mn": 25, "Fe": 26, "Co": 27, "Ni": 28, "Cu": 29, "Zn": 30, "Ga": 31, "Ge": 32, "As": 33, "Se": 34, "Br": 35, "Kr": 36, "Rb": 37, "Sr": 38, "Y": 39, "Zr": 40, "Nb": 41, "Mo": 42, "Tc": 43, "Ru": 44, "Rh": 45, "Pd": 46, "Ag": 47, "Cd": 48, "In": 49, "Sn": 50, "Sb": 51, "Te": 52, "I": 53, "Xe": 54, "Cs": 55, "Ba": 56, "La": 57, "Ce": 58, "Pr": 59, "Nd": 60, "Pm": 61, "Sm": 62, "Eu": 63, "Gd": 64, "Tb": 65, "Dy": 66, "Ho": 67, "Er": 68, "Tm": 69, "Yb": 70, "Lu": 71, "Hf": 72, "Ta": 73, "W": 74, "Re": 75, "Os": 76, "Ir": 77, "Pt": 78, "Au": 79, "Hg": 80, "Tl": 81, "Pb": 82, "Bi": 83, "Po": 84, "At": 85, "Rn": 86, "Fr": 87, "Ra": 88, "Ac": 89, "Th": 90, "Pa": 91, "U": 92, "Np": 93, "Pu": 94, "Am": 95, "Cm": 96, "Bk": 97, "Cf": 98, "Es": 99, "Fm": 100, "Md": 101, "No": 102, "Lr": 103, "Rf": 104, "Db": 105, "Sg": 106, "Bh": 107, "Hs": 108, "Mt": 109, "Ds": 110, "Rg": 111, "Cn": 112, "Uut": 113, "Fl": 114, "Uup": 115, "Lv": 116, "Uus": 117, "Uuo": 118}
    NameIndex = {"Hydrogen": 1, "Helium": 2, "Lithium": 3, "Beryllium": 4, "Boron": 5, "Carbon": 6, "Nitrogen": 7, "Oxygen": 8, "Fluorine": 9, "Neon": 10, "Sodium": 11, "Magnesium": 12, "Aluminium": 13, "Silicon": 14, "Phosphorus": 15, "Sulfur": 16, "Chlorine": 17, "Argon": 18, "Potassium": 19, "Calcium": 20, "Scandium": 21, "Titanium": 22, "Vanadium": 23, "Chromium": 24, "Manganese": 25, "Iron": 26, "Cobalt": 27, "Nickel": 28, "Copper": 29, "Zinc": 30, "Gallium": 31, "Germanium": 32, "Arsenic": 33, "Selenium": 34, "Bromine": 35, "Krypton": 36, "Rubidium": 37, "Strontium": 38, "Yttrium": 39, "Zirconium": 40, "Niobium": 41, "Molybdenum": 42, "Technetium": 43, "Ruthenium": 44, "Rhodium": 45, "Palladium": 46, "Silver": 47, "Cadmium": 48, "Indium": 49, "Tin": 50, "Antimony": 51, "Tellurium": 52, "Iodine": 53, "Xenon": 54, "Caesium": 55, "Barium": 56, "Lanthanum": 57, "Cerium": 58, "Praseodymium": 59, "Neodymium": 60, "Promethium": 61, "Samarium": 62, "Europium": 63, "Gadolinium": 64, "Terbium": 65, "Dysprosium": 66, "Holmium": 67, "Erbium": 68, "Thulium": 69, "Ytterbium": 70, "Lutetium": 71, "Hafnium": 72, "Tantalum": 73, "Tungsten": 74, "Rhenium": 75, "Osmium": 76, "Iridium": 77, "Platinum": 78, "Gold": 79, "Mercury": 80, "Thallium": 81, "Lead": 82, "Bismuth": 83, "Polonium": 84, "Astatine": 85, "Radon": 86, "Francium": 87, "Radium": 88, "Actinium": 89, "Thorium": 90, "Protactinium": 91, "Uranium": 92, "Neptunium": 93, "Plutonium": 94, "Americium": 95, "Curium": 96, "Berkelium": 97, "Californium": 98, "Einsteinium": 99, "Fermium": 100, "Mendelevium": 101, "Nobelium": 102, "Lawrencium": 103, "Rutherfordium": 104, "Dubnium": 105, "Seaborgium": 106, "Bohrium": 107, "Hassium": 108, "Meitnerium": 109, "Darmstadtium": 110, "Roentgenium": 111, "Copernicium": 112, "Ununtrium": 113, "Flerovium": 114, "Ununpentium": 115, "Livermorium": 116, "Ununseptium": 117, "Ununoctium": 118}

    try:
        return AbbrIndex[element]
    except:
        try:
            return NameIndex[element]
        except:
            print("Unknown element")
            raise

get_atomic_number("Hydrogen")
get_atomic_number("Hf")
get_atomic_number("Hydro")   # Raise exception as expected

Est-ce que l'un de vous à mieux à proposer ? Comment écrire de façon élégante la (les ?) fonction réciproque, c'est-à-dire obtenir le symbole ou (exclusif) le nom à partir du numéro atomique ?

PS : pour éviter les histoires de casse, je remplacerai element par element.capitalize() lors des appels aux dicos.

Dernière modification par melixgaro (Le 26/08/2014, à 20:38)


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#2 Le 26/08/2014, à 16:39

pingouinux

Re : [Python] Numéro atomique d'un élément à partir de son nom

Bonjour,
Pour la fonction get_atomic_number, tu peux éventuellement regrouper les 2 dictionnaires en un seul.
Pour les fonctions réciproques, je me créerais les dictionnaires inverses (à faire une seule fois en dehors des fonctions).
Par exemple

AbbrIndex = {"H": 1, "He": 2, "Li": 3, "Be": 4}
IndexAbbr={}
for k,v in AbbrIndex.items() : IndexAbbr[v]=k

print(IndexAbbr)

Ce qui donne

{1: 'H', 2: 'He', 3: 'Li', 4: 'Be'}

Hors ligne

#3 Le 26/08/2014, à 16:57

melixgaro

Re : [Python] Numéro atomique d'un élément à partir de son nom

à pingouinux :
Oui j'avais pensé à faire un dictionnaire inverse. J'ai posé la question pour savoir si on pouvait avec un seul objet (dictionnaire, tableau ou autre) faire les deux fonctions.

à HP :
Je veux bien faire un objet Atome() avec les propriétés Atome.numero, Atome.nom, Atome.symbole mais comment puis je faire une recherche sur les propriétés ? Comment puis je trouver l'indice de l'objet qui a une propriété nom égal à "Helium" par exemple ?

Merci pour vos contributions en tout cas wink

Dernière modification par melixgaro (Le 26/08/2014, à 20:38)


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#4 Le 26/08/2014, à 17:09

pingouinux

Re : [Python] Numéro atomique d'un élément à partir de son nom

melixgaro a écrit :

J'ai posé la question pour savoir si on pouvait avec un seul objet (dictionnaire, tableau ou autre) faire les deux fonctions.

Oui, c'est tout-à-fait possible. Par exemple

AbbrIndex = {"H": 1, "He": 2, "Li": 3, "Be": 4}

def get_abbr(atomic) :
    for k in AbbrIndex.keys() :
        if AbbrIndex[k]==atomic : return k

print(get_abbr(2))
print(get_abbr(5))

Résultat

He
None

Hors ligne

#5 Le 26/08/2014, à 17:27

melixgaro

Re : [Python] Numéro atomique d'un élément à partir de son nom

à HP :
Je repense à ta proposition de base de donnée stockée dans un fichier JSON. C'est vrai que de grands tabeaux dans un code, c'est pas très joli. D'un autre côté, comme ça ne devrait pas tellement changer, ça n'est pas trop grave et ça vite une opération E/S.

Quoiqu'il en soit, si je veux mettre en œuvre ta proposition, où dois-je placer le fichier de sorte qu'il soit « connu du système » (mes programmes python sont dans le PATH de python, donc accessible de n'importe où par l'interpréteur python) ? Ça va m'obliger à coder un chemin en dur, genre /home/moi/my_python/atoms.json, non ? Ce qui peut être embêtant pour partager la fonction ou le jour où mon architecture est modifiée.


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#6 Le 26/08/2014, à 20:01

tiramiseb

Re : [Python] Numéro atomique d'un élément à partir de son nom

Hors ligne

#7 Le 26/08/2014, à 20:54

melixgaro

Re : [Python] Numéro atomique d'un élément à partir de son nom

Bonsoir,

à tiramiseb :

merci. J'avais trouvé les 2 premiers seulement. Le troisième (chem) propose exactement les fonctions que je veux, mais il ne connaît pas l'intégralité du tableau périodique. Il s'arrête au lanthane (57, La), il en manque quand même un bon paquet ! Les 2 premiers ne paraissaient pas vraiment répondre à mon besoin. À y regarder de plus près, seul periodic semble proposer une fonction de recherche. Mais ça nécessite un import hors bibliothèque standard... En codant moi-même, ça me fait pratiquer un peu plus python, ce qui n'est pas plus mal. wink


PS : Et pour des petits bouts de codes comme ça, je succombe vite au syndrome du pas-inventé-ici (not-invented-here) big_smile


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#8 Le 26/08/2014, à 20:59

tiramiseb

Re : [Python] Numéro atomique d'un élément à partir de son nom

Oui, c'est bien ça le problème, le NIH.

Si le 3me te convient mais qu'il manque juste des données, eh bien forke-le pour inclure toutes les données !

Hors ligne

#9 Le 27/08/2014, à 07:22

nesthib

Re : [Python] Numéro atomique d'un élément à partir de son nom

@melixgaro : ne fais jamais de try/except sans spécifier l'erreur attendue. Dans ton cas tu peux avoir une KeyError, donc spécifie-le, ceci t'évitera des bugs silencieux.

Une petite suggestion, utilise une base de données sqlite :

import sqlite3

# cette partie n'est à exécuter qu'une seule fois pour créer la base de données
elements = [(1, 'Hydrogen', 'H'), (2, 'Helium', 'He'), (3, 'Lithium', 'Li')]

db = sqlite3.connect('/tmp/periodic.db')
c = db2.cursor()

c.execute('CREATE TABLE elements (Id INT, Name TEXT, Symbol TEXT)')
c.executemany('INSERT INTO elements VALUES(?, ?, ?)', elements)
db.commit()
db.close()

# Cette fonction permet de chercher dans la base par nom ou par symbole
def get_elem(text):
    db = sqlite3.connect('periodic.db')
    with db:
        c = db.cursor()
        n = c.execute('SELECT Id from elements WHERE (Symbol is ? OR Name is ?)', (text,)*2).fetchone()
        return n[0] if n else None

La fonction s'utilise de la façon suivante :

>>> get_elem('H')
1
>>> get_elem('Helium')
2
>>> get_elem('Water')
>>>

La base de données te permettra d'ajouter des informations supplémentaires pour chaque élément (dans la table elements ou dans une table séparée) wink


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#10 Le 27/08/2014, à 08:13

Brunod

Re : [Python] Numéro atomique d'un élément à partir de son nom

Un tableau en 3 colonnes : N°, nom, symbole, à consulter avec un grep de ce qui est recherché ne ferait pas l'affaire ?
Edit : pour la casse, plutôt un egrep -i alors.

Dernière modification par Brunod (Le 27/08/2014, à 08:14)


Windows est un système d'exploitation de l'homme par l'ordinateur. Linux, c'est le contraire...
39 pc linux convertis

Hors ligne

#11 Le 27/08/2014, à 08:14

tiramiseb

Re : [Python] Numéro atomique d'un élément à partir de son nom

Et un fork de la bibliothèque qui convient en terme de fonctionnalités mais qui n'a juste pas toutes les infos, c'est mieux ! smile


Surtout qu'en fait j'ai donné le lien vers la version 1.1 alors qu'il existe une version 2.0 :
https://pypi.python.org/pypi/chem/2.0
Celle-ci a peut-être tout...


En tout cas, dans le fichier "element_data.py" de cette version 2.0 je vois bien des éléments au-delà du 57...

Dernière modification par tiramiseb (Le 27/08/2014, à 08:17)

Hors ligne

#12 Le 27/08/2014, à 13:37

melixgaro

Re : [Python] Numéro atomique d'un élément à partir de son nom

à nesthib :

merci pour cette solution très intéressante (et qui me fait découvrir sqlite par le petit bout de la lorgnette wink)

Question : si je te suis bien, j'écris une fois pour toute la base de donnée. Dans ton exemple, tu l'écris dans /tmp. Mais quel est le meilleur endroit pour l'enregistrer sachant que le dossier où sont mes modules python est dans le PATH de python et que je souhaite partager le module ? Avec un chemin de ce genre : ~/.config/mon_module/elements.db ? (en fait plus généralement, quelle est le meilleur chemin pour une base de données qui doit être lue lors de l'import d'un module ?)

à tiramiseb :

ok je vais regarder la v2

En tout cas, merci à chacun pour vos contributions !

Dernière modification par melixgaro (Le 27/08/2014, à 13:38)


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#13 Le 27/08/2014, à 13:47

tiramiseb

Re : [Python] Numéro atomique d'un élément à partir de son nom

à nesthib

NIH... ^_^

Hors ligne

#14 Le 27/08/2014, à 14:22

melixgaro

Re : [Python] Numéro atomique d'un élément à partir de son nom

à tiramiseb :
non, malheureusement pareil pour la v2, pas d'élément pour Z > 57

PS : je comprends ton point de vue sur le NIH, mais comprends aussi que je profite de cet exemple simple pour améliorer mon python wink au début, on commence tous par réécrire les mêmes codes : tour de Hanoï, tri, etc etc


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#15 Le 27/08/2014, à 15:05

tiramiseb

Re : [Python] Numéro atomique d'un élément à partir de son nom

non, malheureusement pareil pour la v2, pas d'élément pour Z > 57

Pourtant dans "element_data.py" il y a :

inv_pro = {1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', 10: 'Ne', 11: 'Na', 12: 'Mg', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', 20: 'Ca', 21: 'Sc', 22: 'Ti', 23: 'V', 24: 'Cr', 25: 'Mn', 26: 'Fe', 27: 'Co', 28: 'Ni', 29: 'Cu', 30: 'Zn', 31: 'Ga', 32: 'Ge', 33: 'As', 34: 'Se', 35: 'Br', 36: 'Kr', 37: 'Rb', 38: 'Sr', 39: 'Y', 40: 'Zr', 41: 'Nb', 42: 'Mo', 43: 'Tc', 45: 'Ru', 46: 'Pd', 47: 'Ag', 48: 'Cd', 49: 'In', 50: 'Sn', 51: 'Sb', 52: 'Te', 53: 'I', 54: 'Xe', 55: 'Cs', 56: 'Ba', 57: 'La', 72: 'Hf', 73: 'Ta', 74: 'W', 75: 'Re', 76: 'Os', 77: 'Ir', 78: 'Pt', 79: 'Au', 80: 'Hg', 81: 'Tl', 82: 'Pb', 83: 'Bi', 84: 'Po', 85: 'At', 86: 'Rn', 87: 'Fr', 88: 'Ra', 89: 'Ac', 104: 'Rf', 105: 'Db', 106: 'Sg', 107: 'Bh', 108: 'Hs', 109: 'Mt'}

Je ne suis pas fort en chimie, ce que je vois c'est que la liste ne contient pas les lanthanides ni les actinides (d'après ce que je vois du tableau périodique)... Maintenant je ne saurais pas expliquer pourquoi...


C'est peut-être pareil dans la version 1.1.

Dernière modification par tiramiseb (Le 27/08/2014, à 15:06)

Hors ligne

#16 Le 27/08/2014, à 15:17

nesthib

Re : [Python] Numéro atomique d'un élément à partir de son nom

@tiramiseb : je n'ai pas dit que je re-coderais si c'était pour mon usage, mais je te rappelle que chacun fait ce qu'il veut, je propose une solution qu'il peut mettre en œuvre pour apprendre wink


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#17 Le 27/08/2014, à 15:19

melixgaro

Re : [Python] Numéro atomique d'un élément à partir de son nom

à tiramiseb :
tu as parfaitement raison !
En fait, pour savoir si c'était complet, j'ai testé avec quelques éléments après le lanthane (europium, uranium...) et, évidemment, je suis tombé dans les deux trous que tu as justement identifiés : les lanthanides et les actinides sont presque tous absents (en fait, il n'y a que le 1er de chaque famille, le La et l'Ac)

PS : j'avais vérifié la liste de la v1 de la même façon... Et effectivement, c'est la même liste : donc toute la table sans les lanthanides et les actinides, soit près de 30 éléments disparus

Dernière modification par melixgaro (Le 27/08/2014, à 15:22)


Linux depuis ~2007. Xubuntu seulement.

Hors ligne

#18 Le 27/08/2014, à 15:29

tiramiseb

Re : [Python] Numéro atomique d'un élément à partir de son nom

Donc plutôt que de tout recoder, tu peux n'ajouter que "près de 30 éléments" au fichier "element_data.py", puis tu n'as plus qu'à partager ce fork...

Hors ligne