ptable_ee.py

Created by laigna

Created on March 14, 2026

8.38 KB

Full 118-element visual periodic table with color-coded categories, arrow navigation, detail view with Estonian names, atomic mass, electron shells, state


# Perioodilisustabel EE - NumWorks
# Created by Alvar Laigna - https://alvarlaigna.com
# Nooled:liigu OK:vaata Back:tagasi
from kandinsky import fill_rect as F,draw_string as D
from ion import keydown as K
from time import sleep as Z
SW,SH=320,222
BK=(0,)*3;WH=(255,)*3
BL=(50,110,230);TL=(0,190,190)
YL=(220,200,60);GN=(60,190,60)
DG=(120,)*3

okv=1 if K(4)or K(52) else 0

def okd():
 return K(4)or K(52)

def okp():
 global okv
 d=okd()
 if d and not okv:
  okv=1
  return True
 if not d:okv=0
 return False

def wup():
 while okd():Z(0.02)
 Z(0.12)

# Category colors: 0=Leelism,1=Leel.muld,2=Siirde,3=Muu met,4=Poolmet,5=Mittmet,6=Halogen,7=Vaarisg,8=Lantan,9=Aktin
CC=[(230,80,80),(240,150,50),(255,200,80),(180,180,200),
(140,200,140),(80,200,80),(100,220,220),(160,120,220),
(255,160,140),(255,130,160),(200,200,80)]
# Category names in Estonian
CN="Leelismetall,Leelismuldmetall,Siirdemetall,Muu metall,Poolmetallid,Mittemetall,Halogeenid,Vaarisgaas,Lantanoidid,Aktinoidid,Muu mittemetall".split(",")
# States: 0=Tahke,1=Vedel,2=Gaas,3=Tundmata
SN=("Tahke","Vedel","Gaas","Tundmatu")
# Element data: symbol,mass,category,state,shells
# Stored as compact string, parsed on demand
SY="H,He,Li,Be,B,C,N,O,F,Ne,Na,Mg,Al,Si,P,S,Cl,Ar,K,Ca,Sc,Ti,V,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr,Rb,Sr,Y,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I,Xe,Cs,Ba,La,Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu,Hf,Ta,W,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn,Fr,Ra,Ac,Th,Pa,U,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Lr,Rf,Db,Sg,Bh,Hs,Mt,Ds,Rg,Cn,Nh,Fl,Mc,Lv,Ts,Og".split(",")
NM="Vesinik,Heelium,Liitium,Berullium,Boor,Susinik,Laammastik,Hapnik,Fluor,Neoon,Naatrium,Magneesium,Alumiinium,Raanium,Fosfor,Vaavel,Kloor,Argoon,Kaalium,Kaltsium,Skandium,Titaan,Vanaadium,Kroom,Mangaan,Raud,Koobalt,Nikkel,Vask,Tsink,Gallium,Germaanium,Arseen,Seleen,Broom,Krupton,Rubiidium,Strontsium,Utrium,Tsirkoonium,Nioobium,Molubdeen,Tehneetsium,Ruteenium,Roodium,Pallaadium,Hobe,Kaadmium,Indium,Tina,Antimon,Telluur,Jood,Ksenoon,Tseesium,Baarium,Lantaan,Tseerium,Praseoduum,Neoduum,Promeetium,Samaarium,Euroopium,Gadoliinium,Terbium,Dusprosium,Holmium,Erbium,Tuulium,Uterbium,Luteetsium,Hafnium,Tantaal,Volfram,Reenium,Osmium,Iriidium,Plaatina,Kuld,Elavhobe,Tallium,Plii,Vismut,Poloonium,Astaat,Radoon,Frantsium,Raadium,Aktiinium,Toorium,Protaktiinium,Uraan,Neptuunium,Plutoonium,Ameriitsium,Kuurium,Berkelium,Kalifornium,Einsteinium,Fermium,Mendeleevium,Nobelium,Lavrentsium,Rutherfordium,Dubnium,Seaborgium,Boorium,Hassium,Meitnerium,Darmstadtium,Rontgenium,Kopernitsium,Nihoonium,Flerovium,Moskovium,Livermorium,Tenessiin,Oganessoon".split(",")
# Atomic masses (rounded)
MS="1.008,4.003,6.941,9.012,10.81,12.01,14.01,16.00,19.00,20.18,22.99,24.31,26.98,28.09,30.97,32.07,35.45,39.95,39.10,40.08,44.96,47.87,50.94,52.00,54.94,55.85,58.93,58.69,63.55,65.38,69.72,72.63,74.92,78.97,79.90,83.80,85.47,87.62,88.91,91.22,92.91,95.95,98.00,101.1,102.9,106.4,107.9,112.4,114.8,118.7,121.8,127.6,126.9,131.3,132.9,137.3,138.9,140.1,140.9,144.2,145.0,150.4,152.0,157.3,158.9,162.5,164.9,167.3,168.9,173.0,175.0,178.5,180.9,183.8,186.2,190.2,192.2,195.1,197.0,200.6,204.4,207.2,209.0,209.0,210.0,222.0,223.0,226.0,227.0,232.0,231.0,238.0,237.0,244.0,243.0,247.0,247.0,251.0,252.0,257.0,258.0,259.0,266.0,267.0,268.0,269.0,270.0,269.0,278.0,281.0,282.0,285.0,286.0,289.0,290.0,293.0,294.0,294.0".split(",")
# Category per element (0-10)
CT=[5,7,0,1,4,5,5,5,6,7,0,1,3,4,5,5,6,7,0,1,2,2,2,2,2,2,2,2,2,2,3,4,4,10,6,7,0,1,2,2,2,2,2,2,2,2,2,2,3,3,4,4,6,7,0,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,2,2,2,2,2,2,2,2,3,3,3,4,6,7,0,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,3,3,3,3,6,7]
# State: 0=solid,1=liquid,2=gas,3=unknown
ST=[2,2,0,0,0,0,2,2,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
# Electron shells per element
ES="1,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.8.1,2.8.2,2.8.3,2.8.4,2.8.5,2.8.6,2.8.7,2.8.8,2.8.8.1,2.8.8.2,2.8.9.2,2.8.10.2,2.8.11.2,2.8.13.1,2.8.13.2,2.8.14.2,2.8.15.2,2.8.16.2,2.8.18.1,2.8.18.2,2.8.18.3,2.8.18.4,2.8.18.5,2.8.18.6,2.8.18.7,2.8.18.8,2.8.18.8.1,2.8.18.8.2,2.8.18.9.2,2.8.18.10.2,2.8.18.12.1,2.8.18.13.1,2.8.18.13.2,2.8.18.15.1,2.8.18.16.1,2.8.18.18.0,2.8.18.18.1,2.8.18.18.2,2.8.18.18.3,2.8.18.18.4,2.8.18.18.5,2.8.18.18.6,2.8.18.18.7,2.8.18.18.8,2.8.18.18.8.1,2.8.18.18.8.2,2.8.18.18.9.2,2.8.18.19.9.2,2.8.18.21.8.2,2.8.18.22.8.2,2.8.18.23.8.2,2.8.18.24.8.2,2.8.18.25.8.2,2.8.18.25.9.2,2.8.18.27.8.2,2.8.18.28.8.2,2.8.18.29.8.2,2.8.18.30.8.2,2.8.18.31.8.2,2.8.18.32.8.2,2.8.18.32.9.2,2.8.18.32.10.2,2.8.18.32.11.2,2.8.18.32.12.2,2.8.18.32.13.2,2.8.18.32.14.2,2.8.18.32.15.2,2.8.18.32.17.1,2.8.18.32.18.1,2.8.18.32.18.2,2.8.18.32.18.3,2.8.18.32.18.4,2.8.18.32.18.5,2.8.18.32.18.6,2.8.18.32.18.7,2.8.18.32.18.8,2.8.18.32.18.8.1,2.8.18.32.18.8.2,2.8.18.32.18.9.2,2.8.18.32.18.10.2,2.8.18.32.20.9.2,2.8.18.32.21.9.2,2.8.18.32.22.9.2,2.8.18.32.24.8.2,2.8.18.32.25.8.2,2.8.18.32.25.9.2,2.8.18.32.27.8.2,2.8.18.32.28.8.2,2.8.18.32.29.8.2,2.8.18.32.30.8.2,2.8.18.32.31.8.2,2.8.18.32.32.8.2,2.8.18.32.32.9.2,2.8.18.32.32.10.2,2.8.18.32.32.11.2,2.8.18.32.32.12.2,2.8.18.32.32.13.2,2.8.18.32.32.14.2,2.8.18.32.32.15.2,2.8.18.32.32.16.2,2.8.18.32.32.17.2,2.8.18.32.32.18.2,2.8.18.32.32.18.3,2.8.18.32.32.18.4,2.8.18.32.32.18.5,2.8.18.32.32.18.6,2.8.18.32.32.18.7,2.8.18.32.32.18.8".split(",")
# Grid position: (col,row) for each element
# row0-6=main, row8=lanthanides, row9=actinides
_G=[]
# Row 0: H,He
_G+=[(0,0),(17,0)]
# Row 1: Li-Ne
_G+=[(0,1),(1,1)]+[(c,1) for c in range(12,18)]
# Row 2: Na-Ar
_G+=[(0,2),(1,2)]+[(c,2) for c in range(12,18)]
# Row 3: K-Kr (full)
_G+=[(c,3) for c in range(18)]
# Row 4: Rb-Xe (full)
_G+=[(c,4) for c in range(18)]
# Row 5+8: Cs,Ba, La-Lu(row8), Hf-Rn(row5)
_G+=[(0,5),(1,5)]
_G+=[(3+j,8) for j in range(15)]
_G+=[(3+j,5) for j in range(15)]
# Row 6+9: Fr,Ra, Ac-Lr(row9), Rf-Og(row6)
_G+=[(0,6),(1,6)]
_G+=[(3+j,9) for j in range(15)]
_G+=[(3+j,6) for j in range(15)]
GP=_G
# Build reverse lookup: (col,row)->element index
GR={}
for i in range(118):
 GR[GP[i]]=i

# Grid drawing constants
OX=7;OY=1
CW=17;CH=14

def ypos(r):
 if r<=6:return OY+r*CH
 return OY+7*CH+4+(r-8)*CH

def dcel(i,hl=False):
 c,r=GP[i]
 x=OX+c*CW
 y=ypos(r)
 cl=CC[CT[i]]
 if hl:
  F(x,y,CW,CH,WH)
  F(x+1,y+1,CW-2,CH-2,cl)
 else:
  F(x,y,CW,CH,cl)
 s=SY[i]
 tx=x+1 if len(s)==2 else x+5
 D(s,tx,y+1,BK if not hl else WH,cl)

def dgrid():
 F(0,0,SW,SH,BK)
 for i in range(118):
  dcel(i)
 # Ln/Ac markers
 D("*",OX+2*CW+3,ypos(5)+1,(200,140,120),BK)
 D("**",OX+2*CW+1,ypos(6)+1,(200,110,140),BK)
 D("Ln",OX+3,ypos(8)+1,(200,140,120),BK)
 D("Ac",OX+3,ypos(9)+1,(200,110,140),BK)

def sbar(i):
 F(0,SH-18,SW,18,(20,20,40))
 s=SY[i];n=NM[i];z=str(i+1)
 t=z+". "+s+" - "+n+" ["+CN[CT[i]]+"]"
 if len(t)>38:t=t[:38]
 D(t,4,SH-16,TL,(20,20,40))

def detail(i):
 bg=(20,20,40)
 F(0,0,SW,SH,bg)
 cl=CC[CT[i]]
 # Header box
 F(10,5,SW-20,50,cl)
 z=str(i+1)
 D(z,16,8,BK,cl)
 D(SY[i],16,24,(40,40,40),cl)
 D(NM[i],80,10,BK,cl)
 D(MS[i]+" u",80,30,BK,cl)
 # Info lines
 p=GP[i][1]
 if p>=8:pr=6 if CT[i]==8 else 7
 else:pr=p+1
 g=GP[i][0]+1
 if CT[i] in (8,9):gs="Ln/Ac"
 else:gs=str(g)
 info=[("Aatomnumber",z),("Suumbol",SY[i]),
  ("Nimetus",NM[i]),("Aatommass",MS[i]+" u"),
  ("Periood",str(pr)),("Ruhm",gs),
  ("Kategooria",CN[CT[i]]),("Olek",SN[ST[i]]),
  ("Elektronkihid",ES[i])]
 ly=62
 for lab,val in info:
  D(lab+":",10,ly,TL,bg)
  D(str(val),160,ly,WH,bg)
  ly+=18
 D("Back = tagasi",100,SH-16,DG,bg)
 while True:
  if K(17):
   Z(0.2)
   return
  Z(0.03)

def legend():
 F(0,SH-14,SW,14,BK)

def run():
 cc,cr=0,0
 pi=-1
 dgrid()
 legend()
 while True:
  # Find valid element at cursor
  ei=GR.get((cc,cr),-1)
  # Draw highlight
  if ei>=0:
   if pi>=0 and pi!=ei:
    dcel(pi)
   dcel(ei,True)
   sbar(ei)
   pi=ei
  if okp():
   if ei>=0:
    wup()
    detail(ei)
    dgrid()
    legend()
    if pi>=0:
     dcel(pi,True)
     sbar(pi)
  if K(17):
   Z(0.2)
   F(0,0,SW,SH,BK)
   return
  nc,nr=cc,cr
  if K(0):nc=max(0,cc-1);Z(0.12)
  if K(3):nc=min(17,cc+1);Z(0.12)
  if K(1):
   nr=cr-1
   if nr<0:nr=0
   if nr==7:nr=6
   Z(0.12)
  if K(2):
   nr=cr+1
   if nr>9:nr=9
   if nr==7:nr=8
   Z(0.12)
  if (nc,nr)!=(cc,cr):
   if (nc,nr) in GR:
    cc,cr=nc,nr
   else:
    # Try to find nearest valid cell in new row
    if nr!=cr:
     for d in range(18):
      if (nc+d,nr) in GR:
       cc,cr=nc+d,nr;break
      if (nc-d,nr) in GR:
       cc,cr=nc-d,nr;break
    elif nc!=cc:
     cc,cr=nc,nr
  Z(0.02)

run()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.