Commit b58e95699323617a2f84fdcc25c92eb0b727591c
1 parent
ab47fb7c
Exists in
master
First commit
Showing
4 changed files
with
817 additions
and
0 deletions
Show diff stats
... | ... | @@ -0,0 +1,319 @@ |
1 | +PRO dustem_fit_intensity_emiles_example,model=model $ | |
2 | + ,sed_file=sed_file $ | |
3 | + ,Nitermax=Nitermax $ | |
4 | + ,postscript=postscript $ | |
5 | + ,fits_save=fits_save $ | |
6 | + ,help=help $ | |
7 | + ,wait=wait $ | |
8 | + ,noobj=noobj $ | |
9 | + ,verbose=verbose | |
10 | + | |
11 | +;+ | |
12 | +; NAME: | |
13 | +; dustem_fit_intensity_emiles_example | |
14 | +; | |
15 | +; PURPOSE: | |
16 | +; This routine is an example of how to fit an observational SED | |
17 | +; (StokesI only) with DustEM and DustEMWrap, and using the EMiles Strellar template pluggin | |
18 | +; | |
19 | +; For this example, the code uses the SED in the file example_SED_1.xcat, | |
20 | +; which is distributed in the Data/EXAMPLE_OBSDATA/ directory | |
21 | +; | |
22 | +; The example SED has Stokes I photometric data points from | |
23 | +; IRAC, MIPS and IRAS. Examples illustrating running DustEMWrap to | |
24 | +; fit spectral data, polarisation data and extinction data | |
25 | +; are provided in other _example routines in the src/idl/ | |
26 | +; directory. See the DustEMWrap User Guide for more information. | |
27 | +; | |
28 | +; CATEGORY: | |
29 | +; DustEMWrap, Distributed, High-Level, User Example | |
30 | +; | |
31 | +; CALLING SEQUENCE: | |
32 | +; dustem_fit_intensity_emiles_example[,model=][sed_file=][,postscript=][,Nitermax=][,fits_save=][,/help,/wait,/verbose] | |
33 | +; | |
34 | +; INPUTS: | |
35 | +; None | |
36 | +; | |
37 | +; OPTIONAL INPUT PARAMETERS: | |
38 | +; None | |
39 | +; | |
40 | +; OUTPUTS: | |
41 | +; None | |
42 | +; | |
43 | +; OPTIONAL OUTPUT PARAMETERS: | |
44 | +; Plots, results structure in binary FITS table format | |
45 | +; | |
46 | +; ACCEPTED KEY-WORDS: | |
47 | +; model = specifies the interstellar dust mixture used by | |
48 | +; DustEM. See userguide or dustem_test_model_exists.pro | |
49 | +; for more details about available models in current release. | |
50 | +; sed_file = string naming the path to text file in .xcat format that | |
51 | +; describes the observational SED. If not set, the file | |
52 | +; 'Data/EXAMPLE_OBSDATA/example_SED_1.xcat' is used. | |
53 | +; postscript = if set, final plot is saved as postscript file | |
54 | +; Nitermax = maximum number of fit iterations. Default is 5. | |
55 | +; fits_save = if set, save the fit results in a binary | |
56 | +; FITS file. | |
57 | +; help = if set, print this help | |
58 | +; wait = if set, wait this many seconds between each step of | |
59 | +; the code (for illustration purposes) | |
60 | +; verbose = if set, subroutines will run in verbose mode | |
61 | +; noobj = if set, runs with no object graphics | |
62 | +; | |
63 | +; COMMON BLOCKS: | |
64 | +; None | |
65 | +; | |
66 | +; SIDE EFFECTS: | |
67 | +; None | |
68 | +; | |
69 | +; RESTRICTIONS: | |
70 | +; The DustEM fortran code must be installed | |
71 | +; The DustEMWrap IDL code must be installed | |
72 | +; | |
73 | +; PROCEDURES AND SUBROUTINES USED: | |
74 | +; | |
75 | +; EXAMPLES | |
76 | +; dustem_fit_intensity_example | |
77 | +; dustem_fit_intensity_example,Nitermax=1,fits_save='/tmp/mysavefile.fits' | |
78 | +; dustem_fit_intensity_example,model='DBP90' | |
79 | +; | |
80 | +; MODIFICATION HISTORY: | |
81 | +; Written by JPB Apr-2011 | |
82 | +; Evolution details on the DustEMWrap gitlab. | |
83 | +; See http://dustemwrap.irap.omp.eu/ for FAQ and help. | |
84 | +;- | |
85 | + | |
86 | +IF keyword_set(help) THEN BEGIN | |
87 | + doc_library,'dustem_fit_intensity_emiles_example' | |
88 | + goto,the_end | |
89 | +END | |
90 | + | |
91 | +IF keyword_set(model) THEN BEGIN | |
92 | + use_model=strupcase(model) | |
93 | +ENDIF ELSE BEGIN | |
94 | + use_model='DBP90' ;Example with default keywords uses the DBP90 model | |
95 | +ENDELSE | |
96 | + | |
97 | +exists=dustem_test_model_exists(use_model) | |
98 | +if exists ne 1 then $ | |
99 | + message,'Unknown dust model' | |
100 | + | |
101 | +use_polarization=0 ; initialize Dustemwrap in no polarization mode | |
102 | +use_window=2 ; default graphics window number to use for plotting the results | |
103 | +use_verbose=0 | |
104 | +if keyword_set(verbose) then use_verbose=1 | |
105 | +use_Nitermax=5 ; maximum number of iterations for the fit | |
106 | +IF keyword_set(Nitermax) THEN use_Nitermax=Nitermax | |
107 | + | |
108 | +dustem_define_la_common | |
109 | + | |
110 | +;=== Set the (model-dependent) parameters that you want to fit (pd), | |
111 | +;=== their initial values (iv) | |
112 | +;=== and whether they are bounded (ulimed,llimed,llims,ulims). | |
113 | +;=== Fixed parameters (fpd) and their values (fiv) are also set here. | |
114 | +;=== Refer to the DustEM and DustEMWrap User guides for an explanation | |
115 | +;=== of the physical meaning of dust model and plug-in parameters, and | |
116 | +;=== how to specify them. | |
117 | + | |
118 | +;=== Examples are provided for some of the dust models. | |
119 | +;=== To try them, uncomment the model that you want to try and re-run | |
120 | + | |
121 | +;=== AN EXAMPLE FOR DBP90 | |
122 | +;=== Here we fit the dust abundances of the DBP90 model, the | |
123 | +;=== intensity of the dust-heating radiation field, as well as a plug-in | |
124 | +;=== for synchrotron emission | |
125 | +;=== The free parameters are all lower-bounded at zero. | |
126 | +;=== use_model='DBP90' ; you should specify this above! | |
127 | + | |
128 | +age_values=[0.03, 0.05, 0.08, 0.15, 0.25, 0.40, 0.60, 1.0, 1.75, 3.0, 5.0, 8.5, 13.5] | |
129 | +metalicity_values=[-1.49, -0.96, -0.35, +0.06, +0.26, +0.4] | |
130 | +Nage=n_elements(age_values) | |
131 | +Nmetalicity=n_elements(metalicity_values) | |
132 | +ia=where(age_values EQ 0.2500,counta) | |
133 | +iz=where(metalicity_values EQ -0.35,countb) | |
134 | +ij=lonarr(1,2) | |
135 | +ij[0,0]=ia & ij[0,1]=iz | |
136 | +ind1=ij2index(ij,[Nage,Nmetalicity])+1 | |
137 | +ia=where(age_values EQ 0.05,counta) | |
138 | +iz=where(metalicity_values EQ +0.06,countb) | |
139 | +ij=lonarr(1,2) | |
140 | +ij[0,0]=ia & ij[0,1]=iz | |
141 | +ind2=ij2index(ij,[Nage,Nmetalicity])+1 | |
142 | + | |
143 | +; pd = [ $ | |
144 | +; '(*!dustem_params).G0', $ ;G0 | |
145 | +; '(*!dustem_params).grains(0).mdust_o_mh',$ ;PAH0 mass fraction | |
146 | +; '(*!dustem_params).grains(1).mdust_o_mh',$ ;VSG mass fraction | |
147 | +; '(*!dustem_params).grains(2).mdust_o_mh',$ ;BG mass fraction | |
148 | +; 'dustem_plugin_emiles_stellar_continuum_'+strtrim(ind1[0]+1,2), $ ;Emiles coefficient for 0.25Gyr,Z/H=-0.35 | |
149 | +; 'dustem_plugin_emiles_stellar_continuum_'+strtrim(ind2[0]+1,2)] ;Emiles coefficient for 0.05Gyr,Z/H=+0.06 | |
150 | + | |
151 | +; ; initial values vector for run without synchrotron plugin | |
152 | +; iv = [1.6, 2.2e-4, 5.7e-4, 3.4e-3,100.,100.] | |
153 | + | |
154 | +pd = [ $ | |
155 | + '(*!dustem_params).G0', $ ;G0 | |
156 | + '(*!dustem_params).grains(0).mdust_o_mh',$ ;PAH0 mass fraction | |
157 | + '(*!dustem_params).grains(1).mdust_o_mh',$ ;VSG mass fraction | |
158 | + '(*!dustem_params).grains(2).mdust_o_mh',$ ;BG mass fraction | |
159 | + 'dustem_plugin_emiles_stellar_continuum_1', $ ;tau factor to apply for reddening [-] | |
160 | + 'dustem_plugin_emiles_stellar_continuum_'+strtrim(ind1[0]+1,2), $ ;Emiles coefficient for 0.25Gyr,Z/H=-0.35 | |
161 | + 'dustem_plugin_emiles_stellar_continuum_'+strtrim(ind2[0]+1,2)] ;Emiles coefficient for 0.05Gyr,Z/H=+0.06 | |
162 | + | |
163 | +iv = [1.6, 2.2e-4, 5.7e-4, 3.4e-3,0.5,33.,31.] | |
164 | +Npar=n_elements(pd) | |
165 | +ulimed=replicate(0,Npar) | |
166 | +llimed=replicate(1,Npar) | |
167 | +llims=replicate(1.e-15,Npar) | |
168 | +ulims=replicate(1.e-15,Npar) | |
169 | +ulimed[4]=1. & ulims[4]=1. | |
170 | +fpd=[] & fiv=[] | |
171 | + | |
172 | +; pd = [ $ | |
173 | +; '(*!dustem_params).G0', $ ;G0 | |
174 | +; '(*!dustem_params).grains(0).mdust_o_mh',$ ;PAH0 mass fraction | |
175 | +; '(*!dustem_params).grains(1).mdust_o_mh',$ ;VSG mass fraction | |
176 | +; '(*!dustem_params).grains(2).mdust_o_mh',$ ;BG mass fraction | |
177 | +; 'dustem_plugin_phangs_stellar_continuum_1', $ ;tau factor to apply for reddening [-] | |
178 | +; 'dustem_plugin_phangs_stellar_continuum_'+strtrim(ind1[0]+1,2), $ ;Emiles coefficient for 0.25Gyr,Z/H=-0.35 | |
179 | +; 'dustem_plugin_phangs_stellar_continuum_'+strtrim(ind2[0]+1,2)] ;Emiles coefficient for 0.25Gyr,Z/H=-0.35 | |
180 | +; ; | |
181 | +; ; initial values vector for run without synchrotron plugin | |
182 | +; iv = [1.6, 2.2e-4, 5.7e-4, 3.4e-3,0.1,100.,100.] | |
183 | +; Npar=n_elements(pd) | |
184 | +; ulimed=replicate(0,Npar) | |
185 | +; llimed=replicate(1,Npar) | |
186 | +; llims=replicate(1.e-15,Npar) | |
187 | +; ulims=replicate(1.e-15,Npar) | |
188 | +; fpd=[] & fiv=[] | |
189 | + | |
190 | + | |
191 | +if keyword_set(wait) then begin | |
192 | + message,'Finished setting dust model and plug-in parameters: '+use_model,/info | |
193 | + wait,wait | |
194 | +end | |
195 | + | |
196 | +;== INITIALISE DUSTEM | |
197 | +dustem_init,model=use_model,polarization=use_polarization | |
198 | +!dustem_nocatch=1 | |
199 | +!dustem_verbose=use_verbose | |
200 | +IF keyword_set(noobj) THEN !dustem_noobj=1 | |
201 | +!EXCEPT=2 ; for debugging | |
202 | + | |
203 | +;=== READ EXAMPLE SED DATA | |
204 | +dir=!dustem_wrap_soft_dir+'/Data/EXAMPLE_OBSDATA/' | |
205 | +file=dir+'example_SED_5.xcat' | |
206 | +IF keyword_set(sed_file) THEN file=sed_file | |
207 | +sed=read_xcat(file,/silent) | |
208 | + | |
209 | +if keyword_set(wait) then begin | |
210 | + message,'Finished reading SED data: '+file,/info | |
211 | + wait,wait | |
212 | +end | |
213 | + | |
214 | +;;=== ADJUST THE UNCERTAINTIES FROM WITHIN THE CODE (FOR ILLUSTRATION) | |
215 | +ind=where(sed.sigmaII LT (0.2*sed.StokesI)^2,count) | |
216 | +IF count NE 0 THEN sed[ind].sigmaII=(0.2*sed[ind].StokesI)^2 | |
217 | + | |
218 | +;== SET THE OBSERVATIONAL STRUCTURE | |
219 | +;== sed is passed twice in the call -- the first occurrence is the SED that you | |
220 | +;== wish to fit, the second occurrence is the SED that you wish to visualise. | |
221 | +dustem_set_data,m_fit=sed,m_show=sed | |
222 | + | |
223 | +;== SET INITIAL VALUES AND LIMITS OF THE PARAMETERS THAT WILL BE | |
224 | +;== ADJUSTED DURING THE FIT | |
225 | +dustem_init_params,use_model,pd,iv,fpd=fpd,fiv=fiv,ulimed=ulimed,llimed=llimed,ulims=ulims,llims=llims | |
226 | + | |
227 | + | |
228 | +if keyword_set(wait) then begin | |
229 | + message,'Finished initializing DustEMWrap, including plugins and fixed parameters',/info | |
230 | + wait,wait | |
231 | +end | |
232 | + | |
233 | +;=== INFORMATION TO RUN THE FIT | |
234 | +tol=1.e-16 ;fit tolerence | |
235 | + | |
236 | +;=== INFORMATION TO MAKE THE PLOT | |
237 | +yr=[1.00e-4,1.00E2] ; y-axis limits | |
238 | +xr=[1.00E-1,6.00e4] ; x-axis limits | |
239 | +tit='FIT INTENSITY EXAMPLE' ; plot title | |
240 | +ytit=textoidl('I_\nu (MJy/sr) for N_H=10^{20} H/cm^2') ; y-axis title | |
241 | +xtit=textoidl('\lambda (\mum)') ; x-axis title | |
242 | + | |
243 | + | |
244 | +;=== RUN THE FIT | |
245 | +t1=systime(0,/sec) | |
246 | +res=dustem_mpfit_data(tol=tol,Nitermax=use_Nitermax,gtol=gtol $ | |
247 | + ,/xlog,/ylog,xr=xr,yr=yr,xtit=xtit,ytit=ytit,title=tit $ | |
248 | + ,legend_xpos=legend_xpos,legend_ypos=legend_ypos $ | |
249 | + ,errors=errors,chi2=chi2,rchi2=rchi2,show_plot=show_plot) | |
250 | +t2=systime(0,/sec) | |
251 | + | |
252 | +if keyword_set(wait) then begin | |
253 | + message,'Finished running DustEMWrap, using Niters: '+strtrim(string(use_Nitermax),2),/info | |
254 | + message,'Time taken [sec]: '+sigfig(t2-t1,2,/sci),/info | |
255 | + wait,wait | |
256 | +end | |
257 | + | |
258 | +;=== MAKE THE FINAL PLOT | |
259 | +IF keyword_set(postscript) THEN BEGIN | |
260 | +; dir_ps='./' | |
261 | + mydevice=!d.name | |
262 | + set_plot,'PS' | |
263 | +; ps_file=dir_ps+postscript | |
264 | + ps_file=postscript | |
265 | + device,filename=ps_file,/color | |
266 | +ENDIF | |
267 | + | |
268 | +;stop | |
269 | + | |
270 | +IF !dustem_noobj THEN BEGIN | |
271 | + dustemwrap_plot_noobj,*(*!dustem_fit).CURRENT_PARAM_VALUES,st=dummy,xr=xr,/xstyle,yr=yr,/ysty,/ylog,/xlog,title=tit+' (Final fit)' | |
272 | + ENDIF ELSE BEGIN | |
273 | + dustemwrap_plot,*(*!dustem_fit).CURRENT_PARAM_VALUES,st=dummy,xr=xr,/xstyle,yr=yr,/ysty,/ylog,/xlog,title=tit+' (Final fit)' | |
274 | +ENDELSE | |
275 | + | |
276 | +IF keyword_set(postscript) THEN BEGIN | |
277 | + device,/close | |
278 | + set_plot,mydevice | |
279 | + message,'Wrote '+ps_file,/info | |
280 | +ENDIF | |
281 | + | |
282 | +if keyword_set(wait) then begin | |
283 | + message,'Made the plot of the final results',/info | |
284 | + wait,wait | |
285 | +end | |
286 | + | |
287 | +IF keyword_set(fits_save) THEN BEGIN | |
288 | + message,'Writing out results structure: '+fits_save,/info | |
289 | + dustem_write_fits_table,filename=fits_save,help=help | |
290 | +;=== At this point, you could erase all dustem system variables, or exit idl... all the | |
291 | +;=== information needed to recover the results and remake the plots has been saved in the FITS table | |
292 | + | |
293 | +;=== Moved the following to dustem_fits_io_example | |
294 | + ;; dustem_read_fits_table,filename=fits_save,dustem_st=dustem_spectra_st | |
295 | + ;; ;stop | |
296 | + ;; ;!dustem_show=ptr_new(*!dustem_data) ;test | |
297 | + ;; !dustem_noobj=1 | |
298 | + ;; ;==== plot result taken from the saved fits table | |
299 | + ;; res=*(*!dustem_fit).CURRENT_PARAM_VALUES | |
300 | + ;; IF !dustem_noobj THEN BEGIN | |
301 | + ;; ;dustemwrap_plot_noobj,res,st=dustem_spectra_st,xr=xr,/xstyle,yr=yr,/ysty,/ylog,/xlog,title=tit+' (From Saved FITS file)' | |
302 | + ;; dustemwrap_plot_noobj,res,xr=xr,/xstyle,yr=yr,/ysty,/ylog,/xlog,title=tit+' (From Saved FITS file)' | |
303 | + ;; ENDIF ELSE BEGIN | |
304 | + ;; ;dustemwrap_plot,res,st=dustem_spectra_st,xr=xr,/xstyle,yr=yr,/ysty,/ylog,/xlog,title=tit+' (From Saved FITS file)' | |
305 | + ;; dustemwrap_plot,res,xr=xr,/xstyle,yr=yr,/ysty,/ylog,/xlog,title=tit+' (From Saved FITS file)' | |
306 | + ;; ENDELSE | |
307 | + ;; ;stop | |
308 | + | |
309 | + IF keyword_set(wait) THEN BEGIN | |
310 | + message,'Saved the results as FITS in the file: '+fits_save,/info | |
311 | + wait,wait | |
312 | + ENDIF | |
313 | +ENDIF | |
314 | + | |
315 | + | |
316 | +the_end: | |
317 | +message,'Finished dustem_fit_intensity_example',/info | |
318 | + | |
319 | +END | ... | ... |
... | ... | @@ -0,0 +1,177 @@ |
1 | +FUNCTION dustem_plugin_emiles_stellar_continuum,key=key $ | |
2 | + ,val=val $ | |
3 | + ,scope=scope $ | |
4 | + ,paramtag=paramtag $ | |
5 | + ,paramdefault=paramdefault $ | |
6 | + ,help=help | |
7 | + | |
8 | +;+ | |
9 | +; NAME: | |
10 | +; dustem_plugin_emiles_stellar_continuum | |
11 | +; PURPOSE: | |
12 | +; DustEMWrap plugin to add EMILES stellar template emission to Dustemwrap SEDs | |
13 | +; CATEGORY: | |
14 | +; DustEM, Distributed, Mid-Level, Plugin | |
15 | +; CALLING SEQUENCE: | |
16 | +; stellar_brightness=dustem_plugin_emiles_stellar_continuum([,key=][,val=][,scope=][,paramtag=][paramdefault=][,/help]) | |
17 | +; INPUTS: | |
18 | +; None | |
19 | +; OPTIONAL INPUT PARAMETERS: | |
20 | +; key = input parameter number | |
21 | +; First parameter: factor to apply to tau for redenning (1 means value derived from emission SED) | |
22 | +; Following 13*6 parameters are weights by which to multiply the MILES templates [Msun/pc^2] | |
23 | +; val = corresponding input parameter value | |
24 | +; OUTPUTS: | |
25 | +; stellar_brightness = stellar spectrum spectrum resampled on dustem wavelengths [MJy/sr] | |
26 | +; OPTIONAL OUTPUT PARAMETERS: | |
27 | +; scope = scope of the plugin | |
28 | +; paramdefault = default values of parameters | |
29 | +; paramtag = plugin parameter names as strings | |
30 | +; ACCEPTED KEY-WORDS: | |
31 | +; help = if set, print this help | |
32 | +; COMMON BLOCKS: | |
33 | +; None | |
34 | +; SIDE EFFECTS: | |
35 | +; None | |
36 | +; RESTRICTIONS: | |
37 | +; The DustEMWrap IDL code must be installed | |
38 | +; PROCEDURE: | |
39 | +; This is a DustEMWrap plugin | |
40 | +; EXAMPLES | |
41 | +; dustem_init | |
42 | +; vec=dustem_plugin_emiles_stellar_continuum(scope=scope) | |
43 | +; MODIFICATION HISTORY: | |
44 | +; Written by JPB June 2023 | |
45 | +; Evolution details on the DustEMWrap gitlab. | |
46 | +; See http://dustemwrap.irap.omp.eu/ for FAQ and help. | |
47 | +;- | |
48 | + | |
49 | +IF keyword_set(help) THEN BEGIN | |
50 | + doc_library,'dustem_plugin_emiles_stellar_continuum' | |
51 | + output=0. | |
52 | + goto,the_end | |
53 | +ENDIF | |
54 | + | |
55 | +;stop | |
56 | + | |
57 | +;default values of input parameters | |
58 | +scope='ADD_SED' | |
59 | + | |
60 | +age_values=[0.03, 0.05, 0.08, 0.15, 0.25, 0.40, 0.60, 1.0, 1.75, 3.0, 5.0, 8.5, 13.5] | |
61 | +metalicity_values=[-1.48630, -0.961400, -0.351200, +0.0600000, +0.255900, +0.397100] | |
62 | + | |
63 | +;read template info | |
64 | +info_st=dustem_read_emiles_stellar_templates(age_values,metalicity_values,/info_only) | |
65 | +age_values_emiles=info_st.age | |
66 | +order=sort(age_values_emiles) | |
67 | +age_values_emiles=age_values_emiles[order] | |
68 | +un=uniq(age_values_emiles) | |
69 | +age_values_emiles=age_values_emiles[un] | |
70 | +met_values_emiles=info_st.z | |
71 | +order=sort(met_values_emiles) | |
72 | +met_values_emiles=met_values_emiles[order] | |
73 | +un=uniq(met_values_emiles) | |
74 | +met_values_emiles=met_values_emiles[un] | |
75 | + | |
76 | +Nage=n_elements(age_values) | |
77 | +Nmetalicity=n_elements(metalicity_values) | |
78 | +Nparam=Nage*Nmetalicity+1 ;+1 is for opacity | |
79 | +paramtag=strarr(Nparam) | |
80 | +paramdefault=dblarr(Nparam) | |
81 | +paramdefault[*]=0.D0 | |
82 | +i=0L | |
83 | +paramtag[0]='tau_f' | |
84 | +ii=1L | |
85 | +FOR i=1L,Nparam-1 DO BEGIN | |
86 | + ij=index2ij([i-1],[Nage,Nmetalicity]) | |
87 | + paramtag[ii]='Age'+strtrim(ij[0,0],2)+'Met'+strtrim(ij[0,1],2) | |
88 | + ii=ii+1 | |
89 | +ENDFOR | |
90 | +paramvalues=paramdefault | |
91 | +IF keyword_set(key) THEN BEGIN | |
92 | + ind=where(key EQ 1,count) | |
93 | + IF count NE 0 THEN paramvalues[0]=val[ind[0]] | |
94 | + FOR i=1L,Nparam-1 DO BEGIN | |
95 | + ind=where(key EQ i+1,count) | |
96 | + IF count NE 0 THEN paramvalues[i]=val[ind[0]] | |
97 | + ENDFOR | |
98 | +ENDIF | |
99 | + | |
100 | +;==== initialize templates if not present | |
101 | +defsysv,'!dustem_plugin_emiles_stellar_continuum',exist=exist | |
102 | +IF exist EQ 0 THEN BEGIN | |
103 | + st={ssps:ptr_new(),wavs:ptr_new(),Mstars:ptr_new()} | |
104 | + defsysv,'!dustem_plugin_emiles_stellar_continuum',st | |
105 | +ENDIF | |
106 | +IF not ptr_valid(!dustem_plugin_emiles_stellar_continuum.ssps) THEN BEGIN | |
107 | + message,'Initializing SSP templates',/continue | |
108 | + template_flux=dustem_read_emiles_stellar_templates(age_values,metalicity_values,template_wav=template_wav,Mstars=Mstars) | |
109 | + !dustem_plugin_emiles_stellar_continuum.ssps=ptr_new(template_flux) | |
110 | + !dustem_plugin_emiles_stellar_continuum.wavs=ptr_new(template_wav) | |
111 | + !dustem_plugin_emiles_stellar_continuum.mstars=ptr_new(Mstars) | |
112 | +ENDIF | |
113 | + | |
114 | + | |
115 | +lambir=dustem_get_wavelengths() | |
116 | +Nwavs=n_elements(lambir) | |
117 | +output=fltarr(Nwavs,3) | |
118 | +wavs=*!dustem_plugin_emiles_stellar_continuum.wavs | |
119 | +Mstars=*!dustem_plugin_emiles_stellar_continuum.mstars | |
120 | +;==== sum up the stellar spectrum | |
121 | +;stop | |
122 | +FOR i=1L,Nparam-1 DO BEGIN | |
123 | + ;IF paramvalues[i] NE 0. AND ptr_valid((*!phangs_ssps)[i-1]) THEN BEGIN | |
124 | + IF paramvalues[i] NE 0. THEN BEGIN | |
125 | + ;stop | |
126 | + ;only interpolate within the template wavelengths | |
127 | + ;ind=where(lambir LE max(*!phangs_wavs) AND lambir GE min(*!phangs_wavs),count) | |
128 | + ind=where(lambir LE max(wavs) AND lambir GE min(wavs),count) | |
129 | + ;Mstar=(*!phangs_Mstars)[i] | |
130 | + Mstar=Mstars[i-1] | |
131 | + IF count NE 0 THEN BEGIN | |
132 | + ;output[ind,0]=output[ind,0]+paramvalues[i]*interpol(*(*!phangs_ssps)[i-1],*!phangs_wavs,lambir[ind]) | |
133 | + ;spectrum=*(*!phangs_ssps)[i-1] | |
134 | + ;ssp=*(*!phangs_ssps)[i-1] | |
135 | + ssp=*(*!dustem_plugin_emiles_stellar_continuum.ssps)[i-1] | |
136 | + ;stop | |
137 | + output[ind,0]=output[ind,0]+paramvalues[i]*Mstar*interpol(ssp,wavs,lambir[ind]) | |
138 | + ENDIF | |
139 | + ENDIF | |
140 | +ENDFOR | |
141 | +;==== Caution: at this point, output is in Lsun/pc^2/Angstroem | |
142 | +;Caution: I am not sure about the nomalisation of the extinction curve that is in | |
143 | +IF ptr_valid(!dustem_current) THEN BEGIN | |
144 | + ;stop | |
145 | + tau_fact=paramvalues[0] | |
146 | + extinction_curve=((*!dustem_current).ext).ext_tot*(*!dustem_HCD)/1.0e21 ;This is tau | |
147 | + ;*(*!dustem_HCD)/1.0e21 | |
148 | + ;wav_ref=551.e-9*1.e6 ;visible 551 nm in microns | |
149 | + ;tau_ref=interpol(extinction_curve,lambir,wav_ref) | |
150 | + ;normalize extinction curve by given tau fact | |
151 | + extinction_curve=extinction_curve*tau_fact | |
152 | + ;stop | |
153 | + output[*,0]=output[*,0]*exp(-1.*extinction_curve) | |
154 | +ENDIF | |
155 | + | |
156 | +;no polarization for now | |
157 | +output[*,1]=0. | |
158 | +output[*,2]=0. | |
159 | + | |
160 | +;at that stage, output is F_lambda in Lsun/A/pc^2 | |
161 | +;goint to MJy/sr (1e-20 W/m2/sr/hz) | |
162 | +pc=3.085677581e16 ;m | |
163 | +;kpc=3.085677581e19 ;m | |
164 | +Lsun=3.828e26 ;Watts | |
165 | +c=3.e5*1e3 ;m/s | |
166 | +;Fact=Lsun ;Watts/A | |
167 | +;fact=fact*c ;Watts/hz | |
168 | +;fact=fact/4./!pi ;Watts/Hz/sr | |
169 | +;fact=fact/pc^2 ;Watts/m2/Hz/sr | |
170 | + | |
171 | +fact=Lsun/pc*c/4./!pi/pc | |
172 | +output=output*fact | |
173 | + | |
174 | +the_end: | |
175 | +RETURN,output | |
176 | + | |
177 | +END | ... | ... |
... | ... | @@ -0,0 +1,165 @@ |
1 | +FUNCTION dustem_plugin_phangs_stellar_continuum,key=key $ | |
2 | + ,val=val $ | |
3 | + ,scope=scope $ | |
4 | + ,paramtag=paramtag $ | |
5 | + ,paramdefault=paramdefault $ | |
6 | + ,help=help | |
7 | + | |
8 | +;+ | |
9 | +; NAME: | |
10 | +; dustem_plugin_phangs_stellar_continuum | |
11 | +; PURPOSE: | |
12 | +; DustEMWrap plugin to add EMILES stellar template emission to Dustemwrap SEDs | |
13 | +; CATEGORY: | |
14 | +; DustEM, Distributed, Mid-Level, Plugin | |
15 | +; CALLING SEQUENCE: | |
16 | +; stellar_brightness=dustem_plugin_phangs_stellar_continuum([,key=][,val=][,scope=][,paramtag=][paramdefault=][,/help]) | |
17 | +; INPUTS: | |
18 | +; None | |
19 | +; OPTIONAL INPUT PARAMETERS: | |
20 | +; key = input parameter number | |
21 | +; First parameter: E(B-V) for extinction applied to the template, as used in Phangs | |
22 | +; Following 13*6 parameters are weights by which to multiply the MILES templates [Msun/pc^2] | |
23 | +; val = corresponding input parameter value | |
24 | +; OUTPUTS: | |
25 | +; stellar_brightness = stellar spectrum spectrum resampled on dustem wavelengths [MJy/sr] | |
26 | +; OPTIONAL OUTPUT PARAMETERS: | |
27 | +; scope = scope of the plugin | |
28 | +; paramdefault = default values of parameters | |
29 | +; paramtag = plugin parameter names as strings | |
30 | +; ACCEPTED KEY-WORDS: | |
31 | +; help = if set, print this help | |
32 | +; COMMON BLOCKS: | |
33 | +; None | |
34 | +; SIDE EFFECTS: | |
35 | +; None | |
36 | +; RESTRICTIONS: | |
37 | +; The DustEMWrap IDL code must be installed | |
38 | +; PROCEDURE: | |
39 | +; This is a DustEMWrap plugin for phangs | |
40 | +; It differs from dustem_plugin_emiles_stellar_continuum.pro only by the way the extinction is applied to the output spectrum | |
41 | +; EXAMPLES | |
42 | +; dustem_init | |
43 | +; vec=dustem_plugin_phangs_stellar_continuum(scope=scope) | |
44 | +; MODIFICATION HISTORY: | |
45 | +; Written by JPB June 2023 | |
46 | +; Evolution details on the DustEMWrap gitlab. | |
47 | +; See http://dustemwrap.irap.omp.eu/ for FAQ and help. | |
48 | +;- | |
49 | + | |
50 | +IF keyword_set(help) THEN BEGIN | |
51 | + doc_library,'dustem_plugin_phangs_stellar_continuum' | |
52 | + output=0. | |
53 | + goto,the_end | |
54 | +ENDIF | |
55 | + | |
56 | +;stop | |
57 | + | |
58 | +;default values of input parameters | |
59 | +scope='ADD_SED' | |
60 | + | |
61 | +age_values=[0.03, 0.05, 0.08, 0.15, 0.25, 0.40, 0.60, 1.0, 1.75, 3.0, 5.0, 8.5, 13.5] | |
62 | +metalicity_values=[-1.48630, -0.961400, -0.351200, +0.0600000, +0.255900, +0.397100] | |
63 | + | |
64 | +;read template info | |
65 | +info_st=dustem_read_emiles_stellar_templates(age_values,metalicity_values,/info_only) | |
66 | +age_values_emiles=info_st.age | |
67 | +order=sort(age_values_emiles) | |
68 | +age_values_emiles=age_values_emiles[order] | |
69 | +un=uniq(age_values_emiles) | |
70 | +age_values_emiles=age_values_emiles[un] | |
71 | +met_values_emiles=info_st.z | |
72 | +order=sort(met_values_emiles) | |
73 | +met_values_emiles=met_values_emiles[order] | |
74 | +un=uniq(met_values_emiles) | |
75 | +met_values_emiles=met_values_emiles[un] | |
76 | + | |
77 | +Nage=n_elements(age_values) | |
78 | +Nmetalicity=n_elements(metalicity_values) | |
79 | +Nparam=Nage*Nmetalicity+1 ;+1 is for opacity | |
80 | +paramtag=strarr(Nparam) | |
81 | +paramdefault=dblarr(Nparam) | |
82 | +paramdefault[*]=0.D0 | |
83 | +i=0L | |
84 | +paramtag[0]='E(B-V)' | |
85 | +ii=1L | |
86 | +FOR i=1L,Nparam-1 DO BEGIN | |
87 | + ij=index2ij([i-1],[Nage,Nmetalicity]) | |
88 | + paramtag[ii]='Age'+strtrim(ij[0,0],2)+'Met'+strtrim(ij[0,1],2) | |
89 | + ii=ii+1 | |
90 | +ENDFOR | |
91 | +paramvalues=paramdefault | |
92 | +IF keyword_set(key) THEN BEGIN | |
93 | + ind=where(key EQ 1,count) | |
94 | + IF count NE 0 THEN paramvalues[0]=val[ind[0]] | |
95 | + FOR i=1L,Nparam-1 DO BEGIN | |
96 | + ind=where(key EQ i+1,count) | |
97 | + IF count NE 0 THEN paramvalues[i]=val[ind[0]] | |
98 | + ENDFOR | |
99 | +ENDIF | |
100 | + | |
101 | +;==== initialize templates if not present | |
102 | +defsysv,'!dustem_plugin_phangs_stellar_continuum',exist=exist | |
103 | +IF exist EQ 0 THEN BEGIN | |
104 | + st={ssps:ptr_new(),wavs:ptr_new(),Mstars:ptr_new()} | |
105 | + defsysv,'!dustem_plugin_phangs_stellar_continuum',st | |
106 | +ENDIF | |
107 | +IF not ptr_valid(!dustem_plugin_phangs_stellar_continuum.ssps) THEN BEGIN | |
108 | + message,'Initializing SSP templates',/continue | |
109 | + template_flux=dustem_read_emiles_stellar_templates(age_values,metalicity_values,template_wav=template_wav,Mstars=Mstars) | |
110 | + !dustem_plugin_phangs_stellar_continuum.ssps=ptr_new(template_flux) | |
111 | + !dustem_plugin_phangs_stellar_continuum.wavs=ptr_new(template_wav) | |
112 | + !dustem_plugin_phangs_stellar_continuum.mstars=ptr_new(Mstars) | |
113 | +ENDIF | |
114 | + | |
115 | +;stop | |
116 | + | |
117 | +lambir=dustem_get_wavelengths() | |
118 | +Nwavs=n_elements(lambir) | |
119 | +output=fltarr(Nwavs,3) | |
120 | +wavs=*!dustem_plugin_phangs_stellar_continuum.wavs | |
121 | +Mstars=*!dustem_plugin_phangs_stellar_continuum.mstars | |
122 | +;==== sum up the stellar spectrum | |
123 | +;stop | |
124 | +FOR i=1L,Nparam-1 DO BEGIN | |
125 | + IF paramvalues[i] NE 0. THEN BEGIN | |
126 | + ;stop | |
127 | + ;only interpolate within the template wavelengths | |
128 | + ind=where(lambir LE max(wavs) AND lambir GE min(wavs),count) | |
129 | + Mstar=Mstars[i-1] | |
130 | + IF count NE 0 THEN BEGIN | |
131 | + ssp=*(*!dustem_plugin_phangs_stellar_continuum.ssps)[i-1] | |
132 | + output[ind,0]=output[ind,0]+paramvalues[i]*Mstar*interpol(ssp,wavs,lambir[ind]) | |
133 | + ENDIF | |
134 | + ENDIF | |
135 | +ENDFOR | |
136 | +;==== Caution: at this point, output is unredenned Flambda in Lsun/pc^2/Angstroem | |
137 | + | |
138 | +;==== reden spectrum using Calzetti's extinction law (which is what Phangs does) | |
139 | +flux=output[*,0] | |
140 | +;factor -1 is to reden, instead of unreden. factor 1e4 is to go from microns to Angstroem | |
141 | +calz_unred, lambir*1.e4, flux, -1.*paramvalues[0], flux_red, R_V = R_V | |
142 | +output[*,0]=flux_red | |
143 | + | |
144 | +;no polarization for now | |
145 | +output[*,1]=0. | |
146 | +output[*,2]=0. | |
147 | + | |
148 | +;at that stage, output is F_lambda in Lsun/A/pc^2 | |
149 | +;goint to MJy/sr (1e-20 W/m2/sr/hz) | |
150 | +pc=3.085677581e16 ;m | |
151 | +;kpc=3.085677581e19 ;m | |
152 | +Lsun=3.828e26 ;Watts | |
153 | +c=3.e5*1e3 ;m/s | |
154 | +;Fact=Lsun ;Watts/A | |
155 | +;fact=fact*c ;Watts/hz | |
156 | +;fact=fact/4./!pi ;Watts/Hz/sr | |
157 | +;fact=fact/pc^2 ;Watts/m2/Hz/sr | |
158 | + | |
159 | +fact=Lsun/pc*c/4./!pi/pc | |
160 | +output=output*fact | |
161 | + | |
162 | +the_end: | |
163 | +RETURN,output | |
164 | + | |
165 | +END | ... | ... |
... | ... | @@ -0,0 +1,156 @@ |
1 | +FUNCTION dustem_read_emiles_stellar_templates,age_values, $ | |
2 | + metalicity_values, $ | |
3 | + template_wav=template_wav, $ | |
4 | + Mstars=Mstars, $ | |
5 | + info_only=info_only, $ | |
6 | + info_st=info_st, $ | |
7 | + help=help | |
8 | + | |
9 | +;+ | |
10 | +; NAME: | |
11 | +; dustem_read_emiles_stellar_templates | |
12 | +; PURPOSE: | |
13 | +; reads EMILES stellar population templates | |
14 | +; CATEGORY: | |
15 | +; DustEMWrap, Distributed, High-Level, User Example | |
16 | +; CALLING SEQUENCE: | |
17 | +; templates=dustem_read_emiles_stellar_templates(age_values,metalicity_values[,template_waves=][,Mstars=][,/info_only][,info_st=][,/help]) | |
18 | +; INPUTS: | |
19 | +; age_values : array of age values | |
20 | +; metalicity_values : array of metalicity values | |
21 | +; OPTIONAL INPUT PARAMETERS: | |
22 | +; None | |
23 | +; OUTPUTS: | |
24 | +; templates : SSP templates (F_lambda) [Lsun Msun^-1 A^-1] | |
25 | +; OPTIONAL OUTPUT PARAMETERS: | |
26 | +; template_wav = common wavelength array for templates [Angstroem] | |
27 | +; Mstars = Mass of stars [Msun] | |
28 | +; info_st = info structure for the templates | |
29 | +; ACCEPTED KEY-WORDS: | |
30 | +; info_only : if set, read only the information structure | |
31 | +; help : if set, prints this help | |
32 | +; COMMON BLOCKS: | |
33 | +; None | |
34 | +; SIDE EFFECTS: | |
35 | +; None | |
36 | +; RESTRICTIONS: | |
37 | +; The DustEM fortran code must be installed | |
38 | +; The DustEMWrap IDL code must be installed | |
39 | +; PROCEDURES AND SUBROUTINES USED: | |
40 | +; | |
41 | +; EXAMPLES | |
42 | +; | |
43 | +; MODIFICATION HISTORY: | |
44 | +; Written by JPB June-2023 | |
45 | +; Evolution details on the DustEMWrap gitlab. | |
46 | +; See http://dustemwrap.irap.omp.eu/ for FAQ and help. | |
47 | +;- | |
48 | + | |
49 | +IF keyword_set(help) THEN BEGIN | |
50 | + doc_library,'dustem_read_emiles_stellar_templates' | |
51 | + templates=-1 | |
52 | + goto,the_end | |
53 | +END | |
54 | + | |
55 | +dir_templates='/Users/jpb/Soft_Libraries/dustem-wrapper_idl/Data/SSPs/ssp_emiles-ch/' | |
56 | + | |
57 | +;read templates info file | |
58 | +;IMF slope Z Age Mtotal M(*+remn) M* Mremn Mgas M(*+remn)/Lv M*/Lv Mv unknown | |
59 | +file=dir_templates+'templates_info.txt' | |
60 | +format='A,F,F,F,F,F,F,F,F,F,F,F,F' | |
61 | +readcol,file,imf,slope,z,age,Mtot,Mstar_rem,Mstar,Mremn,Mgas,Mstar_rem_o_Lv,Mstar_o_Lv,Mv,unknown,format=format | |
62 | +one_st={imf:'',slope:0.,z:0.,age:0.,Mtot:0.,Mstar_rem:0.,Mstar:0.,Mremn:0.,Mgas:0.,Mstar_rem_o_Lv:0.,Mstar_o_Lv:0.,Mv:0.,unknown:0.} | |
63 | +info_st=replicate(one_st,n_elements(imf)) | |
64 | +info_st.imf=imf | |
65 | +info_st.slope=slope | |
66 | +info_st.z=z | |
67 | +info_st.age=age | |
68 | +info_st.mtot=Mtot | |
69 | +info_st.Mstar_rem=Mstar_rem | |
70 | +info_st.Mstar=Mstar | |
71 | +info_st.Mremn=Mremn | |
72 | +info_st.Mgas=Mgas | |
73 | +info_st.Mstar_rem_o_Lv=Mstar_rem_o_Lv | |
74 | +info_st.Mstar_o_Lv=Mstar_o_Lv | |
75 | +info_st.Mv=Mv | |
76 | +info_st.unknown=unknown | |
77 | +IF keyword_set(info_only) THEN BEGIN | |
78 | + templates=info_st | |
79 | + goto,the_end | |
80 | +ENDIF | |
81 | + | |
82 | +;stop | |
83 | + | |
84 | +;file name format is ssp_emiles-ch/Ech1.30Zp0.40T13.5000_iTp0.00_baseFe_linear_FWHM_variable.fits | |
85 | +;=== producing age and metalicity strings for file names | |
86 | +age_values_4str=string(age_values,format='(F7.4)') | |
87 | +FOR i=0L,n_elements(age_values_4str)-1 DO age_values_4str[i]=textoidl_str_replace(age_values_4str[i],' ','0') | |
88 | +metalicity_values_4str=round(metalicity_values*100.)/100. ;This is the array for metalicity values in fits files names | |
89 | +metalicity_values_4str=string(metalicity_values_4str,format='(F5.2)') | |
90 | +FOR i=0L,n_elements(metalicity_values_4str)-1 DO metalicity_values_4str[i]=textoidl_str_replace(metalicity_values_4str[i],' ','p') | |
91 | +FOR i=0L,n_elements(metalicity_values_4str)-1 DO metalicity_values_4str[i]=textoidl_str_replace(metalicity_values_4str[i],'-','m') | |
92 | + | |
93 | +;Ntemplates=n_elements(paramvalues)-1 | |
94 | +Ntemplates=n_elements(age_values)*n_elements(metalicity_values) | |
95 | +Nage=n_elements(age_values) | |
96 | +Nmetalicity=n_elements(metalicity_values) | |
97 | + | |
98 | +templates=ptrarr(Ntemplates) | |
99 | + | |
100 | +;file names are like: Ech1.30Zm0.35T00.2500_iTp0.00_baseFe_linear_FWHM_variable.fits | |
101 | +file_start='Ech1.30' | |
102 | +file_end='_iTp0.00_baseFe_linear_FWHM_variable.fits' | |
103 | +ii=0L | |
104 | +Nage_str=6 | |
105 | +Nmet_str=4 | |
106 | +Mstars=fltarr(Ntemplates) | |
107 | +files_not_found=[''] | |
108 | +FOR i=1L,Ntemplates DO BEGIN | |
109 | + zsign_str='p' | |
110 | + ij=index2ij([i-1],[Nage,Nmetalicity]) | |
111 | + iage=ij[0,0] | |
112 | + imet=ij[0,1] | |
113 | + age=age_values[iage] | |
114 | + met=metalicity_values[imet] | |
115 | + met_str=metalicity_values_4str[imet] | |
116 | + age_str=age_values_4str[iage] | |
117 | + message,'reading template for Age '+age_str+' Met '+met_str,/continue | |
118 | + file=dir_templates+file_start+'Z'+met_str+'T'+age_str+file_end | |
119 | + fi=file_info(file) | |
120 | + IF fi.exists THEN BEGIN | |
121 | + message,'Reading SSP '+file,/continue | |
122 | + spec=readfits(file,h,2) | |
123 | + templates[ii]=ptr_new(spec) | |
124 | + make_axis,h,wavs | |
125 | + ind=where(info_st.z EQ met AND info_st.age EQ age,count) | |
126 | + IF count EQ 0 THEN BEGIN | |
127 | + message,'age,met not found in template info',/continue | |
128 | + stop | |
129 | + ENDIF ELSE BEGIN | |
130 | + Mstars[i-1]=info_st[ind[0]].Mstar | |
131 | + ENDELSE | |
132 | + ENDIF ELSE BEGIN | |
133 | + message,'file not found '+file,/continue | |
134 | + files_not_found=[files_not_found,file] | |
135 | + ENDELSE | |
136 | + ii=ii+1 | |
137 | +ENDFOR | |
138 | + | |
139 | +IF n_elements(files_not_found) NE 1 THEN BEGIN | |
140 | + files_not_found=files_not_found[1:*] | |
141 | + message,strmid(n_elements(files_not_found),2)+' SSP files were not found :',/continue | |
142 | + hprint,files_not_found | |
143 | + stop | |
144 | +ENDIF | |
145 | + | |
146 | +;Nspec=n_elements(spec) | |
147 | +;print,min(wavs),max(wavs) | |
148 | +; 3500.2000 12000.250 | |
149 | +angstroem2mic=1.e6/1.e10 | |
150 | +template_wav=wavs*angstroem2mic ;mic | |
151 | + | |
152 | +the_end: | |
153 | + | |
154 | +RETURN,templates | |
155 | + | |
156 | +END | |
0 | 157 | \ No newline at end of file | ... | ... |