-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathstar.py
More file actions
184 lines (169 loc) · 7.31 KB
/
star.py
File metadata and controls
184 lines (169 loc) · 7.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import numpy as np
import logging
from . import modatm
from .config import *
from .tools import read_csv
logger = logging.getLogger(__name__)
class Data:
"""q2 Data objects contain the information from the input star
and lines CSV files as attributes 'star_data' and 'lines'.
"""
def __init__(self, fname_star_data, fname_lines=None):
"""Takes as input a star data file (CSV, required) and a line-list
data file (CSV, optional) to create a q2 data object.
"""
try:
self.star_data = read_csv(fname_star_data, file_type='stars')
self.star_data_fname = fname_star_data
if not self.star_data:
logger.error('Star data file not read. Data.star_data '+\
'attribute set to None.')
except:
self.star_data = None
self.star_data_fname = None
logger.error('Star data file not found.')
if fname_lines:
try:
self.lines = read_csv(fname_lines, file_type='lines')
self.lines_fname = fname_lines
if not self.lines:
logger.error('Lines data file not read. Data.lines '+\
'attribute set to None.')
except:
self.lines = None
self.lines_fname = None
logger.error('Lines file not found.')
else:
self.lines = None
self.lines_fname = None
logger.warning('No lines data. Wont be able to MOOG.')
if self.star_data:
logger.info('Data object created with star_data attribute.')
if self.lines:
logger.info('lines_data attribute added to Data object.')
def __repr__(self):
if self.star_data:
nstars = len(self.star_data['id'])
else:
nstars = 0
if self.lines:
nlines = len(np.where(self.lines['wavelength'] > 0)[0])
else:
nlines = 0
return "Data object built from:\n"\
" stars file = {0} ({1} stars)\n"\
" lines file = {2} ({3} lines)".\
format(self.star_data_fname, nstars, self.lines_fname, nlines)
class Star:
"""q2 Star objects contain information about a star (e.g., Teff, logg,
etc). This information can be grabbed from a q2.Data object using the
'get_data_from' method. If the Star object has parameters known, a
model atmosphere can be computed using the 'get_model_atmosphere'
method. This will attach a 'model_atmosphere' attribute to the Star
object.
"""
def __init__(self, name='Unnamed star',
teff=None, logg=None, feh=None, vt=None,
err_teff=None, err_logg=None, err_feh=None, err_vt=None):
self.name = name
self.teff = teff
self.logg = logg
self.feh = feh
self.vt = vt
if err_teff:
self.err_teff = err_teff
if err_logg:
self.err_logg = err_logg
if err_feh:
self.err_feh = err_feh
if err_vt:
self.err_vt = err_vt
logger.info('Star object successfully created.')
def __repr__(self):
if hasattr(self, 'linelist'):
nlines = len(self.linelist['wavelength'])
species = ','.join([str(sp) for sp in\
set(self.linelist['species'])])
else:
nlines = species = None
if hasattr(self, 'model_atmosphere'):
ma = self.model_atmosphere_grid
else:
ma = None
return "Star object named '{0}':\n"\
" Teff (K) = {1}, logg [cgs] = {2}, [Fe/H] = {3}, "\
"vt (km/s) = {4}\n"\
" Spectral lines = {5} (species: {6})\n"\
" Model atmosphere: {7}".\
format(self.name, self.teff, self.logg, self.feh, self.vt,
nlines, species, ma)
def get_data_from(self, Data):
"""If the Star object has a name that matches one of the id's in
a Data object, the information from Data will be given to Star.
"""
#idx must correspond to a unique id; hence the [0][0]
try:
idx = np.where(Data.star_data['id'] == self.name)[0][0]
logger.info("Star '"+self.name+"' found in data object.")
except:
logger.error("Star '"+self.name+"' not found in data object.")
return None
parameters = ['teff', 'err_teff', 'logg', 'err_logg',
'feh', 'err_feh', 'vt', 'err_vt', 'rho', 'err_rho',
'v', 'err_v', 'plx', 'err_plx', 'converged', 'feh_model']
msg = []
for par in parameters:
if par in Data.star_data.keys():
if Data.star_data[par][idx] != None:
setattr(self, par, Data.star_data[par][idx])
msg.append(par)
if msg:
logger.info('Attribute(s) '+','.join(msg)+\
' added to star object.')
# gets line data excluding cells with no ew:
#if hasattr(Data, 'lines'):
if Data.lines:
idx = np.where(Data.lines[self.name] != np.nan)
self.linelist = {'wavelength': Data.lines['wavelength'][idx],
'species': Data.lines['species'][idx],
'ep': Data.lines['ep'][idx],
'gf': Data.lines['gf'][idx],
'ew': Data.lines[self.name][idx]}
logger.info('Attribute linelist added to star object.')
else:
logger.warning('There is no line data to attach to Star object.')
def get_model_atmosphere(self, grid='odfnew'):
"""If teff, logg, and feh are set attributes for a Star object,
a model atmosphere will be interpolated from one of the
available grids: 'odfnew' (default), 'aodfnew', 'over', 'nover'
(all Kurucz), or 'marcs'.
"""
if self.teff == None or self.logg == None or self.feh == None:
logger.error('To create model atmosphere, star must have all '+
'three fundamental parameters: Teff, logg, and '+
'[Fe/H].')
return None
if hasattr(self, 'feh_model'):
feh = self.feh_model
else:
feh = self.feh
x = modatm.interpolate(self.teff, self.logg,
feh, grid)
if x != None:
self.model_atmosphere = x
self.model_atmosphere_grid = grid
def get_absolute_magnitude(self, recalculate=False):
if hasattr(self, 'M_V') and hasattr(self, 'err_M_V') \
and not recalculate:
logger.warning('star already has M_V and err_M_V defined. '+\
'Nothing changed. Use recalculate=True to overwrite')
return None
try:
self.M_V = self.v - 5 * np.log10(1000/self.plx) + 5.
self.err_M_V = np.sqrt(self.err_v**2 +\
(np.log10(np.exp(1))**2)*25*(self.err_plx/self.plx)**2)
logger.info('Absolute magnitude and error attributes '+\
'added to star object')
except:
logger.warning('Could not calculate absolute magnitude. '+\
'Star must have v and err_v attributes (vmag).')