1 """
2 Access atomic data
3
4 Mendelev's Table::
5
6 1 H Hydrogen 11 Na Natrium 21 Sc Scandium 31 Ga Gallium 41 Nb Niobium 51 Sb Antimony
7 2 He Helium 12 Mg Magnesium 22 Ti Titanium 32 Ge Germanium 42 Mo Molybdenum 52 Te Tellurium
8 3 Li Lithium 13 Al Aluminium 23 V Vanadium 33 As Arsenic 43 Tc Technetium 53 I Iodine
9 4 Be Beryllium 14 Si Silicon 24 Cr Chromium 34 Se Selenium 44 Ru Ruthenium 54 Xe Xenon
10 5 B Boron 15 P Phosphorus 25 Mn Manganese 35 Br Bromine 45 Rh Rhodium 55 Cs Caesium
11 6 C Carbon 16 S Sulfur 26 Fe Iron 36 Kr Krypton 46 Pd Palladium 56 Ba Barium
12 7 N Nitrogen 17 Cl Chlorine 28 Ni Nickel 37 Rb Rubidium 47 Ag Silver 57 La Lanthanum
13 8 O Oxygen 18 Ar Argon 27 Co Cobalt 38 Sr Strontium 48 Cd Cadmium 58 Ce Cerium
14 9 F Fluorine 19 K Potassium 29 Cu Copper 39 Y Yttrium 49 In Indium 59 Pr Praseodymium
15 10 Ne Neon 20 Ca Calcium 30 Zn Zinc 40 Zr Zirconium 50 Sn Tin 60 Nd Neodymium
16
17 61 Pm Promethium 71 Lu Lutetium 81 Tl Thallium 91 Pa Protactinium 101 Md Mendelevium 111 Rg Roentgenium
18 62 Sm Samarium 72 Hf Hafnium 82 Pb Lead 92 U Uranium 102 No Nobelium 112 Uub Ununbium
19 63 Eu Europium 73 Ta Tantalum 83 Bi Bismuth 93 Np Neptunium 103 Lr Lawrencium 113 Uut Ununtrium
20 64 Gd Gadolinium 74 W Tungsten 84 Po Polonium 94 Pu Plutonium 104 Rf Rutherfordium 114 Uuq Ununquadium
21 65 Tb Terbium 75 Re Rhenium 85 At Astatine 95 Am Americium 105 Db Dubnium 115 Uup Ununpentium
22 66 Dy Dysprosium 76 Os Osmium 86 Rn Radon 96 Cm Curium 106 Sg Seaborgium 116 Uuh Ununhexium
23 67 Ho Holmium 77 Ir Iridium 87 Fr Francium 97 Bk Berkelium 107 Bh Bohrium 118 Uuo Ununoctium
24 68 Er Erbium 78 Pt Platinum 88 Ra Radium 98 Cf Californium 108 Hs Hassium
25 69 Tm Thulium 79 Au Gold 89 Ac Actinium 99 Es Einsteinium 109 Mt Meitnerium
26 70 Yb Ytterbium 80 Hg Mercury 90 Th Thorium 100 Fm Fermium 110 Ds Darmstadtium
27
28 """
29 import os
30 import logging
31 import numpy as np
32 import pylab as pl
33 from numpy import inf
34
35 from ivs import config
36 from ivs.inout import ascii
37 from ivs.aux import loggers
38
39 logger = logging.getLogger("SPEC.LINELIST")
40 logger.addHandler(loggers.NullHandler)
41
42 atomcode = ['X', 'H','He','Li','Be', 'B', 'C', 'N', 'O', 'F','Ne',
43 'Na','Mg','Al','Si', 'P', 'S','Cl','Ar', 'K','Ca',
44 'Sc','Ti', 'V','Cr','Mn','Fe','Ni','Co','Cu','Zn',
45 'Ga','Ge','As','Se','Br','Kr','Rb','Sr', 'Y','Zr',
46 'Nb','Mo','Tc','Ru','Rh','Pd','Ag','Cd','In','Sn',
47 'Sb','Te', 'I','Xe','Cs','Ba','La','Ce','Pr','Nd',
48 'Pm','Sm','Eu','Gd','Tb','Dy','Ho','Er','Tm','Yb',
49 'Lu','Hf','Ta', 'W','Re','Os','Ir','Pt','Au','Hg',
50 'Tl','Pb','Bi','Po','At','Rn','Fr','Ra','Ac','Th',
51 'Pa', 'U','Np','Pu','Am','Cu','Bk','Cf','Es','Fm',
52 'Md','No','Lr','Rf','Db','Sg','Bh','Hs','Mt','Ds',
53 'Rg']
54 roman = ['I','II','III','IV','V','VI','VII','VIII','IX','X','XI','XII','XIII']
55
56
57
58 stellar = os.path.join('linelists/mask')
59
60
61
62 -def VALD(elem=None,xmin=3200.,xmax=4800.,outputdir=None):
63 """
64 Request linelists from VALD for each ion seperately within a specific wavelength range.
65
66 elem = an array of ions e.g. ['CI','OII'], xmin and xmax: wavelength range in which the spectral lines are searched, outputdir = output directory chosen by the user.
67
68 If no elements are given, this function returns all of them.
69
70 @param elem: list of ions
71 @type elem: list of str
72 """
73 if elem is None:
74 files = sorted(config.glob('VALD_individual','VALD_*.lijnen'))
75 elem = [os.path.splitext(os.path.basename(ff))[0].split('_')[1] for ff in files]
76
77 all_lines = []
78 for i in range(len(elem)):
79 print elem[i]
80 filename = config.get_datafile('VALD_individual','VALD_' + elem[i] + '.lijnen')
81 if not os.path.isfile(filename):
82 logger.info('No data for element ' + str(elem[i]))
83 return None
84
85 newwav,newexc,newep,newgf = np.loadtxt(filename).T
86 lines = np.rec.fromarrays([newwav,newexc,newep,newgf],names=['wavelength','ion','ep','gf'])
87 keep = (xmin<=lines['wavelength']) & (lines['wavelength']<=xmax)
88 if not hasattr(keep,'__iter__'):
89 continue
90 lines = lines[keep]
91 if len(lines) and outputdir is not None:
92 ascii.write_array(lines,outputdir + 'VALD_' + str(elem[i]) + '_' + str(xmin) + '_' + str(xmax) + '.dat',auto_width=True,header=True,formats=['%.3f','%.1f','%.3f','%.3f'])
93 elif len(lines):
94 all_lines.append(lines)
95 else:
96 logger.debug('No lines of ' + str(elem[i]) + ' in given wavelength range')
97 return np.hstack(all_lines)
98
99 -def get_lines(teff,logg,z=0,atoms=None,ions=None,wrange=(-inf,inf),\
100 blend=0.0):
101 """
102 Retrieve line transitions and strengths for a specific stellar type
103
104 Selection wavelength range in angstrom.
105
106 Ions should be a list of ions to include. This can either be a string or
107 a number
108
109 A lines is considerd a blend if the closest line is closer than C{blend} angstrom.
110
111 Returns record array with fields C{wavelength}, C{ion} and C{depth}.
112
113 Example usage:
114
115 Retrieve all Silicon lines between 4500 and 4600 for a B1V star.
116
117 >>> data = get_lines(20000,4.0,atoms=['Si'],wrange=(4500,4600))
118 >>> p = pl.figure()
119 >>> p = pl.vlines(data['wavelength'],1,1-data['depth'])
120
121 See how the depth of the Halpha line varies wrt temperature:
122
123 >>> teffs = range(5000,21000,1000) + range(22000,32000,2000) + range(30000,50000,50000)
124 >>> depths = np.zeros((len(teffs),7))
125 >>> for i,teff in enumerate(teffs):
126 ... data = get_lines(teff,5.0,ions=['HI'],wrange=(3800,7000))
127 ... depths[i] = data['depth']
128
129 >>> p = pl.figure();p = pl.title('Depth of Balmer lines (Halpha-Heta)')
130 >>> p = pl.plot(teffs,1-depths,'o-')
131 >>> p = pl.xlabel('Effective temperature');p = pl.grid()
132
133 """
134
135 filename = 'mask.%d.%02d.p%02d'%(int(teff),int(logg*10),int(z))
136 filename = config.get_datafile(stellar,filename)
137
138 data = ascii.read2recarray(filename,skip_lines=1,dtype=[('wavelength','f8'),('ion','f8'),('depth','f8'),('c3','f8'),('c4','f8'),('c5','f8')])
139 data = pl.mlab.rec_drop_fields(data,['c3','c4','c5'])
140 data['wavelength'] *= 10.
141
142 if blend>0:
143 blends_left = np.hstack([0,np.diff(data['wavelength'])])
144 blends_right= np.hstack([np.diff(data['wavelength']),1e10])
145 keep = (blends_left>blend) & (blends_right>blend)
146 data = data[keep]
147
148
149 keep = (wrange[0]<=data['wavelength']) & (data['wavelength']<=wrange[1])
150 data = data[keep]
151
152 if atoms is not None or ions is not None:
153 keep = np.array(np.zeros(len(data)),bool)
154 else:
155 keep = np.array(np.ones(len(data)),bool)
156 if atoms is not None:
157
158 atoms = [(isinstance(atom,str) and atomcode.index(atom.title()) or atom) for atom in atoms]
159 for atom in atoms:
160 keep = keep | (np.abs(data['ion']-atom)<0.5)
161 if ions is not None:
162
163 ions = [(isinstance(ion,str) and name2ioncode(ion) or ion) for ion in ions]
164 for ion in ions:
165 keep = keep | (np.abs(data['ion']-ion)<0.005)
166
167 return data[keep]
168
169
170
171
172
173
175 """
176 Convert 14.01 to SiII
177 """
178 atom = int(np.floor(ioncode))
179 ion = int(np.round((ioncode-atom)*100))
180 return atomcode[atom]+roman[ion]
181
183 """
184 Convert SiII to 14.01
185 """
186 atomname,ionstage = splitname(name)
187 return atomcode.index(atomname) + roman.index(ionstage)/100.
188
190 """
191 Split SiII into Si and II
192 """
193 atomname = ''
194 ionstage = ''
195 for char in name:
196 if not atomname or char.islower():
197 atomname+=char
198 elif char.isupper():
199 ionstage+=char
200 return atomname,ionstage
201
202
203
204
205
206 if __name__=="__main__":
207 import doctest
208 doctest.testmod()
209 pl.show()
210