spectrum.py

created by andreanx

created on May 25, 2019

4.99 KB

Draws the emission spectrum and absorption spectrum of the first 8 elements. Use : spectrum(n,a,b,g) with : n for the atomic number, [a;b] for the min and max wavelengths, default is [380;780].


from kandinsky import *
sw,sh,li,ls=320,222,380,780

def draw_vert(x,y1,y2,c):
  for y in range(y1,y2+1):set_pixel(x,y,c)

def f(v,l,m,p):
  for k in range(len(l)-1):
    if v>=abs(l[k]) and v<=abs(l[k+1]):
      if m[k]<0:a,b=l[k+1],l[k]
      else:a,b=l[k],l[k+1]
      return p[k]+abs(m[k]*(v-a)/(a-b))
  return 0

def l2c(l):
  r,g,b=f(l,[380,440,510,580,700,780],[-1,0,1,0,-.7],[0,0,0,1,.3]),f(l,[380,440,490,580,645,780],[0,1,0,-1,0],[0,0,1,0,0]),f(l,[380,420,490,510,780],[.7,0,-1,0],[.3,1,0,0])
  if l<400:r*=b
  return color(round(255*r),round(255*g),round(255*b))

def c2hsv(c):
  try:
    r,g,b=c[0]/255,c[1]/255,c[2]/255
  except:
    b,g,r=((c&31)<<3)/255,((((c>>5)&63)<<2)&255)/255,((((c>>11)&31)<<3)%255)/255
  cs=max(r,g,b)
  d=cs-min(r,g,b)
  return ((cs==r) and ((g-b)/d)%6 or (cs==g) and (b-r)/d+2 or (cs==b) and (r-g)/d+4)/3,d/cs,cs

def hsv2c(h,s,v):
  c=v*s
  x,m,k=c*(1-abs((h%(2/3))*3-1)),v-c,(h*3)//1
  return color(round(255*(m+x*(k%3==1)+c*(k%5==0))),round(255*(m+c*(k==1 or k==2)+x*(k%3==0))),round(255*(m+x*(k%3==2)+c*(k==3 or k==4))))

def rays(n,b):
  a=[655876,721417,786961,983582,1245750,1573482,1704724,1835796,852994,263170,2229257,1115152,263189,1442839,656407,918560,394272,525346,853051,525376,1901635,1180739,722009,1246297,1246299,590939,1115248,1639546,853117,656545,2229456,1639632,787732,1639712,525619,1901895,1246535,1443164,1115660,1115660,853523,853523,1312289,1312289,1576,1115695,1115695,656949,656949,263733,1608,1615,919120,919120,1617,1623,722519,394839,525912,263768,1632,1632,1635,1640,591468,591468,263788,788085,788085,1660,1666,1667,1675,1683,1688,1696,1700,2295464,2295465,2098918,2098918,2950947,2950947,2361345,1312775,1574919,264199,722951,1640455,1640493,1640493,1509421,2033720,2230328,2164797,395333,1640517,264262,1771590,2121,2123,919629,2361431,2492503,723035,1902695,1312873,395370,1575041,788622,1116302,526482,1509523,2230419,1116320,1116321,2224,1771754,854259,1050872,1247480,1247499,1509651,1509652,1247508,395548,264488,395560,1247531,264500,723252,1640766,723279,1313103,1640789,526696,395624,854391,854398,1116542,2034208,1706535,1313324,1509932,1706563,1706563,1968709,2099782,1509986,1706610,1706724,1510137,1510211,1313603,2100232,2100232,2100232,2296844,2427916,1772570,1903643,1969179,1969179,1969179,2100252,1772580,1969191,2427951,2493487,1903669,2296917,2231381,2100309,1903702,1903703,1903713,1903729,658546,658546,1903741,2100357,2100357,2100358,2296967,2165895,2034846,1969337,2100410,2165950,1969352,1903817,1772747,2297041,2100433,1903836,1969373,1707229,1772765,2034909,1969373,2428182,2297110,1903895,1772838,1969450,1772868,1969483,1969484,1969484,1903948,2100556,2428247,2493784,1772925,1641865,2035204,2100748,1641998,2166288,2493972,1773076,1904148,2100760,2297368,2100760,1773082,1969694,1773086,1904158,1904159,2035238,1707560,1773096,2035243,2035244,1969708,2166316,1642037,1707575,2035258,2035263,2297409,1642055,1707591,2100809,2297424,2100816,1642065,2166353,2100817,1969746,2166354,2428499,1642067,1707604,2297428,2035299,2166372,1838697,1642090,1773163,2035310,1838703,1904242,1904242,1838707,2100852,2035319,2166391,2297464,2100856,2428537,2297465,2166393,2100858,2100859,2297469,1904276,1773205,1642135,1904280,1773209,2166442,2035374,2297531,2297532,2428604,2166461,2166463,2035395,2363075,1969860,2035403,1969869,2100949,2297557,2035414,2297558,2035415,1838812,1904349,2035437,2100994,1773314,1904389,1904390,1904390,1904391,1904392,1969928,1642249,1904394,1707787,2035467,2035468,2363148,2101004,2035468,2101004,1838861,1904398,1904399,2363161,1904410,1904412,1969948,1904413,1969949,1904414,1904420,1904488,1838953,2035561,2363242,2428780,2428783,1904509,1511294,2166668,1839104,1708034,2166795,1839116,1904655,1839119,1773583,1970191,1642511,1904656,2166801,1970194,1839131,2035739,2166812,1576988,1445917,1773597,1708062,1970207,2035744,1642528,1839137,1445923,1970211,2035751,2166823,1577003,1445933,1445933,1445936,1445938,2035764,1839158,1970231,2035767,1970233,1642553,1970236,2166845,2035774,1839169,1839169,1445955,1445955,1445955,1445955,2101327,2035792,1577041,1839188,2101332,2166869,1839189,2101334,2035800,1970266,2035803,1839216,1970289,1970290,1773721,1839257,1904793,1642660,1708196,1773732,1708210,1708211,1773748,1839320,1904856,1577180,1839329,1904865,1708257,1642727,2167020,2167020,2232556,1577206,1642742,1642753,1642753,2101513,2101513,2167050,1773838,1577240,1642781,2101568,2167104,1904976,2167129,2167129,2101593,1905008,1642864,1708400,1708400,1642887,2429325,2429325,2363790]
  for v in a:
    an=(v>>9)&127
    if an>n and n>=0:break
    else:
      if (an==n or n<0):b.append([(v&511)+li,(v>>16)/63])
  b.sort(key=lambda x:x[0])
  return b

def spectrum(n,a=li,b=ls,g=.2):
  a,b,r=min(a,b),max(b,a),rays(n,[])
  r.append([0])
  d,k=(b-a)/(sw-1),0
  for x in range(0,sw):
    l,m=x*d+a,0
    c=l2c(l)
    while abs(r[k][0]-l)<d:t,k,m=True,k+1,m+r[k][1]
    h,s,v=c2hsv(c)
    q=min(m,1)*(1-g)
    ce,ca=hsv2c(h,s,g+q*v),hsv2c(h,s,v-q*(v-g))
    draw_vert(x,0,sh//3-1,c)
    draw_vert(x,sh//3,(2*sh)//3-1,ce)
    draw_vert(x,(2*sh)//3,sh-1,ca)
  return r[:-1]