Commit b58e95699323617a2f84fdcc25c92eb0b727591c

Authored by Jean-Philippe Bernard
1 parent ab47fb7c
Exists in master

First commit

src/idl/dustem_fit_intensity_emiles_example.pro 0 → 100644
@@ -0,0 +1,319 @@ @@ -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
src/idl/dustem_plugin_emiles_stellar_continuum.pro 0 → 100644
@@ -0,0 +1,177 @@ @@ -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
src/idl/dustem_plugin_phangs_stellar_continuum.pro 0 → 100644
@@ -0,0 +1,165 @@ @@ -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
src/idl/dustem_read_emiles_stellar_templates.pro 0 → 100644
@@ -0,0 +1,156 @@ @@ -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 \ No newline at end of file 157 \ No newline at end of file