#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
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
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
Salut,
Pourquoi réinventer la roue ?
https://pypi.python.org/pypi/periodic
https://pypi.python.org/pypi/periodictable
https://pypi.python.org/pypi/chem/1.1
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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.
PS : Et pour des petits bouts de codes comme ça, je succombe vite au syndrome du pas-inventé-ici (not-invented-here)
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 !
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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)
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde 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 !
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)
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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 )
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... ^_^
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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 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)
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
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
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde 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...
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
Hors ligne