1
2
3 """
4 A plotting environment for Chemistry output.
5
6 Author: M. Van de Sande
7
8 """
9
10 import os
11 from scipy import array
12 import operator
13 import subprocess
14 from scipy.interpolate import interp1d
15 import numpy as np
16
17 import cc.path
18 from cc.plotting.objects.PlottingSession import PlottingSession
19 from cc.tools.io import DataIO
20 from cc.modeling.objects import Transition
21 from cc.plotting import Plotting2
22 from cc.tools.readers import LineList
23 from cc.data.instruments import Pacs
24 from cc.modeling.objects import Star
25
26
27
29
30 """
31 Class for plotting gas lines and their information.
32
33 """
34
35 - def __init__(self,star_name,path_chemistry='OutputClumpy',\
36 inputfilename=None,fn_add_star=1):
37
38 """
39 Initializing an instance of PlotGas.
40
41 @param star_name: name of the star from Star.dat, use default only
42 when never using any star model specific things
43 @type star_name: string
44
45 @keyword path_chemistry: Output modeling folder in MCMax home folder
46
47 (default: 'OutputClumpy')
48 @type path_chemistry: string
49 @keyword inputfilename: name of inputfile that is also copied to the
50 output folder of the plots,
51 if None nothing is copied
52
53 (default: None)
54 @type inputfilename: string
55
56 @keyword fn_add_star: Add the star name to the requested plot filename.
57 Only relevant if fn_plt is given in a sub method.
58
59 (default: 1)
60 @type fn_add_star: bool
61
62
63 """
64
65 super(PlotChem, self).__init__(star_name=star_name,\
66 path=path_chemistry,\
67 code='Chemistry',\
68 inputfilename=inputfilename,\
69 fn_add_star=fn_add_star)
70
71 cc.path.cout = os.path.join(cc.path.chemistry,self.path)
72
73
74
76
77 '''
78 Make a Star list based on the Chemistry model ids.
79
80 @param models: model_ids for the Chemistry db
81 @type models: list(string)
82
83 @return: the parameter sets
84 @rtype: list[Star()]
85
86 '''
87
88 star_grid = Star.makeStars(models=models,\
89 id_type='Chemistry',\
90 code='Chemistry',path=self.path)
91 [star.addCoolingPars() for star in star_grid]
92 return star_grid
93
94
95
96 - def plotVelocity(self,star_grid=[],models=[],fn_plt='',force_plot=0,cfg=''):
97
98 '''
99 Plot velocity versus radius for every model in star_grid.
100
101 @keyword star_grid: List of Star() instances. If default, model ids
102 have to be given.
103
104 (default: [])
105 @type star_grid: list[Star()]
106 @keyword models: The model ids, only required if star_grid is []
107
108 (default: [])
109 @type models: list[string]
110 @keyword fn_plt: A base plot filename. Includes folder. If not, a
111 default is added
112
113 (default: '')
114 @type fn_plt: string
115 @keyword force_plot: force a plotting if more than models are requested
116
117 (default: 0)
118 @type force_plot: bool
119 @keyword cfg: path to the Plotting2.plotCols config file. If default,
120 the hard-coded default plotting options are used.
121
122 (default: '')
123 @type cfg: string
124
125 '''
126
127 print '***********************************'
128 print '** Plotting Gas Velocity Profiles'
129 if not star_grid and models:
130 star_grid = self.makeStars(models=models)
131 elif (not models and not star_grid) or (models and star_grid):
132 print '** Input is undefined or doubly defined. Aborting.'
133 return
134
135 cfg_dict = Plotting2.readCfg(cfg)
136 if cfg_dict.has_key('filename'):
137 fn_plt = cfg_dict.pop('filename')
138
139 if len(star_grid) < 20 or force_plot:
140
141 valid_sg = [star for star in star_grid
142 if star['LAST_CHEMISTRY_MODEL']]
143
144 folders = [os.path.join(cc.path.cout,'models',\
145 star['LAST_CHEMISTRY_MODEL'])+'/' for star in valid_sg]
146
147 radii = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'RADIUS') \
148 for folder in folders]
149 temps = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'VELOCITY') \
150 for folder in folders]
151
152 if temps:
153 keytags = [star['LAST_CHEMISTRY_MODEL'].replace('_','\_')
154 for star in valid_sg]
155
156
157 pfn = fn_plt if fn_plt else 'velocity_profiles'
158 pfn = self.setFnPlt(pfn)
159
160
161 keys_cm = ['Model %i'%(i+1)
162 for i in xrange(len(star_grid))]
163 pfn = Plotting2.plotCols(x=radii,y=temps,cfg=cfg_dict,\
164 filename=pfn,xaxis='$r$ (cm)',\
165 yaxis=r'$v$ (km s$^{-1}$)',\
166 figsize=(12.5,8),fontsize_ticklabels=26,\
167 key_location=(0.05,0.05),xlogscale=1,ylogscale=1,\
168 keytags=keys_cm,fontsize_axis=26,fontsize_key=26)
169 print '** Plots can be found at:'
170 print pfn
171 print '***********************************'
172
173
174 - def plotTemp(self,star_grid=[],models=[],fn_plt='',force_plot=0,cfg=''):
175
176 '''
177 Plot temperature profiles of all models.
178
179 @keyword star_grid: List of Star() instances. If default, model ids
180 have to be given.
181
182 (default: [])
183 @type star_grid: list[Star()]
184 @keyword models: The model ids, only required if star_grid is []
185
186 (default: [])
187 @type models: list[string]
188 @keyword fn_plt: A base plot filename. Includes folder. If not, a
189 default is added
190
191 (default: '')
192 @type fn_plt: string
193 @keyword force_plot: force a plotting if more than models are requested
194
195 (default: 0)
196 @type force_plot: bool
197 @keyword cfg: path to the Plotting2.plotCols config file. If default,
198 the hard-coded default plotting options are used.
199
200 (default: '')
201 @type cfg: string
202
203 '''
204
205 print '***********************************'
206 print '** Plotting Gas Temperature Profiles'
207 if not star_grid and models:
208 star_grid = self.makeStars(models=models)
209 elif (not models and not star_grid) or (models and star_grid):
210 print '** Input is undefined or doubly defined. Aborting.'
211 return
212
213 cfg_dict = Plotting2.readCfg(cfg)
214 if cfg_dict.has_key('filename'):
215 fn_plt = cfg_dict.pop('filename')
216
217 if len(star_grid) < 20 or force_plot:
218
219 valid_sg = [star for star in star_grid
220 if star['LAST_CHEMISTRY_MODEL']]
221
222 folders = [os.path.join(cc.path.cout,'models',\
223 star['LAST_CHEMISTRY_MODEL'])+'/' for star in valid_sg]
224
225 radii = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'RADIUS') \
226 for folder in folders]
227 temps = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'TEMP') \
228 for folder in folders]
229
230 if temps:
231 keytags = [star['LAST_CHEMISTRY_MODEL'].replace('_','\_')
232 for star in valid_sg]
233
234
235 pfn = fn_plt if fn_plt else 'temperature_profiles'
236 pfn = self.setFnPlt(pfn)
237
238
239 keys_cm = ['Model %i'%(i+1)
240 for i in xrange(len(star_grid))]
241 pfn = Plotting2.plotCols(x=radii,y=temps,cfg=cfg_dict,\
242 filename=pfn,xaxis='$r$ (cm)',\
243 yaxis='$T_\mathrm{g}$ (K)',\
244 figsize=(12.5,8),fontsize_ticklabels=26,\
245 key_location=(0.05,0.05),xlogscale=1,ylogscale=1,\
246 keytags=keys_cm,fontsize_axis=26,fontsize_key=26)
247 print '** Plots can be found at:'
248 print pfn
249 print '***********************************'
250 else:
251 print '** No Chemistry models were calculated successfully.'+\
252 'No temperature profiles can be plotted.'
253 print '***********************************'
254
255
256
258
259 '''
260 Plot temperature profiles of all models.
261
262 @keyword star_grid: List of Star() instances. If default, model ids
263 have to be given.
264
265 (default: [])
266 @type star_grid: list[Star()]
267 @keyword models: The model ids, only required if star_grid is []
268
269 (default: [])
270 @type models: list[string]
271 @keyword fn_plt: A base plot filename. Includes folder. If not, a
272 default is added
273
274 (default: '')
275 @type fn_plt: string
276 @keyword force_plot: force a plotting if more than models are requested
277
278 (default: 0)
279 @type force_plot: bool
280 @keyword cfg: path to the Plotting2.plotCols config file. If default,
281 the hard-coded default plotting options are used.
282
283 (default: '')
284 @type cfg: string
285
286 '''
287
288 print '***********************************'
289 print '** Plotting Visual Extinction Profiles'
290 if not star_grid and models:
291 star_grid = self.makeStars(models=models)
292 elif (not models and not star_grid) or (models and star_grid):
293 print '** Input is undefined or doubly defined. Aborting.'
294 return
295
296 cfg_dict = Plotting2.readCfg(cfg)
297 if cfg_dict.has_key('filename'):
298 fn_plt = cfg_dict.pop('filename')
299
300 if len(star_grid) < 20 or force_plot:
301
302 valid_sg = [star for star in star_grid
303 if star['LAST_CHEMISTRY_MODEL']]
304
305 folders = [os.path.join(cc.path.cout,'models',\
306 star['LAST_CHEMISTRY_MODEL'])+'/' for star in valid_sg]
307
308 radii = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'RADIUS') \
309 for folder in folders]
310 avs = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'A_V') \
311 for folder in folders]
312
313 if avs:
314 keytags = [star['LAST_CHEMISTRY_MODEL'].replace('_','\_')
315 for star in valid_sg]
316
317
318 pfn = fn_plt if fn_plt else 'visual_extinction'
319 pfn = self.setFnPlt(pfn)
320
321
322 keys_cm = ['Model %i'%(i+1)
323 for i in xrange(len(star_grid))]
324 pfn = Plotting2.plotCols(x=radii,y=avs,cfg=cfg_dict,\
325 filename=pfn,xaxis='$r$ (cm)',\
326 yaxis='$A_V$ (mag)',\
327 figsize=(12.5,8),fontsize_ticklabels=26,\
328 key_location=(0.05,0.05),xlogscale=1,ylogscale=1,\
329 keytags=keys_cm,fontsize_axis=26,fontsize_key=26)
330 print '** Plots can be found at:'
331 print pfn
332 print '***********************************'
333 else:
334 print '** No Chemistry models were calculated successfully.'+\
335 'No temperature profiles can be plotted.'
336 print '***********************************'
337
338
340
341 '''
342 Plot temperature profiles of all models.
343
344 @keyword star_grid: List of Star() instances. If default, model ids
345 have to be given.
346
347 (default: [])
348 @type star_grid: list[Star()]
349 @keyword models: The model ids, only required if star_grid is []
350
351 (default: [])
352 @type models: list[string]
353 @keyword fn_plt: A base plot filename. Includes folder. If not, a
354 default is added
355
356 (default: '')
357 @type fn_plt: string
358 @keyword force_plot: force a plotting if more than models are requested
359
360 (default: 0)
361 @type force_plot: bool
362 @keyword cfg: path to the Plotting2.plotCols config file. If default,
363 the hard-coded default plotting options are used.
364
365 (default: '')
366 @type cfg: string
367
368 '''
369
370 print '***********************************'
371 print '** Plotting Photodissociation Rate CO'
372 if not star_grid and models:
373 star_grid = self.makeStars(models=models)
374 elif (not models and not star_grid) or (models and star_grid):
375 print '** Input is undefined or doubly defined. Aborting.'
376 return
377
378 cfg_dict = Plotting2.readCfg(cfg)
379 if cfg_dict.has_key('filename'):
380 fn_plt = cfg_dict.pop('filename')
381
382 if len(star_grid) < 20 or force_plot:
383
384 valid_sg = [star for star in star_grid
385 if star['LAST_CHEMISTRY_MODEL']]
386
387 folders = [os.path.join(cc.path.cout,'models',\
388 star['LAST_CHEMISTRY_MODEL'])+'/' for star in valid_sg]
389
390 radii = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'RADIUS') \
391 for folder in folders]
392 cos = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'COK(PHOT)') \
393 for folder in folders]
394
395 if cos:
396 keytags = [star['LAST_CHEMISTRY_MODEL'].replace('_','\_')
397 for star in valid_sg]
398
399
400 pfn = fn_plt if fn_plt else 'CO_photodissociation_rate'
401 pfn = self.setFnPlt(pfn)
402
403
404 keys_cm = ['Model %i'%(i+1)
405 for i in xrange(len(star_grid))]
406 pfn = Plotting2.plotCols(x=radii,y=cos,cfg=cfg_dict,\
407 filename=pfn,xaxis='$r$ (cm)',\
408 yaxis='$k_{CO,photo}$ (s$^{-1}$)',\
409 figsize=(12.5,8),fontsize_ticklabels=26,\
410 key_location=(0.05,0.05),xlogscale=1,ylogscale=1,\
411 keytags=keys_cm,fontsize_axis=26,fontsize_key=26)
412 print '** Plots can be found at:'
413 print pfn
414 print '***********************************'
415 else:
416 print '** No Chemistry models were calculated successfully.'+\
417 'No temperature profiles can be plotted.'
418 print '***********************************'
419
420
421
423
424 '''
425 Plot temperature profiles of all models.
426
427 @keyword star_grid: List of Star() instances. If default, model ids
428 have to be given.
429
430 (default: [])
431 @type star_grid: list[Star()]
432 @keyword models: The model ids, only required if star_grid is []
433
434 (default: [])
435 @type models: list[string]
436 @keyword fn_plt: A base plot filename. Includes folder. If not, a
437 default is added
438
439 (default: '')
440 @type fn_plt: string
441 @keyword force_plot: force a plotting if more than models are requested
442
443 (default: 0)
444 @type force_plot: bool
445 @keyword cfg: path to the Plotting2.plotCols config file. If default,
446 the hard-coded default plotting options are used.
447
448 (default: '')
449 @type cfg: string
450
451 '''
452
453 print '***********************************'
454 print '** Plotting Radiation Field'
455 if not star_grid and models:
456 star_grid = self.makeStars(models=models)
457 elif (not models and not star_grid) or (models and star_grid):
458 print '** Input is undefined or doubly defined. Aborting.'
459 return
460
461 cfg_dict = Plotting2.readCfg(cfg)
462 if cfg_dict.has_key('filename'):
463 fn_plt = cfg_dict.pop('filename')
464
465 if len(star_grid) < 20 or force_plot:
466
467 valid_sg = [star for star in star_grid
468 if star['LAST_CHEMISTRY_MODEL']]
469
470 folders = [os.path.join(cc.path.cout,'models',\
471 star['LAST_CHEMISTRY_MODEL'])+'/' for star in valid_sg]
472
473 radii = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'RADIUS') \
474 for folder in folders]
475 cos = [DataIO.getChemistryPhysPar(folder+'csphyspar.out', 'COK(PHOT)') \
476 for folder in folders]
477
478 if cos:
479 keytags = [star['LAST_CHEMISTRY_MODEL'].replace('_','\_')
480 for star in valid_sg]
481
482
483 pfn = fn_plt if fn_plt else 'radiation_field'
484 pfn = self.setFnPlt(pfn)
485
486
487 keys_cm = ['Model %i'%(i+1)
488 for i in xrange(len(star_grid))]
489 pfn = Plotting2.plotCols(x=radii,y=cos,cfg=cfg_dict,\
490 filename=pfn,xaxis='$r$ (cm)',\
491 yaxis='$I_D$ (photons /s /cm$^2$ /Hz / sr) ',\
492 figsize=(12.5,8),fontsize_ticklabels=26,\
493 key_location=(0.05,0.05),xlogscale=1,ylogscale=1,\
494 keytags=keys_cm,fontsize_axis=26,fontsize_key=26)
495 print '** Plots can be found at:'
496 print pfn
497 print '***********************************'
498 else:
499 print '** No Chemistry models were calculated successfully.'+\
500 'No temperature profiles can be plotted.'
501 print '***********************************'
502
503
504
505 - def plotAbundanceProfiles(self,star_grid=[],models=[],force_plot=0,cfg='',\
506 fn_plt='',molecules=[],per_molecule=0,frac=1):
507
508 '''
509 Plot abundance profiles for all molecules in every model.
510
511 @keyword star_grid: List of Star() instances. If default, model ids
512 have to be given.
513
514 (default: [])
515 @type star_grid: list[Star()]
516 @keyword models: The model ids, only required if star_grid is []
517
518 (default: [])
519 @type models: list[string]
520 @keyword force_plot: force a plotting if more than models are requested
521
522 (default: 0)
523 @type force_plot: bool
524 @keyword cfg: path to the Plotting2.plotCols config file. If default,
525 the hard-coded default plotting options are used.
526
527 (default: '')
528 @type cfg: string
529 @keyword fn_plt: A base plot filename. Includes folder. If not, a
530 default is added
531
532 (default: '')
533 @type fn_plt: string
534 @keyword molecules: Molecules to be plotted.
535
536 (default: [])
537 @type molecules: bool
538 @keyword per_molecule: Plot one molecule for all models in one figure.
539
540 (default: 0)
541 @type per_molecule: bool
542 @keyword per_model: Plot all molecules for one model in one figure.
543
544 (default: 0)
545 @type per_model: bool
546 @keyword frac: Plot the fractional abundances. If not frac, plot number
547 densities.
548
549 (default: 1)
550 @type frac: bool
551
552
553 '''
554
555 print '***********************************'
556 print '** Plotting Abundance Profiles'
557 if not star_grid and models:
558 star_grid = self.makeStars(models=models)
559 elif (not models and not star_grid) or (models and star_grid):
560 print '** Input is undefined or doubly defined. Aborting.'
561 return
562 pfns = []
563 cfg_dict = Plotting2.readCfg(cfg)
564 if cfg_dict.has_key('filename'):
565 fn_plt = cfg_dict.pop('filename')
566 if cfg_dict.has_key('molecules'):
567 molecules = cfg_dict.pop('molecules')
568 if cfg_dict.has_key('per_molecule'):
569 per_molecule = cfg_dict['per_molecule']
570 if cfg_dict.has_key('per_model'):
571 per_model = cfg_dict['per_model']
572
573
574 extra_pars = dict()
575 extra_pars['ymin'] = 1e-9
576 extra_pars['ymax'] = 1e-3
577 extra_pars['ylogscale'] = 1
578 extra_pars['xlogscale'] = 1
579 extra_pars['figsize'] = (12.5,8.5)
580 extra_pars['xaxis'] = 'cm'
581
582
583 ddata = dict()
584 for istar,star in enumerate(star_grid):
585 if not star['LAST_CHEMISTRY_MODEL']: continue
586 ddata[istar] = dict()
587
588 folder = os.path.join(cc.path.cout,'models',\
589 star['LAST_CHEMISTRY_MODEL'])+'/'
590 ddata[istar]['rad'] = DataIO.getChemistryPhysPar(folder+\
591 'csphyspar.out', 'RADIUS')
592 ddata[istar]['id'] = star['LAST_CHEMISTRY_MODEL']
593 if frac:
594 species = DataIO.getChemistryAbundances(folder+'csfrac.out')
595 else:
596 species = DataIO.getChemistryAbundances(folder+'csnum.out')
597
598 for molec in molecules:
599 ddata[istar][molec] = species[molec]
600
601 if not per_molecule:
602
603 radii = [ddata[istar]['rad']]*len(molecules)
604 abuns = [ddata[istar][molec] for molec in molecules]
605 keytags = molecules
606
607 ids = ddata[istar]['id']
608
609
610 yaxis = '$n_\mathrm{molec}/n_{\mathrm{H}_2}$'
611
612
613 pfn = fn_plt if fn_plt else 'abundance_profiles'
614 suff = '_'.join(list(set(ids)))
615 pfn = self.setFnPlt(pfn,fn_suffix=suff)
616
617 pfns.append(Plotting2.plotCols(x=radii,y=abuns,cfg=cfg_dict,\
618 filename=pfn,keytags=keytags,\
619 plot_title=ids.replace('_','\_'),\
620 yaxis=yaxis,**extra_pars))
621
622 if per_molecule:
623
624
625
626 for molec in molecules:
627
628 radii = [dstar['rad']
629 for istar,dstar in ddata.items()]
630 abuns = [dstar[molec]
631 for istar,dstar in ddata.items()]
632 keytags = [dstar['id'].replace('_','\_')
633 for istar,dstar in ddata.items()]
634
635
636
637 yaxis = '$n_\mathrm{%s}/n_{\mathrm{H}_2}$'%str(molec)
638
639
640 pfn = fn_plt if fn_plt else 'abundance_profiles'
641 pfn = self.setFnPlt(pfn,fn_suffix=molec)
642
643 pfns.append(Plotting2.plotCols(x=radii,y=abuns,yaxis=yaxis,\
644 filename=pfn,keytags=keytags,\
645 cfg=cfg_dict,**extra_pars))
646
647 if not per_molecule and pfns and pfns[0][-4:] == '.pdf':
648 pfn = fn_plt if fn_plt else 'abundance_profiles'
649 pfn = self.setFnPlt(pfn) + '.pdf'
650 DataIO.joinPdf(old=pfns,new=pfn)
651 print '** Plots can be found at:'
652 print pfn
653 print '***********************************'
654 else:
655 print '** Plots can be found at:'
656 print '\n'.join(pfns)
657 print '***********************************'
658