1
2
3 """
4 A class for reading and managing Mline output.
5
6 Author: R. Lombaert and M. van de Sande
7
8 """
9
10 import os
11 import numpy as np
12
13 from astropy import constants as cst
14
15 from cc.tools.readers.PopReader import PopReader
16 from cc.tools.readers.MolReader import MolReader
17 from cc.tools.io import DataIO
18
19
21
22 '''
23 A Reader for Mline output files.
24
25 This class inherits from both PopReader and MolReader, and thus provides
26 spectroscopic information of the molecule as given in the mline output. In
27 principle this information should be identical to what is read by
28 RadiatReader from the GASTRoNOoM spectroscopic input files. This information
29 is read from ml1.
30
31 In addition,
32 mline output gives other information calculated by the radiative transfer,
33 and that is available here as well. The level populations specifically are
34 managed through methods in PopReader. This class then also provides
35 additional data such as source function, optical depth, etc. This
36 information is read from ml3.
37
38 MlineReader only depends on GASTRoNOoM output and does not require
39 information from the databases or input files.
40
41 '''
42
44
45 '''
46 Creating an Mline object ready for reading Mline output.
47
48 Reading mline output through full filename, including filepath.
49
50 The mlinefile number is given as *, which is then replaced as needed.
51
52 The wildcard character does not have to be present, and is inserted
53 automatically. It is handled down the line by the parent classes.
54
55 Additional args and kwargs are passed to the dict creation (parent of
56 Reader)
57
58 Note that properties based on the filename are saved as instance
59 properties (such as id, molecule name, filename).
60
61 @param fn: The mline filename, including filepath. The mline
62 file number is given by *.
63 @type fn: string
64
65 '''
66
67
68 fn = fn.replace('ml1','ml*').replace('ml2','ml*').replace('ml3','ml*')
69 super(MlineReader, self).__init__(fn=fn,*args,**kwargs)
70
71
72 self.molecule = os.path.splitext(self.fn)[0].split('_')[-1]
73 self.id = os.path.splitext(self.fn)[0].split('_')[-2].replace('ml*','')
74
75
76
77
78 self.read()
79
80
81
83
84 '''
85 Read the mline output files ml1 and ml3.
86
87 The information is stored in the instance dictionary.
88
89 '''
90
91
92 self.__readML1()
93 self.__readML3()
94
95
96
98
99 '''
100 Read molecule spectroscopic properties and basic circumstellar radial
101 profiles from the ml1 file.
102
103 This is the information that is returned by MolReader methods.
104
105 Note that the level indexing is J + 1 for simple molecules like CO. For
106 any molecule, the 0-energy level has index 1!
107
108 Note also that the vel in the ml1 file is the velocity profile divided
109 by the stochastic velocity. (see source_common/vel.f) The velocity
110 profile saved here is the real velocity profile, corrected for this.
111
112 '''
113
114
115 fn = self.fn.replace('ml*','ml1')
116
117
118 d1 = DataIO.readDict(filename=fn,start_row=8,end_row=38,\
119 convert_floats=1,convert_ints=1,\
120 key_modifier='lower')
121 self['pars'] = d1
122
123
124
125 nhdr = len(d1) + 9 + 1
126
127
128 d2 = np.genfromtxt(fn,usecols=[0,1,2,3,4],skip_header=nhdr,\
129 dtype='i8,i8,i8,f8,f8',max_rows=d1['nline'],\
130 names=['index','lup','llow','frequency','einsteinA'])
131
132
133
134
135
136
137 d2['lup'] += 1
138 d2['llow'] += 1
139 self['trans'] = d2
140
141
142 nhdr += d1['nline'] + 1
143 d3 = np.genfromtxt(fn,skip_header=nhdr,max_rows=d1['ny'],\
144 dtype='i8,f8,f8',names=['index','weight','energy'])
145
146 self['level'] = d3
147
148
149
150 nhdr += d1['ny']
151 colnames = ['p_rstar','vel','nmol','nh2','amol','Tg','Td']
152 d4 = np.genfromtxt(fn,names=colnames,\
153 skip_header=nhdr,max_rows=d1['n_impact'])[::-1]
154 d4['vel'] *= d1['vsto']
155 self['props'] = d4
156
157
158
159
160 self['p'] = d4['p_rstar'] * self['pars']['r_star']
161
162
163
165
166 '''
167 Read the information from the ML3 file.
168
169 This includes in six blocks, with subblocks for each impact parameter:
170 - Scattering integral (si)
171 - Source function (sf)
172 - Line opacities (lo): if negative (or 1e-60 when
173 use_no_maser_option=1) the line is masing.
174 - Number densities (pop)
175 - Derivative of scat int wrt line opacity times line opacity at line
176 center (DsiDloXlo)
177 (see GASTRoNOoM src code source_mline/lamit.f for details: D1)
178 - Derivative of scat int wrt src function times src function at line
179 center (DsiDsfXsf)
180 (see GASTRoNOoM src code source_mline/lamit.f for details: D2)
181
182 '''
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 def readBlock(N_block):
204
205 '''
206 Read a block of data from ml3.
207
208 @param N_block: The index of the block (0 => 5)
209 @type N_block: int
210
211 @return: The data
212 @rtype: array
213
214 '''
215
216
217 nblock = nblock_ny if N_block == 3 else nblock_nline
218
219
220 ind0 = (N_block-1)*nblock_nline + 3*N_block
221
222
223
224 if N_block > 3:
225 ind0 += nblock_ny
226 else:
227 ind0 += nblock_nline
228
229
230 return np.genfromtxt(fn,skip_header=ind0,max_rows=nblock,\
231 delimiter=[14]*8)
232
233
234 fn = self.fn.replace('ml*','ml3')
235 props = ['si','sf','lo','pop','DsiDloXlo','DsiDsfXsf']
236 for pr in props:
237 self[pr] = dict()
238
239
240
241 n_impact = self['pars']['n_impact']
242 nline = self['pars']['nline']
243 nline_l = int(nline)/8+1
244 nblock_nline = n_impact * nline_l
245 ny = self['pars']['ny']
246 ny_l = int(ny)/8+1
247 nblock_ny = n_impact * ny_l
248
249
250 dds = [readBlock(N) for N in xrange(6)]
251
252
253
254
255 for dd,pr in zip(dds,props):
256 if pr == 'pop': continue
257 for i in xrange(nline):
258 self[pr][i+1] = dd[i/8::nline_l,i%8][::-1]
259
260
261
262
263 for i in xrange(ny):
264 self['pop'][i+1] = dds[3][i/8::ny_l,i%8][::-1]
265
266
267
269
270 '''
271 Return a radial circumstellar profile associated with the impact
272 parameter grid for the molecule of this mline model.
273
274 The impact parameter grid in cm is available through getP().
275
276 @param prop: The requested property. One of p_rstar, vel (km/s), nmol
277 (cm^-3), nh2 (cm^-3), amol, Tg (K), Td (K).
278 @type prop: str
279
280 @return: The abundance profile
281 @rtype: array
282
283 '''
284
285 return self['props'][prop]
286