-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
297 lines (242 loc) · 8.79 KB
/
utils.py
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
from __future__ import print_function, absolute_import, division, unicode_literals
import os
import numpy as np
import matplotlib.transforms as mtransforms
from barak.absorb import findtrans, readatom
from barak.io import readtabfits, readtxt, parse_config
from barak.utilities import adict, get_data_path, between
from barak.pyvpfit import readf26
from barak.constants import c_kms
from barak.convolve import convolve_constant_dv
from barak.sed import make_constant_dv_wa_scale
from barak.convolve import convolve_psf
from astropy.table import Table
try:
from COS import convolve_with_COS_FOS
except:
convolve_with_COS_FOS = None
# regions of atmospheric absorption
ATMOS = [(5570, 5590),
(5885, 5900),
(6275, 6325),
(6870, 6950),
(7170, 7350),
(7580, 7690),
(8130, 8350),
(8900, 9200),
(9300, 9850),
(11100, 11620),
(12590, 12790),
(13035, 15110),
(17435, 20850),
(24150, 24800)]
def lines_from_f26(f26):
""" Convert a f26-file list of lines into a list we can pass to
find_tau.
"""
if f26 is None:
return []
if f26.lines is None:
f26.lines = []
lines = []
for l in f26.lines:
print(l['name'])
if l['name'].strip() in ('<<', '>>'):
#print "skipping!"
continue
lines.append((l['name'].replace(' ', ''), l['z'], l['b'], l['logN']))
return lines
def plot_tick_vel(ax, vpos, offset, t, tickz=None):
""" plot a single velocity tick
"""
label = '%s %.0f %.3f' % (t['name'], t['wa0'], t['z'])
label = label.replace('NeVII', 'NeVIII')
T = ax.plot(
[vpos, vpos], [1.05 + offset, 1.4 + offset],
color='k', alpha=0.7, lw=1.5)
Tlabels = []
if (tickz is not None and
not (1e-5 < abs(t['z'] - tickz) < 1e-2)) or tickz is None:
Tlabels.append(ax.text(vpos, 1.05 + offset, label, rotation=60,
fontsize=8, va='bottom', alpha=0.7))
return T, Tlabels
def plot_tick_wa(ax, wa, fl, height, t, tickz=None):
""" plot a single tick on a wavelength scale
"""
label = '%s %.0f %.3f' % (t.name, t.wa0, t.z)
label = label.replace('NeVII', 'NeVIII')
fl = fl * 1.1
T = ax.plot([wa, wa], [fl, fl + height], color='c', alpha=0.7, lw=1.5)
Tlabels = []
if tickz is not None and not (1e-5 < abs(t.z - tickz) < 1e-2) or \
tickz is None:
Tlabels.append(ax.text(wa, fl + 1.35 * height, label, rotation=60,
fontsize=8, va='bottom', alpha=0.7))
return T, Tlabels
def plotregions(ax, wmin, wmax, wa, fl):
""" Plot a series of fitting regions on the matplotlib axes `ax`.
"""
trans = mtransforms.blended_transform_factory(ax.transData, ax.transAxes)
regions = []
for w0, w1 in zip(wmin, wmax):
r0, = ax.plot([w0, w1], [0.8, 0.8], color='r', lw=3, alpha=0.7,
transform=trans)
c0 = between(wa, w0, w1)
r1, = ax.plot(wa[c0], fl[c0], color='y', lw=3, alpha=0.5,
zorder=0, drawstyle='steps-mid')
#r = ax.fill_betweenx([0, 0.8], w0, x2=w1, facecolor='b', alpha=0.2,
# lw=0, zorder=1,
# transform=trans)
regions.extend([r0, r1])
return regions
def plot_velocity_regions(wmin, wmax, w0, w1, obswa, ax, offset,
vel, nfl):
""" wmin, wmax is minimum and maximum wavelengths of the plot.
w0 and w1 are the min and max wavelengths of the fitting
regions. obswa is the wavelength of the transition for this plot.
"""
cond = ((w1 >= wmax) & (w0 < wmax)) | \
((w1 <= wmax) & (w0 >= wmin)) | \
((w1 > wmin) & (w0 <= wmin))
regions = []
if not cond.any():
return regions
vel0 = (w0[cond] / obswa - 1) * c_kms
vel1 = (w1[cond] / obswa - 1) * c_kms
for v0, v1 in zip(vel0, vel1):
yoff = 1.1 + offset
R0, = ax.plot([v0, v1], [yoff, yoff], 'r', lw=3, alpha=0.7)
cond = between(vel, v0, v1)
R1, = ax.plot(vel[cond], nfl[cond] + offset, 'y', lw=4, alpha=0.5,
drawstyle='steps-mid',zorder=0)
regions.extend([R0,R1])
return regions
def print_example_options():
print("""\
Rfwhm = 6.67
features = features_filename
f26 = lines.f26
transitions = transitions/z0p56
taulines = taulines_filename
co_is_sky = False
tickz = 0.567311
ticklabels = True
showticks = True
z = 3
wadiv = 6
nsmooth = 1
show_oscillator_strength = False
dv = 1000
residuals = False
""")
def process_options(args):
opt = adict()
filename = os.path.abspath(__file__).rsplit('/', 1)[0] + '/default.cfg'
opt = parse_config(filename)
if os.path.lexists('./plot.cfg'):
opt = parse_config('./plot.cfg', opt)
opt.atom = readatom(molecules=True)
if opt.Rfwhm is not None:
if isinstance(opt.Rfwhm, basestring):
if opt.Rfwhm == 'convolve_with_COS_FOS':
if convolve_with_COS_FOS is None:
raise ValueError('convolve_with_COS_FOS() not available')
print('Using tailored FWHM for COS/FOS data')
opt.Rfwhm = 'convolve_with_COS_FOS'
elif opt.Rfwhm.endswith('fits'):
print('Reading Resolution FWHM from', opt.Rfwhm)
res = readtabfits(opt.Rfwhm)
opt.Rfwhm = res.res / 2.354
else:
print('Reading Resolution FWHM from', opt.Rfwhm)
fh = open(opt.Rfwhm)
opt.Rfwhm = 1 / 2.354 * np.array([float(r) for r in fh])
fh.close()
else:
opt.Rfwhm = float(opt.Rfwhm)
if opt.features is not None:
print('Reading feature list from', opt.features)
opt.features = readtabfits(opt.features)
if opt.f26 is not None:
name = opt.f26
print('Reading ions and fitting regions from', name)
opt.f26 = readf26(name)
opt.f26.filename = name
if opt.transitions is not None:
print('Reading transitions from', opt.transitions)
fh = open(opt.transitions)
trans = list(fh)
fh.close()
temp = []
for tr in trans:
tr = tr.strip()
if tr and not tr.startswith('#'):
junk = tr.split()
tr = junk[0] + ' ' + junk[1]
t = findtrans(tr, atomdat=opt.atom)
temp.append(dict(name=t[0], wa=t[1][0], tr=t[1]))
opt.linelist = temp
else:
opt.linelist = readtxt(get_data_path() + 'linelists/qsoabs_lines',
names='wa,name,select')
if opt.f26 is None and opt.taulines is not None:
print('Reading ions from', opt.taulines)
fh = open(opt.taulines)
lines = []
for row in fh:
if row.lstrip().startswith('#'):
continue
items = row.split()
lines.append([items[0]] + list(map(float, items[1:])))
fh.close()
opt.lines = lines
if opt.show_regions is None:
opt.show_regions = True
if hasattr(opt, 'aodname'):
opt.aod = Table.read(opt.aodname)
return opt
def process_Rfwhm(Rfwhm, wa, model, models):
""" Convolve the input models using the Rfwhm option
Return the new models.
wa: wavelength array, shape (N,)
model: model flux array, shape (N,)
models: list of model flux arrays each with shape (N,)
Rfwhm is one of:
'convolve_with_COS_FOS'
a float
an array floats with shape (N,)
Returns
-------
new_model, new_models
"""
model_out = None
models_out = []
#import pdb; pdb.set_trace()
if Rfwhm is None:
return model, models
elif Rfwhm == 'convolve_with_COS_FOS':
#print 'convolving with COS/FOS instrument profile'
#import pdb; pdb.set_trace()
model_out = convolve_with_COS_FOS(model, wa, use_COS_nuv=True)
for m in models:
#if m.min() < (1 - 1e-2):
m = convolve_with_COS_FOS(m, wa, use_COS_nuv=True)
models_out.append(m)
elif isinstance(Rfwhm, float):
#print 'Convolving with fwhm %.2f km/s' % Rfwhm
# use a pixel velocity width 4 times smaller than the FWHM
ndiv = 4.
try:
wa_dv = make_constant_dv_wa_scale(wa[0], wa[-1], Rfwhm / ndiv)
except:
import pdb
pdb.set_trace()
model_out = convolve_constant_dv(wa, model, wa_dv, ndiv)
# do the same to every model if there's more than one
for m in models:
#if m.min() < (1 - 1e-2):
m = convolve_constant_dv(wa, m, wa_dv, ndiv)
models_out.append(m)
else:
raise ValueError('Unknown value for Rfwhm option')
return model_out, models_out