1
2
3 """
4 Some tools for measuring line profiles of emission lines.
5
6 Author: R. Lombaert
7
8 """
9
10 import os
11 import numpy as np
12 from scipy import mean,sqrt,log, std,median
13 from scipy import argmin,argmax,array
14 from scipy.integrate import trapz
15 from matplotlib import pyplot as plt
16 from astropy import units as u
17
18 import cc.path
19 from cc.tools.readers import FitsReader, TxtReader
20 from cc.tools.io import DataIO
21 from cc.plotting import Plotting2
22 from cc.tools.units import Equivalency as eq
23
24 from cc.ivs.sigproc import fit, funclib
25
26
27
29
30 """
31 Read the telescope properties from Telescope.dat.
32
33 This currently includes the telescope size in m, and the default
34 absolute flux calibration uncertainty.
35
36 @param telescope: The telescope requested
37 @type telescope: str
38
39 @return: The telescope size and absolute flux calibration uncertainty
40 @rtype: (float,float)
41
42 """
43
44 all_telescopes = DataIO.getInputData(keyword='TELESCOPE',start_index=5,\
45 filename='Telescope.dat')
46 if 'PACS' in telescope:
47 telescope = 'PACS'
48 else:
49 telescope = telescope
50 try:
51 tel_index = all_telescopes.index(telescope)
52 except ValueError:
53 raise ValueError('%s not found in Telescope.dat.'%telescope)
54
55 size = DataIO.getInputData(keyword='SIZE',start_index=5,\
56 filename='Telescope.dat',\
57 rindex=tel_index)
58 abs_err = DataIO.getInputData(keyword='ABS_ERR',start_index=5,\
59 filename='Telescope.dat',\
60 rindex=tel_index)
61 return (size,abs_err)
62
63
64
66
67 '''
68 Read a line profile, independent of the type of extension.
69
70 @keyword filename: The filename to the data file of the line profile. If
71 None a line profile object is expected.
72
73 (default: None)
74 @type filename: string
75
76 @return: The line profile
77 @rtype: LPDataReader()
78
79 '''
80
81 if filename[-5:] == '.fits':
82 lprof = FitsReader.FitsReader(fn=filename)
83 else:
84 lprof = TxtReader.TxtReader(fn=filename)
85 return lprof
86
87
88
90
91 """
92 Integrate a line profile read from a fits file or a txt file.
93
94 Requires a terminal expansion velocity to determine the window in which the
95 integration is done.
96
97 If a fits file is read, the source velocity is taken from it (if available)
98 If a text file is read, a source velocity needs to be given as input.
99
100 @param vexp: The terminal gas velocity
101 @type vexp: float
102
103 @keyword filename: The filename to the data file of the line profile. If
104 None a line profile object is expected.
105
106 (default: None)
107 @type filename: string
108 @keyword lprof: A line profile object (LPDataReader or inheriting classes)
109 If None, a filename is expected!
110
111 (default: None)
112 @type lprof: LPDataReader()
113 @keyword window: The factor with which vexp is multiplied when selecting
114 the integration window in the velocity grid.
115
116 (default: 1.2)
117 @type window: float
118
119 @return: The integrated intensity of the profile
120 @rtype: float
121
122 """
123
124 if lprof is None:
125 lprof = readLineProfile(filename)
126 vel = lprof.getVelocity()
127 flux = lprof.getFlux()
128 vlsr = lprof.getVlsr()
129 vexp = float(vexp)
130 window = float(window)
131
132 vel_sel = vel[(vel > vlsr - window*vexp)*(vel < vlsr + window*vexp)]
133 flux_sel = flux[(vel > vlsr - window*vexp)*(vel < vlsr + window*vexp)]
134 return trapz(x=vel_sel,y=flux_sel)
135
136
137
138 -def getPeakLPData(filename=None,lprof=None,vlsr=None,method='mean',npoints=5):
139
140 """
141 Calculate the peak value of a line profile read from a fits file or a txt
142 file.
143
144 If a fits file is read, the source velocity is taken from it (if available)
145 If a text file is read, a source velocity needs to be given as input.
146
147 The peak value is defined as the mean of central 5 flux points around the
148 source velocity.
149
150 @keyword filename: The filename to the data file of the line profile. If
151 None a line profile object is expected.
152
153 (default: None)
154 @type filename: string
155 @keyword lprof: A line profile object (LPDataReader or inheriting classes)
156 If None, a filename is expected!
157
158 (default: None)
159 @type lprof: LPDataReader()
160 @keyword vlsr: If you want to provide your own vlsr for some reason. Leave
161 as default if you don't have a good reason to do that.
162
163 (default: None)
164 @type vlsr: float
165 @keyword method: The method applied: either 'mean' or 'fit'. Mean derives
166 the peak value from the mean of the npoints flux points
167 around the vlsr. Fit takes the central peak flux at from
168 the fit.
169
170 (default: 'mean')
171 @type method: str
172 @keyword npoints: The number of points around vlsr used for deriving the
173 peak value via the mean method.
174
175 (default: 5)
176 @type npoints: int
177
178 @return: The peak intensity of the profile
179 @rtype: float
180
181 """
182
183 method = method.lower()
184 if method not in ['mean','fit']:
185 method = 'mean'
186
187
188 if lprof is None:
189 lprof = readLineProfile(filename)
190
191
192
193 if method == 'fit':
194 fit = fitLP(lprof=lprof)
195 return fit['peak']
196
197
198 vel = lprof.getVelocity()
199 flux = lprof.getFlux()
200 if vlsr is None:
201 vlsr = lprof.getVlsr()
202 else:
203 vlsr = float(vlsr)
204
205
206 if npoints%2.==0:
207 npoints = int(npoints/2.)
208 else:
209 npoints = int(npoints/2.)
210
211
212 imid = argmin(np.abs(vel-vlsr))
213 return mean(flux[imid-npoints:imid+npoints+1])
214
215
216
218
219 '''
220 Calculate the FWHM of the line profile.
221
222 @param lprof: the line profile object.
223 @type lprof: LPDataReader()
224
225 @return: the fwhm of the line
226 @rtype: float
227
228 '''
229
230 flux = lprof.getFlux()
231 vel = lprof.getVelocity()
232 vlsr = lprof.getVlsr()
233 maxval = max(flux)
234 i_mid = argmax(flux)
235 flux1 = flux[:i_mid]
236 flux2 = flux[i_mid:]
237 v1 = vel[argmin(abs(flux1-maxval/2.))]
238 v2 = vel[argmin(abs(flux2-maxval/2.))+i_mid]
239 return v2-v1
240
241
242
245
246 """
247 Fit a function to a line profile for different initial guesses of a single
248 parameter.
249
250 The best fit function is returned. Best fit is determined by checking for
251 the smallest relative error for the parameter in question.
252
253 @param vel: The velocity grid
254 @type vel: array
255 @param flux: The intensity grid
256 @type flux: array
257 @param initial: initial parameters (eg [int,vlsr,vexp,gamma] for sp)
258 @type initial: list
259 @param index: Index of initial parameter to be varied
260 @type index: int
261 @param values: The values used for the variable initial parameter
262 @type values: tuple
263 @param vary: Allow initial parameter to be changed in fitting process.
264 Must have same length as initial.
265 @type vary: list[bool]
266
267 @keyword function: The function to be fitted
268
269 (default: funclib.soft_parabola)
270 @type function: funclib.function
271 @keyword vary_window: Vary the velocity window based on the third initial
272 parameter. 1.5 for soft parabola, 3 for other functions
273 centered on the second initial parameter.
274 (mu/vlsr and sigma/vexp respectively)
275
276 (default: 0)
277 @type vary_window: bool
278
279 @return: The model after minimization
280 @rtype: funclib.soft_parabola
281
282 """
283
284 values, initial, vary_window = list(values), list(initial), int(vary_window)
285 all_init = [[p]*len(values) for i,p in enumerate(initial) if i != index]
286 all_init.insert(index,values)
287 if vary_window:
288
289
290
291 window = function == funclib.soft_parabola and 1.5 or 3.
292 results = [fitFunction(vel[np.abs(vel-initi[1])<=(initi[2]*window)],\
293 flux[np.abs(vel-initi[1])<=(initi[2]*window)],\
294 initi,function,vary=vary)
295 for initi in zip(*all_init)]
296 else:
297 results = [fitFunction(vel,flux,initi,function,vary=vary)
298 for initi in zip(*all_init)]
299 rel_errors = [fg.get_parameters()[1][index]/fg.get_parameters()[0][index]
300 for fg in results]
301 sel_results = [res
302 for res,rel_err in zip(results,rel_errors)
303 if rel_err > 10**(-5)]
304 sel_errors = array([rel_err
305 for rel_err in rel_errors
306 if rel_err > 10**(-5)])
307 if not sel_results:
308 sel_results = results
309 sel_errors = array(rel_errors)
310 bestresult = sel_results[argmin(abs(sel_errors))]
311 return bestresult
312
313
314
316
317 """
318 Fit a function to a set of x and y values.
319
320 @param x: The x grid
321 @type x: array
322 @param y: The y grid
323 @type y: array
324 @param initial: initial parameters
325 @type initial: list
326 @param function: The function to be fitted
327 @type function: funclib.function (e.g. funclib.soft_parabola,funclib.gauss)
328 @param vary: Allow initial parameter to be changed in fitting process.
329 Must have same length as initial.
330 @type vary: list[bool]
331
332 @return: The model after minimization
333 @rtype: funclib.function() (some function)
334 """
335
336
337
338
339 if function == funclib.gauss and False in vary:
340 mymodel = function(use_jacobian=False)
341 else:
342 mymodel = function()
343
344 mymodel.setup_parameters(values=initial,vary=vary)
345
346 result = fit.minimize(x,y,mymodel)
347 return mymodel
348
349
350
352
353 """
354 Check the shape of the line profile, to see if any irregular patterns are
355 present.
356
357 Based on the diff() method, and the std on the result of it. If sharp
358 patterns are present, they should be picked up by this method, and an extra
359 component can be included in fitting the line.
360
361 Detects absorption irregularities, not emission! At least, it tries to
362 filter the emission effects out. If an emission effect is stronger than
363 an absorption effect, it should also not detect any irregularities.
364
365 Currently checks whether a strong downward trend in the flux is associated
366 with a strong upward trend, within a window of 6 km/s. Broader "absorption
367 detections" are unlikely, since ISM absorption lines should not have a line
368 width that is broader than, e.g., 3 km/s (i.e. turbulent velocity).
369
370 Still being tested!
371
372 @param vel: The velocity grid
373 @type vel: array
374 @param flux: The flux grid
375 @type flux: array
376 @param vlsr: the central source velocity
377 @type vlsr: float
378 @param vexp: The expected gas terminal velocity
379 @type vexp: float
380
381 @keyword window: The window for line selection. Value is multiplied with
382 0.6. For the usual window of 2., this is 1.2 (SP). For the
383 Gaussian window of 3., this is 1.8.
384
385 (default: 2.)
386 @type window: float
387 @keyword show: Show the results of the diff and std methods.
388
389 (default: 0)
390 @type show: bool
391
392 @return: The details of the absorption irregularity. Assuming a Gaussian,
393 a depth, mid point velocity, a width and a continuum value are
394 returned. If no irregularity is found, None is returned
395 @rtype: tuple(float)
396
397 """
398
399
400 velres = np.median(np.diff(vel))
401
402
403 fdf = np.diff(flux)
404 velfdf = vel[1:]
405 fluxfdf = flux[1:]
406
407
408
409
410
411
412 if window == 2: window_factor = 0.8
413 else: window_factor = 0.5
414 fdfwhereline = np.abs(velfdf-vlsr)<=window*window_factor*vexp
415
416
417
418
419
420 i = window
421 fdfwindow = np.abs(velfdf-vlsr)<=i*vexp
422 while len(velfdf[-fdfwhereline*fdfwindow]) < 60 and i != 6:
423 i += 1
424 fdfwindow = np.abs(velfdf-vlsr)<=i*vexp
425
426
427 noiseflux = std(fluxfdf[-fdfwhereline*fdfwindow])
428 fdfcleanflux = fluxfdf<3.*noiseflux
429
430
431 noisedf = std(fdf[-fdfwhereline*fdfwindow*fdfcleanflux])
432
433
434 if show:
435 plt.clf()
436 velfdfplot = velfdf[fdfwindow]
437 fluxfdfplot = fluxfdf[fdfwindow]
438 plt.step(velfdfplot,fluxfdfplot,'-r',lw=3,where='mid',\
439 label='Observed profile')
440 cleanflux = fluxfdf.copy()
441 cleanflux[-(-fdfwhereline*fdfwindow*fdfcleanflux)] = np.nan
442 plt.step(velfdf,cleanflux,'-k',lw=2,where='mid',label='Clean noise')
443 plt.plot(velfdf[fdfwindow],fdf[fdfwindow],'b-',lw=3,\
444 label='diff(profile)')
445 plt.plot([velfdfplot[0],velfdfplot[-1]],[noisedf*3,noisedf*3],'--k',\
446 label='Upper df limit')
447 plt.plot([velfdfplot[0],velfdfplot[-1]],[-noisedf*3,-noisedf*3],'--k',\
448 label='Lower df limit')
449 ax = plt.gca()
450 ax.axvline(x=vlsr-window*window_factor*vexp,linewidth=2, ls='--',\
451 color='k')
452 ax.axvline(x=vlsr+window*window_factor*vexp,linewidth=2, ls='--',\
453 color='k')
454 leg = plt.legend(loc='best',fancybox=True)
455 leg.get_frame().set_alpha(0.5)
456 plt.show()
457
458
459
460 fdf_large = np.abs(fdf[fdfwhereline]) >= 3.*noisedf
461
462 if fdf_large.any():
463 imin = argmin(fdf[fdfwhereline])
464 imax = argmax(fdf[fdfwhereline])
465
466 if not (fdf_large[imin] and fdf_large[imax]):
467 return None
468
469
470
471
472
473
474 if imin < imax and (imax-imin)*velres < 5.:
475
476
477
478 velline = velfdf[fdfwhereline]
479 width = velline[imax] - velline[imin]
480
481 sigma = width/(2.*sqrt(2.*log(2.)))
482
483 velmid = (velline[imax] + velline[imin])/2.
484
485
486
487 interval = np.abs(velfdf-velmid) <= width
488 fmax = max(fluxfdf[interval])
489 fmin = min(fluxfdf[interval])
490 depth = -abs(fmax - fmin)
491
492
493 return (depth,velmid,sigma/2.,0)
494 else:
495
496 return None
497 else:
498 return None
499
500
501
502
503 -def fitLP(filename=None,lprof=None,theory=0,show=0,cfg='',convert_ms_kms=0,\
504 vary_pars=['vexp'],i_vexp=15.0,i_gamma=1.0,do_gauss=0):
505
506 '''
507 Fit a line profile with a soft parabola, and a Gaussian component if
508 required.
509
510 The method automatically checks if a second component is needed (eg an
511 extra absorption component). An estimate of the expansion velocity (width
512 of the profile) and an improved guess of the vlsr are given.
513
514 A guess for the gas terminal velocity is returned, as well as its error and
515 the fitted profile (sp/gaussian, and if applicable extra gaussian and the
516 full fit).
517
518 @keyword filename: The filename to the data file of the line profile. If
519 None a line profile object is expected.
520
521 (default: None)
522 @type filename: string
523 @keyword lprof: A line profile object (LPDataReader or inheriting classes)
524 If None, a filename is expected! If not None, the results
525 are saved in this object as well as returned upon method
526 call
527
528 (default: None)
529 @type lprof: LPDataReader()
530 @keyword convert_ms_kms: Convert velocity grid from m/s to km/s.
531
532 (default: 0)
533 @type convert_ms_kms: bool
534 @keyword theory: If theoretical profile, and filename is given, set vlsr to
535 0 and read two columns. lprof not relevant if True.
536
537 (default: 0)
538 @type theory: bool
539 @keyword vary_pars: The soft parabola parameters varied (can only be vexp
540 or gamma for now). The initial values for parameters
541 listed here are not used. If 'gamma' is requested, a
542 reasonable guess for i_vexp when calling the method
543 will improve the fitting results. This is done for the
544 first guess only! If a Gaussian absorption is present
545 improving these first guesses won't make much of a
546 difference. However, the first guess value for gamma
547 is still used. Vexp is always varied if absorption is
548 present.
549
550 (default: ['vexp'])
551 @type vary_pars: list[string]
552 @keyword i_vexp: The initial guess for the expansion velocity. Not relevant
553 if vexp is included in vary_pars.
554
555 (default: 15.0)
556 @type i_vexp: float
557 @keyword i_gamma: The initial guess for the gamma parameter of soft parab.
558 Not relevant if gamma is included in vary_pars.
559
560 (default: 1.0)
561 @type i_gamma: float
562 @keyword do_gauss: Force a Gaussian fit regardless of soft parabola fit
563 results. Still does the soft parabola fit first to allow
564 for comparison of parameters.
565
566 (default: 0)
567 @type do_gauss: bool
568 @keyword show: Show the results of the fit
569
570 (default: 0)
571 @type show: bool
572
573 @return: dictionary including [vexp,evexp,gamma,egamma,fitprof,gaussian,\
574 fullfit,dintint,fgintint]
575 @rtype: dict[float,float,float,float,funclib.Function(),\
576 funclib.Function(),funclib.Function()]
577
578 '''
579
580 print '*******************************************'
581 if theory and not filename is None:
582 d = DataIO.readCols(filename=filename)
583 vel = d[0]
584 flux = d[1]
585 vlsr = 0.0
586 else:
587 if filename is None:
588 filename = lprof.filename
589 print '** Fitting line profile in %s.'%filename
590 if lprof is None:
591 lprof = readLineProfile(filename)
592 vel = lprof.getVelocity()
593 flux = lprof.getFlux()
594 vel = vel[-np.isnan(flux)]
595 flux = flux[-np.isnan(flux)]
596 vlsr = lprof.getVlsr()
597
598 if convert_ms_kms:
599 vel = vel/1000.
600
601
602
603
604 i_mid = argmin(np.abs(vel-vlsr))
605 peak = mean(flux[i_mid-2:i_mid+3])
606
607
608
609
610
611 if 'gamma' in vary_pars:
612 igammas = array([-0.5,-0.1,0.1,0.5,1.0,2.0,4.0])
613 firstguess = varyInitialFit(vel,flux,[peak,vlsr,i_vexp,0.0],index=3,\
614 values=igammas,vary_window=1,vary=[1,1,1,1],\
615 function=funclib.soft_parabola)
616 i_gamma = firstguess.get_parameters()[0][3]
617
618
619 ivexps = array([50.,40.,30.,25.,20.,15.,10.])
620 if 'vexp' in vary_pars:
621 firstguess = varyInitialFit(vel,flux,[peak,vlsr,0.,i_gamma],index=2,\
622 values=ivexps,vary_window=1,vary=[1,1,1,1],\
623 function=funclib.soft_parabola)
624
625 vexp = abs(firstguess.get_parameters()[0][2])
626 window = 2.
627 print 'First guess fit, using a soft parabola:'
628 print firstguess.param2str(accuracy=5)
629
630
631
632
633 if vexp > 100: vexp = 50.
634
635
636
637
638 keep = np.abs(vel-vlsr)<=(2*window*vexp)
639 velsel,fluxsel = vel[keep],flux[keep]
640 include_gauss = checkLPShape(velsel,fluxsel,vlsr,vexp,window,show=show)
641
642
643
644 if not include_gauss is None:
645
646
647 ivexps = list(ivexps)
648 initial = [peak,vlsr,0.,i_gamma]
649 all_init = [[p]*len(ivexps) for i,p in enumerate(initial) if i != 2]
650 all_init.insert(2,ivexps)
651 functions = [funclib.soft_parabola() for i in ivexps]
652 [ff.setup_parameters(values=initi)
653 for ff,initi in zip(functions,zip(*all_init))]
654
655 gaussians = [funclib.gauss() for ff in functions]
656
657
658 [gg.setup_parameters(values=include_gauss,vary=[True,True,True,False])
659 for gg in gaussians]
660
661 mymodels = [fit.Model(functions=[ff,gg])
662 for ff,gg in zip(functions,gaussians)]
663 [fit.minimize(vel[np.abs(vel-vlsr)<=(init[2]*1.5)],\
664 flux[np.abs(vel-vlsr)<=(init[2]*1.5)],\
665 mymodel)
666 for mymodel,init in zip(mymodels,zip(*all_init))]
667
668 mymodels = [fg
669 for fg in mymodels
670 if fg.get_parameters()[1][2] != 0.]
671 functions = [ff
672 for fg,ff in zip(mymodels,functions)
673 if fg.get_parameters()[1][2] != 0.]
674 gaussians = [gg
675 for fg,gg in zip(mymodels,gaussians)
676 if fg.get_parameters()[1][2] != 0.]
677 fitvalues = array([fg.get_parameters()[0][2]
678 for fg in mymodels])
679 fiterrors = array([fg.get_parameters()[1][2]
680 for fg in mymodels])
681 mymodel = mymodels[argmin(abs(fiterrors/fitvalues))]
682 finalfit = functions[argmin(abs(fiterrors/fitvalues))]
683 gaussian = gaussians[argmin(abs(fiterrors/fitvalues))]
684 print 'Improved fit, including extra Gaussian:'
685 print mymodel.param2str(accuracy=5)
686 else:
687
688
689 if 'gamma' in vary_pars:
690 finalfit = varyInitialFit(vel,flux,[peak,vlsr,vexp,0.0],\
691 index=3,values=igammas,vary_window=1,\
692 function=funclib.soft_parabola,\
693 vary=[True,True,True,True])
694 print 'Final fit with soft parabola, second gamma iteration:'
695 print finalfit.param2str(accuracy=5)
696
697 else:
698 finalfit = firstguess
699
700
701
702
703 vexp = abs(finalfit.get_parameters()[0][2])
704 evexp = abs(finalfit.get_parameters()[1][2])
705 gamma = finalfit.get_parameters()[0][3]
706 egamma = finalfit.get_parameters()[1][3]
707
708
709
710 if (evexp/vexp > 0.40 and gamma > 0) or (evexp/vexp > 0.20 and vexp> 30.) \
711 or do_gauss:
712
713
714
715 do_gauss = 1
716 include_gauss = None
717
718 sigmas = 2*ivexps/(2.*sqrt(2.*log(2.)))
719 finalfit = varyInitialFit(vel,flux,[peak,vlsr,0.,0.],index=2,\
720 values=sigmas,function=funclib.gauss,\
721 vary_window=1,vary=[True,True,True,False])
722 vexp = abs(finalfit.get_parameters()[0][2])*(2.*sqrt(2.*log(2.)))/2.
723 evexp = abs(finalfit.get_parameters()[1][2])*(2.*sqrt(2.*log(2.)))/2.
724 gamma, egamma = None,None
725 window = 3.
726 print 'Improved fit, using a gaussian instead of soft parabola:'
727 print finalfit.param2str(accuracy=5)
728
729
730 peak = finalfit.get_parameters()[0][0]
731 epeak = finalfit.get_parameters()[1][0]
732 fvlsr = finalfit.get_parameters()[0][1]
733 fevlsr = finalfit.get_parameters()[1][1]
734
735
736
737
738 keep = np.abs(vel-vlsr)<=(0.6*window*vexp)
739 velsel = vel[keep]
740 flux_first = firstguess.evaluate(velsel)
741 flux_final = finalfit.evaluate(velsel)
742 dimb = trapz(y=flux[keep],x=velsel)
743 fi_final = trapz(y=flux_final,x=velsel)
744 print('I_mb (emission line data): %f'\
745 %dimb)
746 print('I_mb (SP -- initial guess): %f'\
747 %trapz(y=flux_first,x=velsel))
748 print('I_mb (SP -- final guess): %f'\
749 %fi_final)
750 if not include_gauss is None:
751 fitted_flux = mymodel.evaluate(velsel)
752 print('I_mb (SP + Gauss fit): %f'\
753 %trapz(y=fitted_flux,x=velsel))
754 print('Final v_exp guess: %.4f +/- %.4f km/s'%(vexp,evexp))
755 if not gamma is None:
756 print('Final gamma guess: %.4f +/- %.4f'%(gamma,egamma))
757 print('Final vlsr guess: %.4f +/- %.4f'%(fvlsr,fevlsr))
758 print('Final peak Tmb guess at v_lsr: %.4f +/- %.4f K'%(peak,epeak))
759 fwhm = getLPDataFWHM(lprof)
760 print('The FWHM is %.2f km/s.'%(fwhm))
761
762
763 if show or cfg:
764 plt.clf()
765
766 keep = np.abs(vel-vlsr)<=(1.5*window*vexp)
767 velsel,fluxsel = vel[keep],flux[keep]
768 vel_highres = np.linspace(velsel[0],velsel[-1],10000)
769 flux_final_highres = finalfit.evaluate(vel_highres)
770 flux_first_highres = firstguess.evaluate(vel_highres)
771 if not include_gauss is None:
772 flux_full_highres = mymodel.evaluate(vel_highres)
773 if show:
774 plt.step(velsel,fluxsel,'-r',where='mid',lw=3,\
775 label='Observed profile')
776 plt.plot(vel_highres,flux_first_highres,'b-',lw=3,\
777 label='First guess')
778 plt.plot(vel_highres,flux_final_highres,'g--',lw=3,\
779 label='Improved guess')
780 if not include_gauss is None:
781 plt.plot(vel_highres,flux_full_highres,'g-',lw=2,\
782 label='Full fit (including Gaussian)')
783 leg = plt.legend(loc='best',fancybox=True)
784 leg.get_frame().set_alpha(0.5)
785 plt.show()
786 if cfg:
787 pf = '%s_fitted_%s'%(do_gauss and 'gaussFit' or 'SPFit',\
788 os.path.split(filename)[1])
789 keytags = ['Observed profile','Improved guess']
790 line_types = ['-r','-b',]
791 x = [velsel,vel_highres]
792 y = [fluxsel,flux_final_highres]
793 if not include_gauss is None:
794 line_types.append('g--')
795 x.append(vel_highres)
796 y.append(flux_full_highres)
797 keytags.append('Full fit (including Gaussian)')
798 pf = Plotting2.plotCols(x=x,y=y,filename=pf,cfg=cfg,linewidth=5,\
799 yaxis='$T_\mathrm{mb}\ (\mathrm{K})$',\
800 xaxis='$v (\mathrm{km}/\mathrm{s})$',\
801 keytags=keytags,line_types=line_types,\
802 histoplot=[0])
803 print 'Your figure can be found at %s .'%pf
804
805 results = dict()
806
807 results['do_gauss'] = do_gauss
808
809 results['vlsr'] = fvlsr
810 results['evlsr'] = fevlsr
811 results['vexp'] = vexp
812 results['evexp'] = evexp
813 results['fwhm'] = fwhm
814 results['peak'] = peak
815 results['epeak'] = epeak
816
817
818 results['gamma'] = gamma
819 results['egamma'] = egamma
820
821
822 results['fgintint'] = fi_final
823 results['dintint'] = dimb
824 results['intwindow'] = window*0.6
825
826
827
828 results['fitprof'] = (do_gauss and 'gauss' or 'soft_parabola',\
829 list(finalfit.get_parameters()[0]))
830 if not include_gauss is None:
831 results['fitabs'] = ('gauss',list(gaussian.get_parameters()[0]))
832 else:
833 results['fitabs'] = None
834
835 return results
836