Commit 36e8b8799e318bbbda46193285659ccf8b166d62

Authored by Jean-Michel Glorian
1 parent 427f1205
Exists in master

update from deborah

src/idl/dustem_cc.pro
... ... @@ -78,8 +78,8 @@ instrus=dustem_filter2instru(filter_names)
78 78 inst_tags=tag_names((*!dustem_filters))
79 79  
80 80 ;DEBUG VG
81   -j=where(instrus eq 'HFI',count)
82   -if count gt 0 then instrus(j) = 'HFI_V3P02'
  81 +;j=where(instrus eq 'HFI',count)
  82 +;if count gt 0 then instrus(j) = 'HFI_V3P02'
83 83  
84 84 Nbands=n_elements(filter_names)
85 85 sed=dblarr(Nbands)
... ...
src/idl/dustem_compute_polsed.pro
... ... @@ -53,6 +53,7 @@ spec = stp.em_tot * fact
53 53 if not isarray(spec) THEN stop
54 54 ;stop
55 55 ;COMPUTE THE MODEL SED
  56 +
56 57 dustem_polsed = (*!dustem_data.polsed).values * 0.
57 58  
58 59 ;stop
... ...
src/idl/dustem_data_tag.pro
... ... @@ -4,7 +4,8 @@ ntags=n_tags(!dustem_data)
4 4 mm=lonarr(ntags)
5 5  
6 6 FOR i=0L,ntags-1 DO BEGIN
7   - IF ptr_valid(!dustem_data.(i)) THEN mm(i)=1
  7 + IF ptr_valid(!dustem_data.(i)) THEN mm(i)=1
  8 +
8 9 ENDFOR
9 10 ind=where(mm EQ 1,count)
10 11  
... ...
src/idl/dustem_grains_colors.pro
1   -FUNCTION dustem_grains_colors,Ngrains
  1 +FUNCTION dustem_grains_colors,Ngrains,ls,ps=ps
2 2  
3   -colmax=210 & colmin=30
4   -colors=findgen(Ngrains)/(1.*Ngrains-1)*(colmax-colmin)+colmin
  3 +fixed_colors = [0,210,50,210,50,30,50,80,120,150,180,210,230,250]
  4 +;last_color = n_elements(fixed_colors)-1
  5 +;colors = [0,fixed_colors(last_color-Ngrains+1:last_color)]
  6 +colors = [0,fixed_colors(1:Ngrains)]
  7 +
  8 +ls = [ [ 0,4,3,5,1 ], [ 0,4,3,5,1 ],[ 0,4,3,5,1 ] ]
  9 +
  10 +if keyword_set(ps) then begin
  11 + ; Postscript
  12 + !y.thick = 5
  13 + !x.thick = 5
  14 + !p.thick = 7
  15 + !p.charsize = 1.3
  16 + !p.charthick = 5
  17 + !x.ticklen = 0.04
  18 +endif else begin
  19 + j=where(colors eq 0)
  20 + colors(j)=255
  21 +endelse
5 22  
6 23 RETURN,colors
7 24  
... ...
src/idl/dustem_init.pro
... ... @@ -81,7 +81,8 @@ if keyword_set(pol) then begin
81 81 polsed: ptr_new(), $
82 82 polfrac: ptr_new() $
83 83 }
84   - rchi2_weight = {sed: 0.,ext: 0.,polext: 0.,polsed: 0.,polfrac:0.}
  84 + rchi2_weight = {sed: 0.,ext: 0.,polext: 0.,polsed: 0.,polfrac:0.}
  85 +
85 86 endif else begin
86 87 defsysv, '!dustem_data', { $ ;Data to fit
87 88 sed: ptr_new(), $
... ... @@ -293,7 +294,7 @@ endif ; /noerase
293 294 IF keyword_set(wraptest) THEN BEGIN
294 295 dir_out=!dustem_dat
295 296 dustem_write_all,st_model,dir_out
296   - stop
  297 + ; stop
297 298 st=dustem_run()
298 299 IF keyword_set(plot_it) THEN BEGIN
299 300 loadct,13
... ...
src/idl/dustem_mpfit_data.pro
... ... @@ -88,13 +88,14 @@ for j=0,n_elements(fields)-1 do begin
88 88 endelse
89 89 ;print,"WEIGHT",i,j,weight,n_elements((*!dustem_data.(i)).sigma),"/",n_elements(wav)
90 90  
91   - instruc += ', (*!dustem_data.(' + strtrim(i,2) + ')).'+fields(j)+'*'+strtrim(weight,2)
  91 + instruc += ', (*!dustem_data.(' + strtrim(ind_data_tag(i),2) + ')).'+fields(j)+'*'+strtrim(weight,2)
92 92 ;print,"INSTRUC",instruc
93 93  
94 94 endfor
95 95 instruc += '])(1:*)' ; from 1 to exclude first 0
96 96 ;print,'-> INSTRUC: ',instruc
97   - toto=execute(instruc) ; Variables wav, values & sigma are created
  97 + toto=execute(instruc) ; Variables wav, values & sigma are created
  98 +
98 99 endfor
99 100  
100 101 p_min = dustem_mpfitfun(func_name,wav,values,sigma, $
... ...
src/idl/dustem_mpfit_run.pro
1   -;VG
2   -
3 1 FUNCTION dustem_mpfit_run,x,p_min,_EXTRA=extra
4 2  
5 3 ;+
6 4 ; NAME:
7   -; dustem_mpfit_run
  5 +; dustem_mpfit_run_vg
8 6 ; PURPOSE:
9 7 ; function used to fit dustem model with dustem_mpfit_sed
10 8 ; CATEGORY:
11 9 ; Dustem
12 10 ; CALLING SEQUENCE:
13   -; res=dustem_mpfit_run(x,params[,_EXTRA=extra][,cc_sed=cc_sed][,/help])
  11 +; res=dustem_mpfit_run_vg(x,params[,_EXTRA=extra][,cc_sed=cc_sed][,/help])
14 12 ; INPUTS:
15 13 ; x = necessary for interface but unused
16 14 ; params = Dustem Model parameters normalized to initial values
... ... @@ -32,7 +30,7 @@ FUNCTION dustem_mpfit_run,x,p_min,_EXTRA=extra
32 30 ; PROCEDURE:
33 31 ; None
34 32 ; EXAMPLES
35   -; res=dustem_mpfit_run(x,params[,_EXTRA=extra][,cc_sed=cc_sed][,/help])
  33 +; res=dustem_mpfit_run_vg(x,params[,_EXTRA=extra][,cc_sed=cc_sed][,/help])
36 34 ; MODIFICATION HISTORY:
37 35 ; Adapted to extinction and polarization by Vincent Guillet (IAS)
38 36 ; Written by J.-Ph. Bernard
... ... @@ -42,16 +40,17 @@ FUNCTION dustem_mpfit_run,x,p_min,_EXTRA=extra
42 40  
43 41 ;note that x is not used.
44 42  
  43 +;COMMON MPFIT_ERROR, ERROR_CODE
  44 +
45 45 IF keyword_set(help) THEN BEGIN
46   - doc_library,'dustem_mpfit_run'
  46 + doc_library,'dustem_mpfit_run_vg'
47 47 sed=0.
48 48 goto,the_end
49 49 ENDIF
50   -;stop
51 50  
52 51 p_dim=p_min*(*(*!dustem_fit).param_init_values)
  52 +;Run dustem with as an interface to mpfitfun
53 53  
54   -;CALCULATE THE CONTINUUM
55 54 IF !dustem_idl_continuum THEN cont=dustem_create_continuum()
56 55  
57 56 ;CALL THE DUSTEM_CREATE FUNCTIONS
... ... @@ -66,173 +65,361 @@ dustem_create_functions,p_dim/(*(*!dustem_fit).param_init_values),cont=cont,res=
66 65 ;this call only if IONFRACPAH master-keyword in GRAIN.DAT
67 66 ;Removed for now (JPB). Use of ionfrac should be fully revisited.
68 67 IF !run_ionfrac gt 0. THEN toto = dustem_create_ionfrac()
69   -
70 68 ;RUN THE MODEL AND GET THE SPECTRUM
71 69 st = dustem_run(p_dim)
72   -
73   -;st_model=dustem_read_all(!dustem_soft_dir)
  70 +st_model=dustem_read_all(!dustem_soft_dir)
74 71  
75 72 chi2_sed = 0
76 73 chi2_ext = 0
77 74 chi2_polext = 0
  75 +chi2_polsed = 0
  76 +chi2_polfrac = 0
78 77 rchi2_sed = 0
79 78 rchi2_ext = 0
80 79 rchi2_polext = 0
  80 +rchi2_polsed = 0
  81 +rchi2_polfrac = 0
81 82 wrchi2_sed = 0
82 83 wrchi2_ext = 0
83 84 wrchi2_polext = 0
  85 +wrchi2_polsed = 0
  86 +wrchi2_polfrac = 0
84 87 n_sed = 0
85 88 n_ext = 0
86 89 n_polext = 0
  90 +n_polsed = 0
  91 +n_polfrac = 0
  92 +
  93 +win = 0
87 94  
88 95 tagnames=tag_names(!dustem_data)
89 96 dustem_out = [0]
90   -for i=0,n_tags(!dustem_data)-1 do begin
  97 +ind_data_tag=dustem_data_tag(count=count_data_tag)
  98 +
  99 +;if exist('./noplot') then !dustem_show_plot = 0 else if !dustem_show_plot eq 0 then !dustem_show_plot = 1
91 100  
92   - if !dustem_data.(i) eq ptr_new() then continue
  101 +for i_tag=0,count_data_tag-1 do begin
93 102  
94   - CASE tagnames(i) OF
  103 +;print,i_tag,ind_data_tag(i_tag)
  104 +;print,tagnames(ind_data_tag(i_tag))
  105 + CASE tagnames(ind_data_tag(i_tag)) OF
95 106  
96 107 'SED' : BEGIN
97 108  
98   -
99 109 dustem_sed = dustem_compute_sed(p_dim,st,cont=cont)
100   - dustem_out = [ dustem_out, dustem_sed ]
101 110  
102   - ; Plot if needed
103   - IF !dustem_show_plot NE 0 THEN BEGIN
104   -
105   - window,1
106   - ;dustem_plot_fit_sed,st,dustem_sed,cont,_extra=extra,res=p_min*(*IDO),chi2=(*!dustem_fit).chi2,rchi2=(*!dustem_fit).rchi2
107   - dustem_plot_fit_sed,st,dustem_sed,cont,_extra=extra,res=p_min*(*(*!dustem_fit).param_init_values),chi2=(*!dustem_fit).chi2,rchi2=(*!dustem_fit).rchi2
108   - ; wait,0.5 ;Sorry for efficiency but needed to see the plot
109   -
110   - ENDIF
  111 + ; We normalize to 353
  112 + ;x=min(((*!dustem_data.sed).wav-850)^2,j353)
  113 + ;dustem_sed = dustem_sed/dustem_sed(j353)*(*!dustem_data.sed).values(j353)
111 114  
112 115 chi2_sed = total(((*!dustem_data.sed).values-dustem_sed)^2/(*!dustem_data.sed).sigma^2)
113 116 n_sed = n_elements((*!dustem_data.sed).values)
114 117 rchi2_sed = chi2_sed / n_sed
115 118 wrchi2_sed = rchi2_sed * !fit_rchi2_weight.sed
116   - print,"chi2 SED = ",chi2_sed," rchi2 SED = ",rchi2_sed
  119 + print,"chi2 SED = ",chi2_sed," rchi2 SED = ",rchi2_sed;," weighted rchi2 SED=",wrchi2_sed
  120 + ;print,'wl ',(*!dustem_data.sed).wav
  121 + ;print,"Delta SED per wl: ",(*!dustem_data.sed).values-dustem_sed
  122 + ;print,"error per wl: ",(*!dustem_data.sed).sigma
  123 + ;print,"chi2 per wl: ",((*!dustem_data.sed).values-dustem_sed)^2/(*!dustem_data.sed).sigma^2
  124 + alpha = total(((*!dustem_data.sed).values*dustem_sed)/(*!dustem_data.sed).sigma^2) $
  125 + / total(((*!dustem_data.sed).values)^2/(*!dustem_data.sed).sigma^2)
  126 + beta = total(((*!dustem_data.sed).values*dustem_sed)/(*!dustem_data.sed).sigma^2) $
  127 + / total(dustem_sed^2/(*!dustem_data.sed).sigma^2)
  128 +
  129 + print,"Best SED chi2 obtained if f_HI = ",alpha, " or if we multiply model by ",beta
  130 +
  131 + ;dustem_plot_nuinu_em,st,dustem_sed,cont,/print_radiance,p_dim=p_dim
  132 +
  133 + ; Plot if needed
  134 + IF !dustem_show_plot NE 0 THEN BEGIN
  135 + window,0
  136 + dustem_plot_fit_sed,st,dustem_sed,cont,_extra=extra,res=p_min*(*(*!dustem_fit).param_init_values),chi2=(*!dustem_fit).chi2,rchi2=(*!dustem_fit).rchi2
  137 + ;ytit='Total intensity'
  138 + ;xtit=textoidl('\lambda (\mum)')
  139 + ;win+=1
  140 + ;xr=[10,5e3]
  141 + ;yr=[5e-33,5.e-28]
  142 + ;nodiff = 0
  143 + ;dustem_plot_nuinu_em_vg,st,dustem_sed,cont,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,mergePAH=mergePAH,/donotclose,multi=1,nodiff=nodiff
  144 + ;dustem_plot_nuinu_em_vg,st,dustem_sed,cont,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,mergePAH=mergePAH,multi=2,nodiff=nodiff
  145 +
  146 + ENDIF
  147 +
  148 + dustem_out = [ dustem_out, dustem_sed ]
117 149  
118 150 END
119 151  
120 152 'EXT' : BEGIN
121 153  
122 154 dustem_ext = interpol(st.ext.ext_tot,st.ext.wav,(*!dustem_data.ext).wav)
123   - dustem_out = [ dustem_out, dustem_ext ]
124   -
125   - ; Plot if needed
126   - IF !dustem_show_plot NE 0 THEN BEGIN
127   - window,2
128   - dustem_plot_ext,st,(*!dustem_params),yr=[1.e-6,1.e0],/ysty,xr=[1,400],/xsty
129   - window,3
130   - dustem_plot_ext,st,(*!dustem_params),/UV,yr=[0,2.5],/ysty,xr=[0,10],/xsty
131   - ENDIF
132   -
133   - dustem_ext = interpol(st.ext.ext_tot,st.ext.wav,(*!dustem_data.ext).wav)
134 155 chi2_ext = total(((*!dustem_data.ext).values-dustem_ext)^2/(*!dustem_data.ext).sigma^2)
135 156 n_ext = n_elements((*!dustem_data.ext).values)
136 157 rchi2_ext = chi2_ext / n_ext
137 158 wrchi2_ext = rchi2_ext * !fit_rchi2_weight.ext
138   - print,"chi2 EXT = ",chi2_ext," rchi2 EXT = ",rchi2_ext
  159 + print,"chi2 EXT = ",chi2_ext," rchi2 EXT = ",rchi2_ext;," weighted rchi2 EXT=",wrchi2_ext
  160 + ;print,"chi2 per wl: ",((*!dustem_data.ext).values-dustem_ext)^2/(*!dustem_data.ext).sigma^2
  161 +
  162 + ; Plot if needed
  163 + IF !dustem_show_plot NE 0 THEN BEGIN
  164 +
  165 + win+=1
  166 + ;dustem_plot_ext,st,yr=[1.e-6,1.e0],/ysty,xr=[0.5,40],/xsty,win=win
  167 + xr=[0.3,40]
  168 + yr=[1.e-26,1.e-21]
  169 + dustem_plot_ext,st,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,mergePAH=mergePAH,/donotclose,multi=1
  170 + dustem_plot_ext,st,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,mergePAH=mergePAH,multi=2
  171 +
  172 + win+=1
  173 + ;dustem_plot_ext,st,/UV,yr=[0,2.5],/ysty,xr=[0,10],/xsty,win=win
  174 + xr=[0.2,10]
  175 + yr=[0,3e-21]
  176 + dustem_plot_ext,st,/UV,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,mergePAH=mergePAH,/donotclose,multi=1
  177 + dustem_plot_ext,st,/UV,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,mergePAH=mergePAH,multi=2
  178 +
  179 + ENDIF
139 180  
  181 + dustem_plot_ext,st,/print_Rv
  182 +
  183 + dustem_out = [ dustem_out, dustem_ext ]
  184 +
140 185 END
141 186  
142 187 'POLEXT': BEGIN
143 188  
144   - dustem_polext = interpol(st.polext.ext_tot,st.polext.wav,(*!dustem_data.polext).wav)
145   - dustem_out = [ dustem_out, dustem_polext ]
  189 + IF !dustem_show_plot NE 0 and !run_circ then begin
  190 + win+=1
  191 +
  192 + dustem_plot_circ,st,win=win,xr=[0.1,5],aligned=st_model.align.grains.aligned,yr=[-0.03,0.03]
  193 + endif
  194 +
  195 + IF !run_lin then begin
  196 +
  197 + dustem_polext = interpol(st.polext.ext_tot,st.polext.wav,(*!dustem_data.polext).wav)
  198 + chi2_polext = total(((*!dustem_data.polext).values-dustem_polext)^2/(*!dustem_data.polext).sigma^2)
  199 + n_polext = n_elements((*!dustem_data.polext).values)
  200 + rchi2_polext = chi2_polext / n_polext
  201 + wrchi2_polext = rchi2_polext * !fit_rchi2_weight.polext
  202 + print,"chi2 POLEXT = ",chi2_polext," rchi2 POLEXT = ",rchi2_polext;," weighted rchi2 POLEXT=",wrchi2_polext
  203 + ;print,"chi2 per wl: ",((*!dustem_data.polext).values-dustem_polext)^2/(*!dustem_data.polext).sigma^2
  204 +
  205 + ; Fit in (pmax,lmax,K)
  206 + x=st.polext.wav
  207 + logx=alog(x)
  208 + logy=alog(st.polext.ext_tot)
  209 + ;j=where(st.polext.ext_tot gt 0 and x gt 0.2 and x lt 1)
  210 +
  211 + ; Whittet+1992 (Table 1)
  212 + Uband = 0.36
  213 + Bband = 0.43
  214 + Vband = 0.55
  215 + Rband = 0.63
  216 + Iband = 0.78
  217 + Jband = 1.21
  218 + Hband = 1.64
  219 + Kband = 2.04
  220 + bands = [Uband,Bband,Vband,Rband,Iband,Jband,Hband]
  221 + nbands = n_elements(bands)
  222 + jband = indgen(nbands)*0
  223 + for k=0,nbands-1 do begin
  224 + xx=min(abs(st.polext.wav-bands(k)),j)
  225 + jband(k) = j
  226 + endfor
  227 + ;j=where(st.polext.ext_tot gt 0 and x gt 0.2 and x lt 1)
  228 + res = poly_fit(logx(jband),logy(jband),2)
  229 +
  230 + print
  231 + print,"Serkowski Fit with free K over ",string(st.polext(jband).wav,format='(100F5.2)')
  232 + print,"-------------------------"
  233 + K = -res(2)
  234 + lmax = exp(res(1)/(2*K))
  235 + pmax = exp(res(0)+K*alog(lmax)^2)
  236 + print,"* lmax = ",lmax," micron"
  237 + print,"* K = ",K
  238 + print,"* pmax = ",pmax," for NH=1e21"
  239 + print
  240 +
  241 + ; Plot if needed
  242 + IF !dustem_show_plot NE 0 THEN BEGIN
  243 +
  244 + ; Polarization fraction in the UV-IR
  245 + win+=1
  246 +
  247 + dustem_plot_polar,st,aligned=st_model.align.grains.aligned,yr=[0,0.15],/ysty,xr=[0.1,4],/xsty,win=win
  248 +
  249 + ; Polarisation curve (Serkowski)
  250 + win+=1
  251 + xr=[0.1,50]
  252 + yr=[5e-25,5e-23]
  253 + dustem_plot_polar,st,aligned=st_model.align.grains.aligned,/UV,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,cont=cont,/donotclose,multi=1
  254 + dustem_plot_polar,st,aligned=st_model.align.grains.aligned,/UV,yr=yr,/ysty,xr=xr,/xsty,ps=filename,win=win,cont=cont,multi=2
  255 +
  256 + win+=1
  257 + dustem_plot_fpol,win=win,xr=[10,1000],yr=[0,1.1]
  258 +
  259 +
  260 + ENDIF
  261 +
  262 + ;dustem_plot_polar,st,/print_ratio,cont=cont
  263 +
  264 + dustem_out = [ dustem_out, dustem_polext ]
  265 +
  266 + ENDIF
  267 +
  268 + END
  269 +
  270 + 'POLFRAC': BEGIN
  271 +
  272 + IF !run_lin then begin
  273 +
  274 + dustem_polsed = dustem_compute_polsed(p_dim,st.polsed,cont=cont)
  275 + dustem_sed_tmp = dustem_compute_sed(p_dim,st,cont=cont)
  276 + dustem_sed = dustem_polsed
  277 + ind_filt=where((*!dustem_data.polsed).filt_names NE 'SPECTRUM',count_filt)
  278 + for i = 0, count_filt-1 do begin
  279 + j=where((*!dustem_data.polsed).filt_names(ind_filt(i)) eq (*!dustem_data.sed).filt_names,count)
  280 + if count eq 1 then dustem_sed(i) = dustem_sed_tmp(j(0))
  281 + endfor
  282 + dustem_polfrac = dustem_polsed/dustem_sed
  283 +
  284 + ; We normalize at 353GHz
  285 + ;x=min(((*!dustem_data.polfrac).wav-850)^2,j353)
  286 + ;dustem_polfrac = dustem_polfrac/dustem_polfrac(j353)*(*!dustem_data.polfrac).values(j353)
  287 +
  288 + chi2_polfrac = total(((*!dustem_data.polfrac).values-dustem_polfrac)^2/(*!dustem_data.polfrac).sigma^2)
  289 + n_polfrac = n_elements((*!dustem_data.polfrac).values)
  290 + rchi2_polfrac = chi2_polfrac / n_polfrac
  291 + wrchi2_polfrac = rchi2_polfrac * !fit_rchi2_weight.polfrac
  292 + print,"chi2 POLFRAC = ",chi2_polfrac," rchi2 POLFRAC = ",rchi2_polfrac;," weighted rchi2 POLFRAC=",wrchi2_polfrac
  293 + ;print,"chi2 per wl: ",((*!dustem_data.polfrac).values-dustem_polfrac)^2/(*!dustem_data.polfrac).sigma^2
  294 +
  295 + dustem_out = [ dustem_out, dustem_polfrac ]
146 296  
147 297 ; Plot if needed
148 298 IF !dustem_show_plot NE 0 THEN BEGIN
149 299  
150   - ; Polarization fraction in the UV-IR
151   - window,4
152   - dustem_plot_polar,st,(*!dustem_params),yr=[0,0.08],/ysty,xr=[0.1,4],/xsty
153   -
154   - ; Polarisation curve (Serkowski)
155   - window,5
156   - dustem_plot_polar,st,(*!dustem_params),/UV,yr=[1e-3,3e-2],/ysty,xr=[0.1,10],/xsty
157   -
158   - ; Also show prediction for polarized SED
159   - window,6
160   - tit='Predicted polarization fraction in emission'
161   - ytit='Polarization fraction'
162   - xtit=textoidl('\lambda (\mum)')
163   - xrange = st.sed.wav
164   - Ngrains=n_tags(st.sed)-2
165   - colors=dustem_grains_colors(Ngrains)
166   -
167   - plot_oi,xrange,st.polsed.(Ngrains+1)/st.sed.(Ngrains+1),/nodata,xtit=xtit,ytit=ytit,tit=tit,yr=[0,0.3],/xlog
168   - for i = 0, Ngrains-1 do oplot,xrange,st.polsed.(i+1)/st.sed.(i+1),color=colors(i),psym=psym,linestyle=2
169   - oplot,xrange,st.polsed.(Ngrains+1)/st.sed.(Ngrains+1),psym=psym,linestyle=2
  300 + ; Also show prediction for polarized P/I
  301 + win+=1
  302 + dustem_plot_polar,st,aligned=st_model.align.grains.aligned,/Pfrac,win=win,cont=cont,yr=[0,0.25],/ysty,xr=[10,5d3]
170 303  
171 304 ENDIF
172 305  
173   - dustem_polext = interpol(st.polext.ext_tot,st.polext.wav,(*!dustem_data.polext).wav)
174   - chi2_polext = total(((*!dustem_data.polext).values-dustem_polext)^2/(*!dustem_data.polext).sigma^2)
175   - n_polext = n_elements((*!dustem_data.polext).values)
176   - rchi2_polext = chi2_polext / n_polext
177   - wrchi2_polext = rchi2_polext * !fit_rchi2_weight.polext
178   - print,"chi2 POLEXT = ",chi2_polext," rchi2 POLEXT = ",rchi2_polext
  306 + ENDIF
  307 +
  308 + END
  309 +
  310 + 'POLSED': BEGIN
  311 +
  312 + IF !run_lin then begin
  313 +
  314 + dustem_polsed = dustem_compute_polsed(p_dim,st.polsed,cont=cont)
  315 +
  316 + ; We normalize to 353
  317 + ;x=min(((*!dustem_data.polsed).wav-850)^2,j353)
  318 + ;dustem_polsed = dustem_polsed/dustem_polsed(j353)*(*!dustem_data.polsed).values(j353)
  319 +
  320 + chi2_polsed = total(((*!dustem_data.polsed).values-dustem_polsed)^2/(*!dustem_data.polsed).sigma^2)
  321 + n_polsed = n_elements((*!dustem_data.polsed).values)
  322 + rchi2_polsed = chi2_polsed / n_polsed
  323 + wrchi2_polsed = rchi2_polsed * !fit_rchi2_weight.polsed
  324 + print,"chi2 POLSED = ",chi2_polsed," rchi2 POLSED = ",rchi2_polsed;," weighted rchi2 POLSED=",wrchi2_polsed
  325 + print,"chi2 per wl: ",((*!dustem_data.polsed).values-dustem_polsed)^2/(*!dustem_data.polsed).sigma^2
  326 + ;print,"SNR per wl: ",(*!dustem_data.polsed).values/(*!dustem_data.polsed).sigma
  327 +
  328 + dustem_out = [ dustem_out, dustem_polsed ]
  329 +
  330 + ; Plot if needed
  331 + IF !dustem_show_plot NE 0 THEN BEGIN
  332 +
  333 + win+=1
  334 + xr=[10,5e3]
  335 + yr=[1e-34,1e-28]
  336 + dustem_plot_polar,st,aligned=st_model.align.grains.aligned,/SED,ps=filename,win=win,cont=cont,xr=xr,yr=yr,/xsty,/donotclose,multi=1
  337 + dustem_plot_polar,st,aligned=st_model.align.grains.aligned,/SED,ps=filename,win=win,cont=cont,xr=xr,yr=yr,/xsty,multi=2
  338 +
  339 + ENDIF
  340 +
  341 + ENDIF
179 342  
180 343 END
181 344  
182   -
183   - else : stop
  345 + ELSE : stop
184 346  
185 347 ENDCASE
186 348  
187 349 endfor
188 350  
189   -; Size distribution
190   -;window,7
191   -;fn = path+'out/SDIST.RES'
192   -;OPENR, uu, fn, /get_lun
193   -;tt = '#'
194   -;WHILE STRPOS(tt,'#') EQ 0 do begin
195   -;READF, uu, tt
196   -;ENDWHILE
197   -;ax = dblarr(ntype,nsz_max)
198   -;ava = dblarr(ntype,nsz_max)
199   -;FOR i=0,ntype-1 do begin
200   -;READF,uu,tt
201   -;for is=0,nsize(i)-1 do begin
202   -;READF, uu, tx, ty
203   -;ax(i,is) = tx
204   -;ava(i,is) = ty
205   -;endfor
206   -;ENDFOR
207   -;close,uu
208   -
209   -;tit='Dust size distributions'
210   -;yscl = 1.D29
211   -;xr=[0.1,1e3]
212   -;yr=[-2,3]
213   -;xtit='a (nm)'
214   -;ytit='Mass log( 10!u29!n n!dH!u-1!n a dm/da ) '
215   -;plot_oi, ax(0,0:nsize(0)-1)*1.e7, alog10(ava(0,0:nsize(0)-1)*yscl), line=ls(i+1),xr=xr,/xs,xtit=xtit,/ys,yr=yr,ytit=ytit,tit='DUSTEM'
216   -;FOR i=1,ntype-1 DO begin
217   -; oplot, ax(i,0:nsize(i)-1)*1.e7, alog10(ava(i,0:nsize(i)-1)*yscl), line=ls(i+1)
218   -;ENDFOR
219   -
220   -print,"Total chi2 = ",chi2_sed+chi2_ext+chi2_polext
221   -print,"Total weighted reduced chi2 driving mpfitfun = ", wrchi2_sed+wrchi2_ext+wrchi2_polext
222   -
  351 +; 4 bands fit : IRAS 100 and 857 down to 353 GHz
  352 +;fit_sed,"~/tmp/out/SED.RES",['IRAS','HFI'],iband=[0,0,0,1,1,1,1,1,1,0],beta=fixbeta,/noplot
  353 +DOF = n_elements(p_min)
  354 +total_chi2 = 0
  355 +total_rchi2 = 0
  356 +total_n = 0
  357 +if !fit_rchi2_weight.ext ne 0 then begin
  358 + total_n += n_ext
  359 + total_chi2 += chi2_ext
  360 + total_rchi2 += rchi2_ext
  361 +endif
  362 +if !fit_rchi2_weight.sed ne 0 then begin
  363 + total_n += n_sed
  364 + total_chi2 += chi2_sed
  365 + total_rchi2 += rchi2_sed
  366 +endif
  367 +if !run_pol then begin
  368 +if !fit_rchi2_weight.polext ne 0 then begin
  369 + total_n += n_polext
  370 + total_chi2 += chi2_polext
  371 + total_rchi2 += rchi2_polext
  372 +endif
  373 +if !fit_rchi2_weight.polsed ne 0 then begin
  374 + total_n += n_polsed
  375 + total_chi2 += chi2_polsed
  376 + total_rchi2 += rchi2_polsed
  377 +endif
  378 +if !fit_rchi2_weight.polfrac ne 0 then begin
  379 + total_n += n_polfrac
  380 + total_chi2 += chi2_polfrac
  381 + total_rchi2 += rchi2_polfrac
  382 +endif
  383 +endif
  384 +
  385 +total_wchi2 = chi2_ext * !fit_rchi2_weight.ext $
  386 + + chi2_sed * !fit_rchi2_weight.sed
  387 +if !run_pol then begin
  388 + total_wchi2 += chi2_polext * !fit_rchi2_weight.polext $
  389 + + chi2_polsed * !fit_rchi2_weight.polsed $
  390 + + chi2_polfrac * !fit_rchi2_weight.polfrac
  391 +endif
  392 +
  393 +print
  394 +print,"Total weighted chi2 driving mpfitfun = ", total_wchi2
  395 +print,"Nb of data points = ", total_n
  396 +print,"DOF = ", DOF
  397 +print,"Reduced chi2 EXT/SED/POLEXT/POLSED/POLFRAC",rchi2_ext,rchi2_sed,rchi2_polext,rchi2_polsed,rchi2_polfrac
  398 +print,"Weighted reduced chi2 EXT/SED/POLEXT/POLSED/POLFRAC",wrchi2_ext,wrchi2_sed,wrchi2_polext,wrchi2_polsed,wrchi2_polfrac
  399 +if !run_pol then print,"Weights",!fit_rchi2_weight.ext,!fit_rchi2_weight.sed,!fit_rchi2_weight.polext,!fit_rchi2_weight.polsed,!fit_rchi2_weight.polfrac $
  400 +else print,"Weights",!fit_rchi2_weight.ext,!fit_rchi2_weight.sed
  401 +print,"Mean weighted reduced chi2 = ", total_wchi2/(total_n-DOF)
  402 +print,"Unweighted reduced Total chi2 = ", total_chi2/(total_n-DOF)
  403 +print,"Unweighted mean reduced chi2 = ", total_rchi2/4*total_n/(total_n-DOF)
  404 +
  405 +;print,"Total reduced chi2 = ", (wrchi2_sed+wrchi2_ext+wrchi2_polext+wrchi2_polsed+wrchi2_polfrac)/(n_sed+n_ext+n_polext+n_polsed+n_polfrac-DOF)
  406 +; Reduced chi2 is like if there were the same nb of data points for each curve
  407 +;print,"Mean reduced chi2 = ", (wrchi2_sed+wrchi2_ext+wrchi2_polext+wrchi2_polsed+wrchi2_polfrac) * total_n/(total_n-DOF)
  408 +
  409 +; Plot size distribution
  410 +win+=1
  411 +xr=[0.3,5e3]
  412 +yr=[0.1,100]
  413 +IF !dustem_show_plot NE 0 THEN dustem_plot_sdist,xr=xr,yr=yr,ps=filename,win=win;,/donotclose
223 414  
224 415 ; Suppress the artificial [0] at the beginning
225 416 dustem_out = dustem_out[1:*]
226 417  
227   -;=== Caution, do not use message below here, even
228   -;=== with the /info and /contine options, or the
229   -;=== fit procedure will detect an error !
230   -;=== use print instead.
231 418 IF defined(extra) THEN BEGIN
232 419 IF keyword_set(extra.plot_it) THEN BEGIN
233 420 ; message,'params='+strtrim(p_min,2),/info,/continue
234 421 ; stop
235   - print,'dustem_mpfit_run: Current parameters values:',p_dim
  422 + print,'dustem_mpfit_run_vg: Current parameters values:',p_dim
236 423 ENDIF
237 424 ENDIF
238 425  
... ...
src/idl/dustem_plot_ext.pro
... ... @@ -100,7 +100,7 @@ endif else if keyword_set(albedo) then begin
100 100 ytit=textoidl('albedo')
101 101 plot,xrange,/nodata,xtit=xtit,ytit=ytit,tit=tit,xlog=xlog,ylog=ylog,yr=yr,ys=ys,xr=xr,xsty=xsty
102 102 oplot,xrange,sca_tot/(sca_tot+abs_tot)
103   - stop
  103 +
104 104  
105 105 endif else begin
106 106  
... ... @@ -116,7 +116,7 @@ endif else begin
116 116  
117 117 Ngrains=n_tags(st.sed)-2
118 118 colors=dustem_grains_colors(Ngrains,ls,ps=ps)
119   -
  119 +; stop
120 120 ytit=textoidl('\sigma_{ext}/N_H (cm^2/H)')
121 121 if not keyword_set(ps) then tit='Dustem extinction'
122 122  
... ...
src/idl/dustem_plot_fpol.pro
... ... @@ -18,7 +18,8 @@ endif else begin
18 18 endelse
19 19 endif
20 20  
21   -st_grains=dustem_read_grain(dir_in+'data/'+(*!dustem_inputs).grain,/silent)
  21 +;st_grains=dustem_read_grain(dir_in+'data/'+(*!dustem_inputs).grain,/silent)
  22 +st_grains=dustem_read_grain(dir_in+'data/'+'GRAIN.DAT',/silent)
22 23  
23 24 ngrains = st_grains.ngrains
24 25 colors=dustem_grains_colors(Ngrains,ls,ps=ps)
... ...
src/idl/dustem_plot_nuinu_em.pro
... ... @@ -57,7 +57,7 @@ FOR i=1L,Ngrains DO BEGIN
57 57 oplot,st.sed.wav,st.sed.(i)*fact,color=colors(i-1),psym=psym
58 58 ENDFOR
59 59 oplot,st.sed.wav,st.sed.(i)*fact,color=255,psym=psym
60   -stop
  60 +
61 61 defsysv,'!dustem_data',exists=exists
62 62 if exists then begin
63 63  
... ...
src/idl/dustem_plot_polar.pro
... ... @@ -82,7 +82,8 @@ xtit=textoidl('\lambda (\mum)')
82 82 ; Are observational data defined ?
83 83 defsysv,'!dustem_data',exists=data_exists
84 84  
85   -if keyword_set(print_ratio) then begin
  85 +if ptr_valid(!dustem_data.polext) then begin
  86 + if keyword_set(print_ratio) then begin
86 87  
87 88 ; Correction de couleur
88 89 cc = 1.11
... ... @@ -112,9 +113,14 @@ if keyword_set(print_ratio) then begin
112 113 tauV_data = interpol((*!dustem_data.ext).values,(*!dustem_data.ext).wav,Vband)
113 114 tauB = interpol(st.ext.ext_tot,st.ext.wav,Bband)
114 115 tauB_data = interpol((*!dustem_data.ext).values,(*!dustem_data.ext).wav,Bband)
  116 + print
  117 +
115 118  
116 119 ; I353 and P353 are in fact nu_Pnu, in unit of erg/s/H, not erg/s/sr/H
117   - ; 1 W/m2/sr/1d20H = 1e-17 erg/s/sr/H
  120 + ; 1 W/m2/sr/1d20H = 1e-17 erg/s/sr/H
  121 +endif
  122 +if ptr_valid(!dustem_data.polsed) then begin
  123 +
118 124 dustem_polsed = dustem_compute_polsed(p_dim,st.polsed,cont=cont)
119 125 x=min(((*!dustem_data.polsed).wav-850)^2,jmin)
120 126 P353 = dustem_polsed(jmin)
... ... @@ -132,26 +138,33 @@ if keyword_set(print_ratio) then begin
132 138 print
133 139 print,"Observational constraint"
134 140 print,"-------------------------"
  141 + print,"I353/NH data ",I353_data," MJy/sr for NH=1e20"
  142 + print,"P353/NH data ",P353_data," MJy/sr for NH=1e20"
  143 + print,"P353/I353 data ",P353_data/I353_data*100," %"
  144 + print
  145 + print,"Model results"
  146 + print,"-------------"
  147 + print,"I353/NH model ",I353," MJy/sr for NH=1e20"
  148 + print,"P353/NH model ",P353," MJy/sr for NH=1e20"
  149 + print,"P353/I353 model ",P353/I353*100," %"
  150 +
  151 + if keyword_set(print_ratio) then begin
  152 + print
  153 + print,"Observational constraint"
  154 + print,"-------------------------"
  155 +
135 156 print,"tau_V data ",tauV_data
136 157 print,"(p/tau)_V data ",pV_data/tauV_data*100," %"
137 158 print,"p_V/A_V data ",pV_data/(tauV_data*1.086)*100," %"
138 159 print,"with p_V data ",pV_data," %"
139   - print,"I353/NH data ",I353_data," MJy/sr for NH=1e20"
140   - print,"P353/NH data ",P353_data," MJy/sr for NH=1e20"
141   - print,"P353/I353 data ",P353_data/I353_data*100," %"
142 160 print,"Rs/v data ",(P353_data/I353_data)/(pv_data/tauv_data)
143 161 print,"RP/p data ",(P353_data/1e20) / (pv_data*1e-21)," MJy/sr"
144 162 print,"I353/Av data ",(I353_data/1e20) / (1.086*tauv_data*1e-21)," MJy/sr"
145 163 print
146   - print,"Model results"
147   - print,"-------------"
148 164 print,"(p/tau)_V model ",pV/tauV*100," %"
149 165 print,"p_V/A_V model ",pV/(tauV*1.086)*100," %"
150 166 print,"p_V/E(B-V) model ",pV/((tauB-tauV)*1.086)*100," %"
151 167 print,"with p_V model ",pV," %"
152   - print,"I353/NH model ",I353," MJy/sr for NH=1e20"
153   - print,"P353/NH model ",P353," MJy/sr for NH=1e20"
154   - print,"P353/I353 model ",P353/I353*100," %"
155 168 print,"Rs/v model ",P353/I353/(pV/tauV)
156 169 print,"Rs/EBV model ",P353/I353/(pV/(tauB-tauV))
157 170 print,"RP/p model ",(P353/1e20) / (pv*1e-21)," MJy/sr"
... ... @@ -172,13 +185,14 @@ if keyword_set(print_ratio) then begin
172 185 ;print,"Rs/v P353model/I353data/(pVmodel/tauVdata) ",P353/I353_data/(pV/tauV_data)
173 186 ;print,"RP/p P353model/pVdata ",(P353/1e20)/(pV_data*1e-21)," MJy/sr"
174 187 ;print
175   -
  188 + endif
  189 + endif
176 190  
177 191 endif else if keyword_set(UV) then begin
178 192  
179 193 if not keyword_set(ps) then tit='Dustem polarization cross-section'
180 194 ytit=textoidl('\sigma_{pol}/N_H (cm^2/H)')
181   -
  195 +if ptr_valid(!dustem_data.polext) then begin
182 196 if !dustem_show_plot EQ 2 or multi eq 2 then begin
183 197 ;normpol = polext_tot
184 198 normpol = st.polext.ext_tot
... ... @@ -193,7 +207,9 @@ endif else if keyword_set(UV) then begin
193 207  
194 208 if multi eq 0 then plot_oo,st.polext.wav,st.polext.ext_tot/normpol,/nodata,_Extra=extra,xtit=xtit,ytit=ytit,tit=tit,xr=xr,yr=yr,ylog=ylog
195 209 if multi eq 1 then plot_oo,st.polext.wav,st.polext.ext_tot/normpol,/nodata,_Extra=extra,xtit='',ytit=ytit,tit=tit,xr=xr,yr=yr,ylog=ylog,position=[0.17,0.35,0.95,0.95],xtickformat='(A1)'
196   - if multi eq 2 then plot_oo,st.polext.wav,st.polext.ext_tot/normpol,/nodata,_Extra=extra,xtit=xtit,ytit='Normalized',tit='',xr=xr,yr=[-1,2],ylog=ylog,position=[0.17,0.14,0.95,0.35],/noerase,yticks=3,ymino=5,xticklen=0.1
  210 + if multi eq 2 then plot_oo,st.polext.wav,st.polext.ext_tot/normpol,/nodata,_Extra=extra,xtit=xtit,ytit='Normalized',tit='',xr=xr,yr=[-1,2],ylog=ylog,position=[0.17,0.14,0.95,0.35],/noerase,yticks=3,ymino=5,xticklen=0.1
  211 +
  212 +
197 213 FOR i=0L,Ngrains-1 DO if aligned(i) then oplot,st.polext.wav,(st.polext.abs_grain(i)+st.polext.sca_grain(i))/normpol,color=colors(i+1),psym=psym,line=ls(i+1)
198 214  
199 215 if total(aligned gt 0) then oplot,st.polext.wav,st.polext.ext_tot/normpol,psym=psym
... ... @@ -203,8 +219,8 @@ endif else if keyword_set(UV) then begin
203 219 oplot, (*!dustem_data.polext).wav,(*!dustem_data.polext).values/dustem_polext,ps=4
204 220 if not keyword_set(noerrbars) then err_bar,(*!dustem_data.polext).wav,(*!dustem_data.polext).values/dustem_polext,yrms=(*!dustem_data.polext).sigma/dustem_polext
205 221 endif
206   -
207   -; ; Fit in (pmax,lmax,K)
  222 + endif
  223 + ; ; Fit in (pmax,lmax,K)
208 224 ; x=st.polext.wav
209 225 ; logx=alog(x)
210 226 ;
... ... @@ -238,7 +254,7 @@ endif else if keyword_set(UV) then begin
238 254 ; ; overplot the fit
239 255 ; ;oplot,x(j),exp(res(0)+logx(j)*res(1)-K*logx(j)^2),col=150
240 256  
241   -endif else if keyword_set(SED) then begin
  257 +endif else if ptr_valid(!dustem_data.polsed) then begin
242 258  
243 259 ;device, filename = 'plot008.eps', /color, /encapsulated
244 260 if not keyword_set(ps) then tit='Polarization intensity in emission'
... ...
src/idl/dustem_plot_sdist.pro
... ... @@ -52,12 +52,13 @@ xtit=textoidl('a (\mu m)')
52 52 norm_size = 1.d7
53 53 norm_size = 1.d4
54 54 xr /=1d3
  55 +
55 56 ;ytit='Mass log( 10!u29!n n!dH!u-1!n a dm/da ) '
56 57 ytit=textoidl('4\pi/3 a^3dn/d ln a (cm^3/H)')
57 58 if multi eq 0 then plot_oo, xr, /nodata,xr=xr,/xs,xtit=xtit,/ys,yr=yr,ytit=ytit,tit=''
58 59 if multi eq 1 then plot_oo, xr, /nodata,xr=xr,/xs,xtit='',/ys,yr=yr,ytit=ytit,tit='',position=[0.17,0.45,0.95,0.95],xtickformat='(A1)'
59 60 colors=dustem_grains_colors(ntype,ls,ps=ps)
60   -
  61 +;stop
61 62 FOR i=0,ntype-1 DO begin
62 63 ;if i le 1 and keyword_set(mergePAH) then begin
63 64 ; if i eq 0 then oplot, ax(0,0:nsize(0)-1)*1.e7, alog10(ava(0,0:nsize(0)-1)*yscl)+alog10(ava(1,0:nsize(1)-1)*yscl), line=ls(1),color = colors(1)
... ...
src/idl/dustem_read_align.pro
... ... @@ -42,20 +42,22 @@ one_st={aligned:0.,law:'',athresh:0.,plev:0.,pstiff:0.,TdsTg:0.,a0:0.,rvcut:0.}
42 42 st=replicate(one_st,st_grains.Ngrains)
43 43  
44 44 st.aligned = stregex(st_grains.grains.type_keywords, 'pol', /bool)
45   -
  45 +;count=0
46 46 FOR i=0L,st_grains.Ngrains-1 DO BEGIN
47   -
48   - IF st(i).aligned then begin
49   -
50   - readf,unit,str,format='(A100)'
  47 + IF st(i).aligned then begin
  48 + ; if count EQ 0. then begin
  49 + readf,unit,str,format='(A100)'
  50 + ;endif
  51 +
51 52 strv=str_sep(strcompress(strtrim(str,2)),' ')
52 53 Nstrv=n_elements(strv)
53   -
  54 +
54 55 ii=0L
55   - st(i).law=strv(ii) & ii=ii+1
  56 + st(i).law=strv(ii) & ii=ii+1
56 57  
57 58 ; IDG
58   - IF stregex(st(i).law, 'idg', /bool) THEN begin
  59 + IF stregex(st(i).law, 'idg', /bool) THEN begin
  60 + ii=ii+1
59 61 st(i).TdsTg = strv(ii) & ii=ii+1
60 62 st(i).a0 = strv(ii) & ii=ii+1
61 63 st(i).rvcut = strv(ii) & ii=ii+1
... ... @@ -66,19 +68,25 @@ FOR i=0L,st_grains.Ngrains-1 DO BEGIN
66 68 endif
67 69  
68 70 ; PARAMETRIC
69   - IF stregex(st(i).law, 'par', /bool) THEN begin
70   - ; Grain radius Threshold for alignment, given in microns and converted in cm
  71 + IF stregex(st(i).law, 'par', /bool) THEN begin
  72 + ; Grain radius Threshold for
  73 + ; alignment, given in microns and
  74 + ; converted in cm
71 75 st(i).athresh = strv(ii) & ii=ii+1
72 76 st(i).pstiff = strv(ii) & ii=ii+1
73   - st(i).plev = strv(ii) & ii=ii+1
  77 + st(i).plev = strv(ii) & ii=ii+1
  78 + ; count=1
74 79 endif
75 80  
76 81 IF !run_univ eq 1 then begin
77 82 st = replicate(st(i),st_grains.Ngrains)
78   - st.aligned = stregex(st_grains.grains.type_keywords, 'pol', /bool)
  83 + st.aligned = stregex(st_grains.grains.type_keywords, 'pol', /bool)
  84 + ;stop
79 85 break
80 86 endif
81   -
  87 +
  88 +
  89 +
82 90 ENDIF
83 91  
84 92 ENDFOR
... ... @@ -87,6 +95,7 @@ close,unit
87 95 free_lun,unit
88 96  
89 97 full_st={keywords:key_str,anisG0:anisG0,gamma:0,grains:st}
  98 +
90 99 RETURN,full_st
91 100  
92 101 END
... ...
src/idl/dustem_read_all_res.pro
... ... @@ -73,6 +73,7 @@ CASE !dustem_which OF
73 73 file=dir_out+'out/'+'EXT.RES'
74 74 st_ext=dustem_read_ext_lv(file,silent=silent)
75 75 ;VGb : add polarization
  76 +
76 77 if !run_pol then begin
77 78 file=dir_out+'out/'+'SED_POL.RES'
78 79 st_polsed=dustem_read_dustem_lv(file,silent=silent)
... ...
src/idl/dustem_set_data.pro
... ... @@ -52,6 +52,7 @@ ENDIF
52 52 ;=== clean the data structure
53 53 !dustem_data.sed = ptr_new()
54 54 !dustem_data.ext = ptr_new()
  55 +
55 56 if keyword_set(polext) then !dustem_data.polext = ptr_new()
56 57 if keyword_set(polsed) then !dustem_data.polsed = ptr_new()
57 58 if keyword_set(polfrac) then !dustem_data.polfrac = ptr_new()
... ... @@ -108,7 +109,8 @@ IF keyword_set(polfrac) THEN BEGIN
108 109 ENDIF
109 110  
110 111 IF keyword_set(polext) THEN BEGIN
111   - wavs=polext.wave
  112 + wavs=polext.wave
  113 +
112 114 ;=== Impose central wavelengths for photometric channels
113 115 ind=where(polext.filter NE 'SPECTRUM',count)
114 116 IF count NE 0 THEN BEGIN
... ... @@ -116,7 +118,7 @@ IF keyword_set(polext) THEN BEGIN
116 118 ENDIF
117 119 ;=== define observations structure
118 120 obs_st={instru_names:polext.instru,filt_names:polext.filter,wav:wavs, values:polext.spec,sigma:polext.error}
119   - ;=== fill !dustem_data
  121 + ;=== fill !dustem_data
120 122 !dustem_data.polext = ptr_new(obs_st)
121 123 ENDIF
122 124  
... ...
src/idl/mpfit.pro
... ... @@ -118,7 +118,7 @@
118 118 ; caller gracefully. However, during the debugging process, it is
119 119 ; often useful to halt execution where the error occurred. When you
120 120 ; set the NOCATCH keyword, MPFIT will not do any special error
121   -; trapping, and execution will stop where ever the error occurred.
  121 +; trapping, and execution will stop whereever the error occurred.
122 122 ;
123 123 ; MPFIT does not explicitly change the !ERROR_STATE variable
124 124 ; (although it may be changed implicitly if MPFIT calls MESSAGE). It
... ... @@ -164,9 +164,9 @@
164 164 ; individual values of PARINFO.MPSIDE. Setting AUTODERIVATIVE=0 is
165 165 ; equivalent to resetting PARINFO.MPSIDE=3 for all parameters.
166 166 ;
167   -; However, be aware that even if the user requests explicit
168   -; derivatives for some or all parameters, MPFIT will not always
169   -; request explicit derivatives on ever user function call.
  167 +; Even if the user requests explicit derivatives for some or all
  168 +; parameters, MPFIT will not always request explicit derivatives on
  169 +; every user function call.
170 170 ;
171 171 ; EXPLICIT DERIVATIVES - CALLING INTERFACE
172 172 ;
... ... @@ -303,6 +303,14 @@
303 303 ; that the derivatives computed in two different ways have the same
304 304 ; numerical sign and the same order of magnitude, since these are the
305 305 ; most common programming mistakes.
  306 +;
  307 +; A line of this form may also appear
  308 +;
  309 +; # FJAC_MASK = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  310 +;
  311 +; This line indicates for which parameters explicit derivatives are
  312 +; expected. A list of all-1s indicates all explicit derivatives for
  313 +; all parameters are requested from the user function.
306 314 ;
307 315 ;
308 316 ; CONSTRAINING PARAMETER VALUES WITH THE PARINFO KEYWORD
... ... @@ -448,6 +456,25 @@
448 456 ; constrained to be above 50.
449 457 ;
450 458 ;
  459 +; RECURSION
  460 +;
  461 +; Generally, recursion is not allowed. As of version 1.77, MPFIT has
  462 +; recursion protection which does not allow a model function to
  463 +; itself call MPFIT. Users who wish to perform multi-level
  464 +; optimization should investigate the 'EXTERNAL' function evaluation
  465 +; methods described below for hard-to-evaluate functions. That
  466 +; method places more control in the user's hands. The user can
  467 +; design a "recursive" application by taking care.
  468 +;
  469 +; In most cases the recursion protection should be well-behaved.
  470 +; However, if the user is doing debugging, it is possible for the
  471 +; protection system to get "stuck." In order to reset it, run the
  472 +; procedure:
  473 +; MPFIT_RESET_RECURSION
  474 +; and the protection system should get "unstuck." It is save to call
  475 +; this procedure at any time.
  476 +;
  477 +;
451 478 ; COMPATIBILITY
452 479 ;
453 480 ; This function is designed to work with IDL 5.0 or greater.
... ... @@ -457,6 +484,53 @@
457 484 ; of the IDL Virtual Machine.
458 485 ;
459 486 ;
  487 +; DETERMINING THE VERSION OF MPFIT
  488 +;
  489 +; MPFIT is a changing library. Users of MPFIT may also depend on a
  490 +; specific version of the library being present. As of version 1.70
  491 +; of MPFIT, a VERSION keyword has been added which allows the user to
  492 +; query which version is present. The keyword works like this:
  493 +;
  494 +; RESULT = MPFIT(/query, VERSION=version)
  495 +;
  496 +; This call uses the /QUERY keyword to query the version number
  497 +; without performing any computations. Users of MPFIT can call this
  498 +; method to determine which version is in the IDL path before
  499 +; actually using MPFIT to do any numerical work. Upon return, the
  500 +; VERSION keyword contains the version number of MPFIT, expressed as
  501 +; a string of the form 'X.Y' where X and Y are integers.
  502 +;
  503 +; Users can perform their own version checking, or use the built-in
  504 +; error checking of MPFIT. The MIN_VERSION keyword enforces the
  505 +; requested minimum version number. For example,
  506 +;
  507 +; RESULT = MPFIT(/query, VERSION=version, MIN_VERSION='1.70')
  508 +;
  509 +; will check whether the accessed version is 1.70 or greater, without
  510 +; performing any numerical processing.
  511 +;
  512 +; The VERSION and MIN_VERSION keywords were added in MPFIT
  513 +; version 1.70 and later. If the caller attempts to use the VERSION
  514 +; or MIN_VERSION keywords, and an *older* version of the code is
  515 +; present in the caller's path, then IDL will throw an 'unknown
  516 +; keyword' error. Therefore, in order to be robust, the caller, must
  517 +; use exception handling. Here is an example demanding at least
  518 +; version 1.70.
  519 +;
  520 +; MPFIT_OK = 0 & VERSION = '<unknown>'
  521 +; CATCH, CATCHERR
  522 +; IF CATCHERR EQ 0 THEN MPFIT_OK = MPFIT(/query, VERSION=version, $
  523 +; MIN_VERSION='1.70')
  524 +; CATCH, /CANCEL
  525 +;
  526 +; IF NOT MPFIT_OK THEN $
  527 +; MESSAGE, 'ERROR: you must have MPFIT version 1.70 or higher in '+$
  528 +; 'your path (found version '+version+')'
  529 +;
  530 +; Of course, the caller can also do its own version number
  531 +; requirements checking.
  532 +;
  533 +;
460 534 ; HARD-TO-COMPUTE FUNCTIONS: "EXTERNAL" EVALUATION
461 535 ;
462 536 ; The normal mode of operation for MPFIT is for the user to pass a
... ... @@ -525,6 +599,8 @@
525 599 ; RETURNS:
526 600 ;
527 601 ; Returns the array of best-fit parameters.
  602 +; Exceptions:
  603 +; * if /QUERY is set (see QUERY).
528 604 ;
529 605 ;
530 606 ; KEYWORD PARAMETERS:
... ... @@ -537,8 +613,31 @@
537 613 ; NOTE: to supply your own explicit derivatives,
538 614 ; explicitly pass AUTODERIVATIVE=0
539 615 ;
540   -; BESTNORM - the value of the summed squared weighted residuals for
541   -; the returned parameter values, i.e. TOTAL(DEVIATES^2).
  616 +; BESTNORM - upon return, the value of the summed squared weighted
  617 +; residuals for the returned parameter values,
  618 +; i.e. TOTAL(DEVIATES^2).
  619 +;
  620 +; BEST_FJAC - upon return, BEST_FJAC contains the Jacobian, or
  621 +; partial derivative, matrix for the best-fit model.
  622 +; The values are an array,
  623 +; ARRAY(N_ELEMENTS(DEVIATES),NFREE) where NFREE is the
  624 +; number of free parameters. This array is only
  625 +; computed if /CALC_FJAC is set, otherwise BEST_FJAC is
  626 +; undefined.
  627 +;
  628 +; The returned array is such that BEST_FJAC[I,J] is the
  629 +; partial derivative of DEVIATES[I] with respect to
  630 +; parameter PARMS[PFREE_INDEX[J]]. Note that since
  631 +; deviates are (data-model)*weight, the Jacobian of the
  632 +; *deviates* will have the opposite sign from the
  633 +; Jacobian of the *model*, and may be scaled by a
  634 +; factor.
  635 +;
  636 +; BEST_RESID - upon return, an array of best-fit deviates.
  637 +;
  638 +; CALC_FJAC - if set, then calculate the Jacobian and return it in
  639 +; BEST_FJAC. If not set, then the return value of
  640 +; BEST_FJAC is undefined.
542 641 ;
543 642 ; COVAR - the covariance matrix for the set of parameters returned
544 643 ; by MPFIT. The matrix is NxN where N is the number of
... ... @@ -548,9 +647,11 @@
548 647 ; Parameter errors are also returned in PERROR.
549 648 ;
550 649 ; To compute the correlation matrix, PCOR, use this example:
551   -; IDL> PCOR = COV * 0
552   -; IDL> FOR i = 0, n-1 DO FOR j = 0, n-1 DO $
553   -; PCOR[i,j] = COV[i,j]/sqrt(COV[i,i]*COV[j,j])
  650 +; PCOR = COV * 0
  651 +; FOR i = 0, n-1 DO FOR j = 0, n-1 DO $
  652 +; PCOR[i,j] = COV[i,j]/sqrt(COV[i,i]*COV[j,j])
  653 +; or equivalently, in vector notation,
  654 +; PCOR = COV / (PERROR # PERROR)
554 655 ;
555 656 ; If NOCOVAR is set or MPFIT terminated abnormally, then
556 657 ; COVAR is set to a scalar with value !VALUES.D_NAN.
... ... @@ -558,7 +659,8 @@
558 659 ; DOF - number of degrees of freedom, computed as
559 660 ; DOF = N_ELEMENTS(DEVIATES) - NFREE
560 661 ; Note that this doesn't account for pegged parameters (see
561   -; NPEGGED).
  662 +; NPEGGED). It also does not account for data points which
  663 +; are assigned zero weight by the user function.
562 664 ;
563 665 ; ERRMSG - a string error or warning message is returned.
564 666 ;
... ... @@ -699,10 +801,24 @@
699 801 ; change to a printable character like 'q'.
700 802 ;
701 803 ; MAXITER - The maximum number of iterations to perform. If the
702   -; number is exceeded, then the STATUS value is set to 5
703   -; and MPFIT returns.
  804 +; number of calculation iterations exceeds MAXITER, then
  805 +; the STATUS value is set to 5 and MPFIT returns.
  806 +;
  807 +; If MAXITER EQ 0, then MPFIT does not iterate to adjust
  808 +; parameter values; however, the user function is evaluated
  809 +; and parameter errors/covariance/Jacobian are estimated
  810 +; before returning.
704 811 ; Default: 200 iterations
705 812 ;
  813 +; MIN_VERSION - The minimum requested version number. This must be
  814 +; a scalar string of the form returned by the VERSION
  815 +; keyword. If the current version of MPFIT does not
  816 +; satisfy the minimum requested version number, then,
  817 +; MPFIT(/query, min_version='...') returns 0
  818 +; MPFIT(...) returns NAN
  819 +; Default: no version number check
  820 +; NOTE: MIN_VERSION was added in MPFIT version 1.70
  821 +;
706 822 ; NFEV - the number of MYFUNCT function evaluations performed.
707 823 ;
708 824 ; NFREE - the number of free parameters in the fit. This includes
... ... @@ -761,6 +877,19 @@
761 877 ; DOF = N_ELEMENTS(X) - N_ELEMENTS(PARMS) ; deg of freedom
762 878 ; PCERROR = PERROR * SQRT(BESTNORM / DOF) ; scaled uncertainties
763 879 ;
  880 +; PFREE_INDEX - upon return, PFREE_INDEX contains an index array
  881 +; which indicates which parameter were allowed to
  882 +; vary. I.e. of all the parameters PARMS, only
  883 +; PARMS[PFREE_INDEX] were varied.
  884 +;
  885 +; QUERY - if set, then MPFIT() will return immediately with one of
  886 +; the following values:
  887 +; 1 - if MIN_VERSION is not set
  888 +; 1 - if MIN_VERSION is set and MPFIT satisfies the minimum
  889 +; 0 - if MIN_VERSION is set and MPFIT does not satisfy it
  890 +; The VERSION output keyword is always set upon return.
  891 +; Default: not set.
  892 +;
764 893 ; QUIET - set this keyword when no textual output should be printed
765 894 ; by MPFIT
766 895 ;
... ... @@ -827,6 +956,14 @@
827 956 ; the function and its derivatives. This status indicator
828 957 ; is neither an error nor a convergence indicator.
829 958 ;
  959 +; VERSION - upon return, VERSION will be set to the MPFIT internal
  960 +; version number. The version number will be a string of
  961 +; the form "X.Y" where X is a major revision number and Y
  962 +; is a minor revision number.
  963 +; NOTE: the VERSION keyword was not present before
  964 +; MPFIT version number 1.70, therefore, callers must
  965 +; use exception handling when using this keyword.
  966 +;
830 967 ; XTOL - a nonnegative input variable. Termination occurs when the
831 968 ; relative error between two consecutive iterates is at most
832 969 ; XTOL (and STATUS is accordingly set to 2 or 3). Therefore,
... ... @@ -965,18 +1102,24 @@
965 1102 ; with MPFIT," in proc. Astronomical Data Analysis Software and
966 1103 ; Systems XVIII, Quebec, Canada, ASP Conference Series, Vol. XXX, eds.
967 1104 ; D. Bohlender, P. Dowler & D. Durand (Astronomical Society of the
968   -; Pacific: San Francisco), p. XXX
969   -; http://arxiv.org/XXXXX
  1105 +; Pacific: San Francisco), p. 251-254 (ISBN: 978-1-58381-702-5)
  1106 +; http://arxiv.org/abs/0902.2850
  1107 +; Link to NASA ADS: http://adsabs.harvard.edu/abs/2009ASPC..411..251M
  1108 +; Link to ASP: http://aspbooks.org/a/volumes/table_of_contents/411
  1109 +;
  1110 +; Refer to the MPFIT website as:
  1111 +; http://purl.com/net/mpfit
970 1112 ;
971   -; MINPACK-1, Jorge More', available from netlib.
  1113 +; MINPACK-1 software, by Jorge More' et al, available from netlib.
972 1114 ; http://www.netlib.org/
973 1115 ;
974 1116 ; "Optimization Software Guide," Jorge More' and Stephen Wright,
975 1117 ; SIAM, *Frontiers in Applied Mathematics*, Number 14.
  1118 +; (ISBN: 978-0-898713-22-0)
976 1119 ;
977   -; More', J. 1977, ``The Levenberg-Marquardt Algorithm:
978   -; Implementation and Theory,'' in *Numerical Analysis*,
979   -; vol. 630, ed. G. A. Watson (Springer-Verlag: Berlin), 105
  1120 +; More', J. 1978, "The Levenberg-Marquardt Algorithm: Implementation
  1121 +; and Theory," in Numerical Analysis, vol. 630, ed. G. A. Watson
  1122 +; (Springer-Verlag: Berlin), p. 105 (DOI: 10.1007/BFb0067690 )
980 1123 ;
981 1124 ; MODIFICATION HISTORY:
982 1125 ; Translated from MINPACK-1 in FORTRAN, Apr-Jul 1998, CM
... ... @@ -1141,12 +1284,33 @@
1141 1284 ; the covariance matrix to be computed, CM, 14 Apr 2009
1142 1285 ; Avoid numerical underflow while solving for the LM parameter,
1143 1286 ; (thanks to Sergey Koposov) CM, 14 Apr 2009
1144   -;
1145   -; $Id: mpfit.pro,v 1.64 2009/05/05 05:37:49 craigm Exp $
  1287 +; Use individual functions for all possible MPFIT_CALL permutations,
  1288 +; (and make sure the syntax is right) CM, 01 Sep 2009
  1289 +; Correct behavior of MPMAXSTEP when some parameters are frozen,
  1290 +; thanks to Josh Destree, CM, 22 Nov 2009
  1291 +; Update the references section, CM, 22 Nov 2009
  1292 +; 1.70 - Add the VERSION and MIN_VERSION keywords, CM, 22 Nov 2009
  1293 +; 1.71 - Store pre-calculated revision in common, CM, 23 Nov 2009
  1294 +; 1.72-1.74 - Documented alternate method to compute correlation matrix,
  1295 +; CM, 05 Feb 2010
  1296 +; 1.75 - Enforce TIED constraints when preparing to terminate the
  1297 +; routine, CM, 2010-06-22
  1298 +; 1.76 - Documented input keywords now are not modified upon output,
  1299 +; CM, 2010-07-13
  1300 +; 1.77 - Upon user request (/CALC_FJAC), compute Jacobian matrix and
  1301 +; return in BEST_FJAC; also return best residuals in
  1302 +; BEST_RESID; also return an index list of free parameters as
  1303 +; PFREE_INDEX; add a fencepost to prevent recursion
  1304 +; CM, 2010-10-27
  1305 +; 1.79 - Documentation corrections. CM, 2011-08-26
  1306 +; 1.81 - Fix bug in interaction of AUTODERIVATIVE=0 and .MPSIDE=3;
  1307 +; Document FJAC_MASK. CM, 2012-05-08
  1308 +;
  1309 +; $Id: mpfit.pro,v 1.82 2012/09/27 23:59:44 cmarkwar Exp $
1146 1310 ;-
1147 1311 ; Original MINPACK by More' Garbow and Hillstrom, translated with permission
1148 1312 ; Modifications and enhancements are:
1149   -; Copyright (C) 1997-2003, 2004, 2005, 2006, 2007, 2008, 2009, Craig Markwardt
  1313 +; Copyright (C) 1997-2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Craig Markwardt
1150 1314 ; This software is provided as is without any warranty whatsoever.
1151 1315 ; Permission to use, copy, modify, and distribute modified or
1152 1316 ; unmodified copies is granted, provided this copyright and disclaimer
... ... @@ -1215,6 +1379,44 @@ pro mpfit_setmachar, double=isdouble
1215 1379 end
1216 1380  
1217 1381  
  1382 +; Call user function with no _EXTRA parameters
  1383 +function mpfit_call_func_noextra, fcn, x, fjac, _EXTRA=extra
  1384 + if n_params() EQ 2 then begin
  1385 + return, call_function(fcn, x)
  1386 + endif else begin
  1387 + return, call_function(fcn, x, fjac)
  1388 + endelse
  1389 +end
  1390 +
  1391 +; Call user function with _EXTRA parameters
  1392 +function mpfit_call_func_extra, fcn, x, fjac, _EXTRA=extra
  1393 + if n_params() EQ 2 then begin
  1394 + return, call_function(fcn, x, _EXTRA=extra)
  1395 + endif else begin
  1396 + return, call_function(fcn, x, fjac, _EXTRA=extra)
  1397 + endelse
  1398 +end
  1399 +
  1400 +; Call user procedure with no _EXTRA parameters
  1401 +function mpfit_call_pro_noextra, fcn, x, fjac, _EXTRA=extra
  1402 + if n_params() EQ 2 then begin
  1403 + call_procedure, fcn, x, f
  1404 + endif else begin
  1405 + call_procedure, fcn, x, f, fjac
  1406 + endelse
  1407 + return, f
  1408 +end
  1409 +
  1410 +; Call user procedure with _EXTRA parameters
  1411 +function mpfit_call_pro_extra, fcn, x, fjac, _EXTRA=extra
  1412 + if n_params() EQ 2 then begin
  1413 + call_procedure, fcn, x, f, _EXTRA=extra
  1414 + endif else begin
  1415 + call_procedure, fcn, x, f, fjac, _EXTRA=extra
  1416 + endelse
  1417 + return, f
  1418 +end
  1419 +
1218 1420  
1219 1421 ;; Call user function or procedure, with _EXTRA or not, with
1220 1422 ;; derivatives or not.
... ... @@ -1224,36 +1426,19 @@ function mpfit_call, fcn, x, fjac, _EXTRA=extra
1224 1426 common mpfit_config, mpconfig
1225 1427  
1226 1428 if keyword_set(mpconfig.qanytied) then mpfit_tie, x, mpconfig.ptied
1227   -
1228   - ;; Decide whether we are calling a procedure or function
1229   - if mpconfig.proc then proc = 1 else proc = 0
1230   - mpconfig.nfev = mpconfig.nfev + 1
1231 1429  
1232   - if proc then begin
1233   - if n_params() EQ 3 then begin
1234   - if n_elements(extra) GT 0 then $
1235   - call_procedure, fcn, x, f, fjac, _EXTRA=extra $
1236   - else $
1237   - call_procedure, fcn, x, f, fjac
1238   - endif else begin
1239   - if n_elements(extra) GT 0 then $
1240   - call_procedure, fcn, x, f, _EXTRA=extra $
1241   - else $
1242   - call_procedure, fcn, x, f
1243   - endelse
  1430 + ;; Decide whether we are calling a procedure or function, and
  1431 + ;; with/without FUNCTARGS
  1432 + proname = 'MPFIT_CALL'
  1433 + proname = proname + ((mpconfig.proc) ? '_PRO' : '_FUNC')
  1434 + proname = proname + ((n_elements(extra) GT 0) ? '_EXTRA' : '_NOEXTRA')
  1435 +
  1436 + if n_params() EQ 2 then begin
  1437 + f = call_function(proname, fcn, x, _EXTRA=extra)
1244 1438 endif else begin
1245   - if n_params() EQ 3 then begin
1246   - if n_elements(extra) GT 0 then $
1247   - f = call_function(fcn, x, fjac, _EXTRA=extra) $
1248   - else $
1249   - f = call_function(fcn, x, fjac)
1250   - endif else begin
1251   - if n_elements(extra) GT 0 then $
1252   - f = call_function(fcn, x, _EXTRA=extra) $
1253   - else $
1254   - f = call_function(fcn, x)
1255   - endelse
1256   - endelse
  1439 + f = call_function(proname, fcn, x, fjac, _EXTRA=extra)
  1440 + endelse
  1441 + mpconfig.nfev = mpconfig.nfev + 1
1257 1442  
1258 1443 if n_params() EQ 2 AND mpconfig.damp GT 0 then begin
1259 1444 damp = mpconfig.damp[0]
... ... @@ -1309,12 +1494,14 @@ function mpfit_fdjac2, fcn, x, fvec, step, ulimited, ulimit, dside, $
1309 1494 ;; 2. AUTODERIVATIVE=1, but P[i].MPSIDE EQ 3
1310 1495  
1311 1496 if keyword_set(autoderiv) EQ 0 OR max(dside[ifree] EQ 3) EQ 1 then begin
1312   - fjac = intarr(nall)
  1497 + fjac_mask = intarr(nall)
1313 1498 ;; Specify which parameters need derivatives
1314   - ;; ---- Case 2 ------ ----- Case 1 -----
1315   - fjac[ifree] = (dside[ifree] EQ 3) OR (keyword_set(autoderiv) EQ 0)
1316   - if has_debug_deriv then print, fjac, format='("# FJAC_MASK = ",100000(I0," ",:))'
  1499 + ;; ---- Case 2 ------ ----- Case 1 -----
  1500 + fjac_mask[ifree] = (dside[ifree] EQ 3) OR (keyword_set(autoderiv) EQ 0)
  1501 + if has_debug_deriv then $
  1502 + print, fjac_mask, format='("# FJAC_MASK = ",100000(I0," ",:))'
1317 1503  
  1504 + fjac = fjac_mask ;; Pass the mask to the calling function as FJAC
1318 1505 mperr = 0
1319 1506 fp = mpfit_call(fcn, xall, fjac, _EXTRA=fcnargs)
1320 1507 iflag = mperr
... ... @@ -1340,12 +1527,13 @@ function mpfit_fdjac2, fcn, x, fvec, step, ulimited, ulimit, dside, $
1340 1527 ;; Select only the free parameters
1341 1528 if n_elements(ifree) LT nall then $
1342 1529 fjac = reform(fjac[*,ifree], m, n, /overwrite)
1343   -
1344   - ;; If there are no more free parameters to analyze, then
1345   - ;; return now, (but not if we are debugging the derivatives)
1346   - if ((keyword_set(autoderiv) EQ 0) OR $
1347   - (min(dside[ifree]) EQ 1) OR $
1348   - (has_debug_deriv EQ 0)) then return, fjac
  1530 +
  1531 + ;; Are we done computing derivatives? The answer is, YES, if we
  1532 + ;; computed explicit derivatives for all free parameters, EXCEPT
  1533 + ;; when we are going on to compute debugging derivatives.
  1534 + if min(fjac_mask[ifree]) EQ 1 AND NOT has_debug_deriv then begin
  1535 + return, fjac
  1536 + endif
1349 1537 endif
1350 1538  
1351 1539 ;; Final output array, if it was not already created above
... ... @@ -2174,7 +2362,7 @@ pro mpfit_defiter, fcn, x, iter, fnorm, FUNCTARGS=fcnargs, $
2174 2362 if n_elements(fmt) GT 0 then begin
2175 2363 call_procedure, iterprint, x, format=fmt, _EXTRA=iterargs
2176 2364 endif else begin
2177   - if n_elements(pformat) EQ 0 then pformat = '(G20.6)'
  2365 + if n_elements(pformat) EQ 0 then pformat = '(G40.6)'
2178 2366 parname = 'P('+strtrim(iprint,2)+')'
2179 2367 pformats = strarr(nprint) + pformat
2180 2368  
... ... @@ -2398,6 +2586,45 @@ function mpfit_covar, rr, ipvt, tol=tol
2398 2586 return, r
2399 2587 end
2400 2588  
  2589 +;; Parse the RCSID revision number
  2590 +function mpfit_revision
  2591 + ;; NOTE: this string is changed every time an RCS check-in occurs
  2592 + revision = '$Revision: 1.82 $'
  2593 +
  2594 + ;; Parse just the version number portion
  2595 + revision = stregex(revision,'\$'+'Revision: *([0-9.]+) *'+'\$',/extract,/sub)
  2596 + revision = revision[1]
  2597 + return, revision
  2598 +end
  2599 +
  2600 +;; Parse version numbers of the form 'X.Y'
  2601 +function mpfit_parse_version, version
  2602 + sz = size(version)
  2603 + if sz[sz[0]+1] NE 7 then return, 0
  2604 +
  2605 + s = stregex(version[0], '^([0-9]+)\.([0-9]+)$', /extract,/sub)
  2606 + if s[0] NE version[0] then return, 0
  2607 + return, long(s[1:2])
  2608 +end
  2609 +
  2610 +;; Enforce a minimum version number
  2611 +function mpfit_min_version, version, min_version
  2612 + mv = mpfit_parse_version(min_version)
  2613 + if mv[0] EQ 0 then return, 0
  2614 + v = mpfit_parse_version(version)
  2615 +
  2616 + ;; Compare version components
  2617 + if v[0] LT mv[0] then return, 0
  2618 + if v[1] LT mv[1] then return, 0
  2619 + return, 1
  2620 +end
  2621 +
  2622 +; Manually reset recursion fencepost if the user gets in trouble
  2623 +pro mpfit_reset_recursion
  2624 + common mpfit_fencepost, mpfit_fencepost_active
  2625 + mpfit_fencepost_active = 0
  2626 +end
  2627 +
2401 2628 ; **********
2402 2629 ;
2403 2630 ; subroutine lmdif
... ... @@ -2579,24 +2806,48 @@ end
2579 2806 ;
2580 2807 ; **********
2581 2808 function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
2582   - ftol=ftol, xtol=xtol, gtol=gtol, epsfcn=epsfcn, resdamp=damp, $
  2809 + ftol=ftol0, xtol=xtol0, gtol=gtol0, epsfcn=epsfcn, $
  2810 + resdamp=damp0, $
2583 2811 nfev=nfev, maxiter=maxiter, errmsg=errmsg, $
2584   - factor=factor, nprint=nprint, STATUS=info, $
2585   - iterproc=iterproc, iterargs=iterargs, iterstop=ss,$
  2812 + factor=factor0, nprint=nprint0, STATUS=info, $
  2813 + iterproc=iterproc0, iterargs=iterargs, iterstop=ss,$
2586 2814 iterkeystop=iterkeystop, $
2587 2815 niter=iter, nfree=nfree, npegged=npegged, dof=dof, $
2588   - diag=diag, rescale=rescale, autoderivative=autoderiv, $
2589   - perror=perror, covar=covar, nocovar=nocovar, bestnorm=fnorm, $
  2816 + diag=diag, rescale=rescale, autoderivative=autoderiv0, $
  2817 + pfree_index=ifree, $
  2818 + perror=perror, covar=covar, nocovar=nocovar, $
  2819 + bestnorm=fnorm, best_resid=fvec, $
  2820 + best_fjac=output_fjac, calc_fjac=calc_fjac, $
2590 2821 parinfo=parinfo, quiet=quiet, nocatch=nocatch, $
2591   - fastnorm=fastnorm, proc=proc, query=query, $
  2822 + fastnorm=fastnorm0, proc=proc, query=query, $
2592 2823 external_state=state, external_init=extinit, $
2593   - external_fvec=efvec, external_fjac=efjac
2594   -
  2824 + external_fvec=efvec, external_fjac=efjac, $
  2825 + version=version, min_version=min_version0
  2826 +
  2827 +
2595 2828 COMPILE_OPT strictarr
2596 2829 info = 0L
2597 2830 errmsg = ''
2598 2831  
2599   - if keyword_set(query) then return, 1
  2832 + ;; Compute the revision number, to be returned in the VERSION and
  2833 + ;; QUERY keywords.
  2834 + common mpfit_revision_common, mpfit_revision_str
  2835 + if n_elements(mpfit_revision_str) EQ 0 then $
  2836 + mpfit_revision_str = mpfit_revision()
  2837 + version = mpfit_revision_str
  2838 +
  2839 + if keyword_set(query) then begin
  2840 + if n_elements(min_version0) GT 0 then $
  2841 + if mpfit_min_version(version, min_version0[0]) EQ 0 then $
  2842 + return, 0
  2843 + return, 1
  2844 + endif
  2845 +
  2846 + if n_elements(min_version0) GT 0 then $
  2847 + if mpfit_min_version(version, min_version0[0]) EQ 0 then begin
  2848 + message, 'ERROR: minimum required version '+min_version0[0]+' not satisfied', /info
  2849 + return, !values.d_nan
  2850 + endif
2600 2851  
2601 2852 if n_params() EQ 0 then begin
2602 2853 message, "USAGE: PARMS = MPFIT('MYFUNCT', START_PARAMS, ... )", /info
... ... @@ -2605,15 +2856,15 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
2605 2856  
2606 2857 ;; Use of double here not a problem since f/x/gtol are all only used
2607 2858 ;; in comparisons
2608   - if n_elements(ftol) EQ 0 then ftol = 1.D-10
2609   - if n_elements(xtol) EQ 0 then xtol = 1.D-10
2610   - if n_elements(gtol) EQ 0 then gtol = 1.D-10
2611   - if n_elements(factor) EQ 0 then factor = 100.
2612   - if n_elements(nprint) EQ 0 then nprint = 1
2613   - if n_elements(iterproc) EQ 0 then iterproc = 'MPFIT_DEFITER'
2614   - if n_elements(autoderiv) EQ 0 then autoderiv = 1
2615   - if n_elements(fastnorm) EQ 0 then fastnorm = 0
2616   - if n_elements(damp) EQ 0 then damp = 0 else damp = damp[0]
  2859 + if n_elements(ftol0) EQ 0 then ftol = 1.D-10 else ftol = ftol0[0]
  2860 + if n_elements(xtol0) EQ 0 then xtol = 1.D-10 else xtol = xtol0[0]
  2861 + if n_elements(gtol0) EQ 0 then gtol = 1.D-10 else gtol = gtol0[0]
  2862 + if n_elements(factor0) EQ 0 then factor = 100. else factor = factor0[0]
  2863 + if n_elements(nprint0) EQ 0 then nprint = 1 else nprint = nprint0[0]
  2864 + if n_elements(iterproc0) EQ 0 then iterproc = 'MPFIT_DEFITER' else iterproc = iterproc0[0]
  2865 + if n_elements(autoderiv0) EQ 0 then autoderiv = 1 else autoderiv = autoderiv0[0]
  2866 + if n_elements(fastnorm0) EQ 0 then fastnorm = 0 else fastnorm = fastnorm0[0]
  2867 + if n_elements(damp0) EQ 0 then damp = 0 else damp = damp0[0]
2617 2868  
2618 2869 ;; These are special configuration parameters that can't be easily
2619 2870 ;; passed by MPFIT directly.
... ... @@ -2631,6 +2882,18 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
2631 2882 nfree = 0L
2632 2883 npegged = 0L
2633 2884 dof = 0L
  2885 + output_fjac = 0L
  2886 +
  2887 + ;; Set up a persistent fencepost that prevents recursive calls
  2888 + common mpfit_fencepost, mpfit_fencepost_active
  2889 + if n_elements(mpfit_fencepost_active) EQ 0 then mpfit_fencepost_active = 0
  2890 + if mpfit_fencepost_active then begin
  2891 + errmsg = 'ERROR: recursion detected; you cannot run MPFIT recursively'
  2892 + goto, TERMINATE
  2893 + endif
  2894 + ;; Only activate the fencepost if we are not in debugging mode
  2895 + if NOT keyword_set(nocatch) then mpfit_fencepost_active = 1
  2896 +
2634 2897  
2635 2898 ;; Parameter damping doesn't work when user is providing their own
2636 2899 ;; gradients.
... ... @@ -2669,8 +2932,9 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
2669 2932 ;; Handle error conditions gracefully
2670 2933 if NOT keyword_set(nocatch) then begin
2671 2934 catch, catcherror
2672   - if catcherror NE 0 then begin
  2935 + if catcherror NE 0 then begin ;; An error occurred!!!
2673 2936 catch, /cancel
  2937 + mpfit_fencepost_active = 0
2674 2938 err_string = ''+!error_state.msg
2675 2939 message, /cont, 'Error detected while '+catch_msg+':'
2676 2940 message, /cont, err_string
... ... @@ -2795,8 +3059,6 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
2795 3059 errmsg = 'ERROR: MPMINSTEP is greater than MPMAXSTEP'
2796 3060 goto, TERMINATE
2797 3061 endif
2798   - wh = where(qmin OR qmax, ct)
2799   - qminmax = ct GT 0
2800 3062  
2801 3063 ;; Finish up the free parameters
2802 3064 ifree = where(pfixed NE 1, nfree)
... ... @@ -2819,6 +3081,12 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
2819 3081 ;; Compose only VARYING parameters
2820 3082 xnew = xall ;; xnew is the set of parameters to be returned
2821 3083 x = xnew[ifree] ;; x is the set of free parameters
  3084 + ; Same for min/max step diagnostics
  3085 + qmin = qmin[ifree] & minstep = minstep[ifree]
  3086 + qmax = qmax[ifree] & maxstep = maxstep[ifree]
  3087 + wh = where(qmin OR qmax, ct)
  3088 + qminmax = ct GT 0
  3089 +
2822 3090  
2823 3091 ;; LIMITED parameters ?
2824 3092 mpfit_parinfo, parinfo, tagnames, 'LIMITED', limited, status=st1
... ... @@ -3012,6 +3280,8 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
3012 3280 iflag = 2
3013 3281 if NOT isext then begin
3014 3282 catch_msg = 'calling MPFIT_FDJAC2'
  3283 + ;; NOTE! If you change this call then change the one during
  3284 + ;; clean-up as well!
3015 3285 fjac = mpfit_fdjac2(fcn, x, fvec, step, qulim, ulim, dside, $
3016 3286 iflag=iflag, epsfcn=epsfcn, $
3017 3287 autoderiv=autoderiv, dstep=dstep, $
... ... @@ -3043,6 +3313,7 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
3043 3313 ;; See if any "pegged" values should keep their derivatives
3044 3314 if (nlpeg GT 0) then begin
3045 3315 ;; Total derivative of sum wrt lower pegged parameters
  3316 + ;; Note: total(fvec*fjac[*,i]) is d(CHI^2)/dX[i]
3046 3317 for i = 0L, nlpeg-1 do begin
3047 3318 sum = total(fvec * fjac[*,whlpeg[i]])
3048 3319 if sum GT 0 then fjac[*,whlpeg[i]] = 0
... ... @@ -3057,24 +3328,42 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
3057 3328 endif
3058 3329 endif
3059 3330  
  3331 + ;; Save a copy of the Jacobian if the user requests it...
  3332 + if keyword_set(calc_fjac) then output_fjac = fjac
  3333 +
  3334 + ;; =====================
3060 3335 ;; Compute the QR factorization of the jacobian
3061 3336 catch_msg = 'calling MPFIT_QRFAC'
3062   - mpfit_qrfac, fjac, ipvt, wa1, wa2, /pivot
3063   -
  3337 + ;; IN: Jacobian
  3338 + ;; OUT: Hh Vects Permutation RDIAG ACNORM
  3339 + mpfit_qrfac, fjac, ipvt, wa1, wa2, /pivot
  3340 + ;; Jacobian - jacobian matrix computed by mpfit_fdjac2
  3341 + ;; Hh vects - house holder vectors from QR factorization & R matrix
  3342 + ;; Permutation - permutation vector for pivoting
  3343 + ;; RDIAG - diagonal elements of R matrix
  3344 + ;; ACNORM - norms of input Jacobian matrix before factoring
  3345 +
  3346 + ;; =====================
3064 3347 ;; On the first iteration if "diag" is unspecified, scale
3065 3348 ;; according to the norms of the columns of the initial jacobian
3066 3349 catch_msg = 'rescaling diagonal elements'
3067 3350 if (iter EQ 1) then begin
  3351 + ;; Input: WA2 = root sum of squares of original Jacobian matrix
  3352 + ;; DIAG = user-requested diagonal (not documented!)
  3353 + ;; FACTOR = user-requested norm factor (not documented!)
  3354 + ;; Output: DIAG = Diagonal scaling values
  3355 + ;; XNORM = sum of squared scaled residuals
  3356 + ;; DELTA = rescaled XNORM
3068 3357  
3069 3358 if NOT keyword_set(rescale) OR (n_elements(diag) LT n) then begin
3070   - diag = wa2
3071   - wh = where (diag EQ 0, ct)
  3359 + diag = wa2 ;; Calculated from original Jacobian
  3360 + wh = where (diag EQ 0, ct) ;; Handle zero values
3072 3361 if ct GT 0 then diag[wh] = one
3073 3362 endif
3074 3363  
3075 3364 ;; On the first iteration, calculate the norm of the scaled x
3076 3365 ;; and initialize the step bound delta
3077   - wa3 = diag * x
  3366 + wa3 = diag * x ;; WA3 is temp variable
3078 3367 xnorm = mpfit_enorm(wa3)
3079 3368 delta = factor*xnorm
3080 3369 if delta EQ zero then delta = zero + factor
... ... @@ -3176,7 +3465,7 @@ function mpfit, fcn, xall, FUNCTARGS=fcnargs, SCALE_FCN=scalfcn, $
3176 3465 nwa1 = wa1 * alpha
3177 3466 whmax = where(qmax AND maxstep GT 0, ct)
3178 3467 if ct GT 0 then begin
3179   - mrat = max(abs(nwa1[whmax])/abs(maxstep[ifree[whmax]]))
  3468 + mrat = max(abs(nwa1[whmax])/abs(maxstep[whmax]))
3180 3469 if mrat GT 1 then alpha = alpha / mrat
3181 3470 endif
3182 3471 endif
... ... @@ -3316,6 +3605,7 @@ TERMINATE:
3316 3605 iflag = 0
3317 3606 if n_elements(xnew) EQ 0 then goto, FINAL_RETURN
3318 3607 if nfree EQ 0 then xnew = xall else xnew[ifree] = x
  3608 + if n_elements(qanytied) GT 0 then if qanytied then mpfit_tie, xnew, ptied
3319 3609 dof = n_elements(fvec) - nfree
3320 3610  
3321 3611  
... ... @@ -3350,7 +3640,8 @@ TERMINATE:
3350 3640 (qllim AND (x EQ llim)), npegged)
3351 3641 endif
3352 3642  
3353   - if fcn NE '(EXTERNAL)' AND nprint GT 0 AND info GT 0 then begin
  3643 + ;; Calculate final function value (FNORM) and residuals (FVEC)
  3644 + if isext EQ 0 AND nprint GT 0 AND info GT 0 then begin
3354 3645 catch_msg = 'calling '+fcn
3355 3646 fvec = mpfit_call(fcn, xnew, _EXTRA=fcnargs)
3356 3647 catch_msg = 'in the termination phase'
... ... @@ -3394,10 +3685,12 @@ TERMINATE:
3394 3685 perror[wh] = sqrt(covar[wh, wh])
3395 3686 endif
3396 3687 endif
  3688 +
3397 3689 ; catch_msg = 'returning the result'
3398 3690 ; profvals.mpfit = profvals.mpfit + (systime(1) - prof_start)
3399 3691  
3400 3692 FINAL_RETURN:
  3693 + mpfit_fencepost_active = 0
3401 3694 nfev = mpconfig.nfev
3402 3695 if n_elements(xnew) EQ 0 then return, !values.d_nan
3403 3696 return, xnew
... ...
src/idl/mpfitfun.pro
... ... @@ -73,12 +73,61 @@
73 73 ; using the ERROR_CODE common block variable, as described
74 74 ; below under the MPFIT_ERROR common block definition.
75 75 ;
76   -; See the discussion under "EXPLICIT DERIVATIVES" and AUTODERIVATIVE
77   -; in MPFIT.PRO if you wish to compute the derivatives for yourself.
78   -; AUTODERIVATIVE is accepted by MPFITFUN and passed directly to
79   -; MPFIT. The user function must accept one additional parameter, DP,
80   -; which contains the derivative of the user function with respect to
81   -; each parameter at each data point, as described in MPFIT.PRO.
  76 +; MPFIT by default calculates derivatives numerically via a finite
  77 +; difference approximation. However, the user function *may*
  78 +; calculate the derivatives if desired, but only if the model
  79 +; function is declared with an additional position parameter, DP, as
  80 +; described below.
  81 +;
  82 +; To enable explicit derivatives for all parameters, set
  83 +; AUTODERIVATIVE=0.
  84 +;
  85 +; When AUTODERIVATIVE=0, the user function is responsible for
  86 +; calculating the derivatives of the user function with respect to
  87 +; each parameter. The user function should be declared as follows:
  88 +;
  89 +; ;
  90 +; ; MYFUNCT - example user function
  91 +; ; P - input parameter values (N-element array)
  92 +; ; DP - upon input, an N-vector indicating which parameters
  93 +; ; to compute derivatives for;
  94 +; ; upon output, the user function must return
  95 +; ; an ARRAY(M,N) of derivatives in this keyword
  96 +; ; (keywords) - any other keywords specified by FUNCTARGS
  97 +; ; RETURNS - function values
  98 +; ;
  99 +; FUNCTION MYFUNCT, x, p, dp [, (additional keywords if desired)]
  100 +; model = F(x, p) ;; Model function
  101 +;
  102 +; if n_params() GT 2 then begin
  103 +; ; Create derivative and compute derivative array
  104 +; requested = dp ; Save original value of DP
  105 +; dp = make_array(n_elements(x), n_elements(p), value=x[0]*0)
  106 +;
  107 +; ; Compute derivative if requested by caller
  108 +; for i = 0, n_elements(p)-1 do if requested(i) NE 0 then $
  109 +; dp(*,i) = FGRAD(x, p, i)
  110 +; endif
  111 +;
  112 +; return, resid
  113 +; END
  114 +;
  115 +; where FGRAD(x, p, i) is a model function which computes the
  116 +; derivative of the model F(x,p) with respect to parameter P(i) at X.
  117 +;
  118 +; Derivatives should be returned in the DP array. DP should be an
  119 +; ARRAY(m,n) array, where m is the number of data points and n is the
  120 +; number of parameters. DP[i,j] is the derivative of the ith
  121 +; function value with respect to the jth parameter.
  122 +;
  123 +; MPFIT may not always request derivatives from the user function.
  124 +; In those cases, the parameter DP is not passed. Therefore
  125 +; functions can use N_PARAMS() to indicate whether they must compute
  126 +; the derivatives or not.
  127 +;
  128 +; For additional information about explicit derivatives, including
  129 +; additional settings and debugging options, see the discussion under
  130 +; "EXPLICIT DERIVATIVES" and AUTODERIVATIVE in MPFIT.PRO.
82 131 ;
83 132 ; CONSTRAINING PARAMETER VALUES WITH THE PARINFO KEYWORD
84 133 ;
... ... @@ -253,6 +302,21 @@
253 302 ; BESTNORM - the value of the summed squared residuals for the
254 303 ; returned parameter values.
255 304 ;
  305 +; BEST_FJAC - upon return, BEST_FJAC contains the Jacobian, or
  306 +; partial derivative, matrix for the best-fit model.
  307 +; The values are an array,
  308 +; ARRAY(N_ELEMENTS(DEVIATES),NFREE) where NFREE is the
  309 +; number of free parameters. This array is only
  310 +; computed if /CALC_FJAC is set, otherwise BEST_FJAC is
  311 +; undefined.
  312 +;
  313 +; The returned array is such that BEST_FJAC[I,J] is the
  314 +; partial derivative of the model with respect to
  315 +; parameter PARMS[PFREE_INDEX[J]].
  316 +;
  317 +; BEST_RESID - upon return, an array of best-fit deviates,
  318 +; normalized by the weights or errors.
  319 +;
256 320 ; COVAR - the covariance matrix for the set of parameters returned
257 321 ; by MPFIT. The matrix is NxN where N is the number of
258 322 ; parameters. The square root of the diagonal elements
... ... @@ -260,10 +324,12 @@
260 324 ; parameters IF errors were treated "properly" in MYFUNC.
261 325 ; Parameter errors are also returned in PERROR.
262 326 ;
263   -; To compute the correlation matrix, PCOR, use this:
264   -; IDL> PCOR = COV * 0
265   -; IDL> FOR i = 0, n-1 DO FOR j = 0, n-1 DO $
266   -; PCOR[i,j] = COV[i,j]/sqrt(COV[i,i]*COV[j,j])
  327 +; To compute the correlation matrix, PCOR, use this example:
  328 +; PCOR = COV * 0
  329 +; FOR i = 0, n-1 DO FOR j = 0, n-1 DO $
  330 +; PCOR[i,j] = COV[i,j]/sqrt(COV[i,i]*COV[j,j])
  331 +; or equivalently, in vector notation,
  332 +; PCOR = COV / (PERROR # PERROR)
267 333 ;
268 334 ; If NOCOVAR is set or MPFIT terminated abnormally, then
269 335 ; COVAR is set to a scalar with value !VALUES.D_NAN.
... ... @@ -275,7 +341,11 @@
275 341 ; DOF - number of degrees of freedom, computed as
276 342 ; DOF = N_ELEMENTS(DEVIATES) - NFREE
277 343 ; Note that this doesn't account for pegged parameters (see
278   -; NPEGGED).
  344 +; NPEGGED). It also does not account for data points which
  345 +; are assigned zero weight, for example if :
  346 +; * WEIGHTS[i] EQ 0, or
  347 +; * ERR[i] EQ infinity, or
  348 +; * any of the values is "undefined" and /NAN is set.
279 349 ;
280 350 ; ERRMSG - a string error or warning message is returned.
281 351 ;
... ... @@ -341,8 +411,13 @@
341 411 ; parameter values.
342 412 ;
343 413 ; MAXITER - The maximum number of iterations to perform. If the
344   -; number is exceeded, then the STATUS value is set to 5
345   -; and MPFIT returns.
  414 +; number of calculation iterations exceeds MAXITER, then
  415 +; the STATUS value is set to 5 and MPFIT returns.
  416 +;
  417 +; If MAXITER EQ 0, then MPFIT does not iterate to adjust
  418 +; parameter values; however, the user function is evaluated
  419 +; and parameter errors/covariance/Jacobian are estimated
  420 +; before returning.
346 421 ; Default: 200 iterations
347 422 ;
348 423 ; NAN - ignore infinite or NaN values in the Y, ERR or WEIGHTS
... ... @@ -366,12 +441,15 @@
366 441 ;
367 442 ; NPRINT - The frequency with which ITERPROC is called. A value of
368 443 ; 1 indicates that ITERPROC is called with every iteration,
369   -; while 2 indicates every other iteration, etc. Note that
370   -; several Levenberg-Marquardt attempts can be made in a
371   -; single iteration.
  444 +; while 2 indicates every other iteration, etc. Be aware
  445 +; that several Levenberg-Marquardt attempts can be made in
  446 +; a single iteration. Also, the ITERPROC is *always*
  447 +; called for the final iteration, regardless of the
  448 +; iteration number.
372 449 ; Default value: 1
373 450 ;
374   -; PARINFO - Provides a mechanism for more sophisticated constraints
  451 +; PARINFO - A one-dimensional array of structures.
  452 +; Provides a mechanism for more sophisticated constraints
375 453 ; to be placed on parameter values. When PARINFO is not
376 454 ; passed, then it is assumed that all parameters are free
377 455 ; and unconstrained. Values in PARINFO are never
... ... @@ -400,13 +478,43 @@
400 478 ; DOF = N_ELEMENTS(X) - N_ELEMENTS(PARMS) ; deg of freedom
401 479 ; PCERROR = PERROR * SQRT(BESTNORM / DOF) ; scaled uncertainties
402 480 ;
  481 +; PFREE_INDEX - upon return, PFREE_INDEX contains an index array
  482 +; which indicates which parameter were allowed to
  483 +; vary. I.e. of all the parameters PARMS, only
  484 +; PARMS[PFREE_INDEX] were varied.
  485 +;
  486 +; QUERY - if set, then MPFIT() will return immediately with one of
  487 +; the following values:
  488 +; 1 - if MIN_VERSION is not set
  489 +; 1 - if MIN_VERSION is set and MPFIT satisfies the minimum
  490 +; 0 - if MIN_VERSION is set and MPFIT does not satisfy it
  491 +; Default: not set.
  492 +;
403 493 ; QUIET - set this keyword when no textual output should be printed
404 494 ; by MPFIT
405 495 ;
406   -; STATUS - an integer status code is returned. All values other
407   -; than zero can represent success. It can have one of the
  496 +; STATUS - an integer status code is returned. All values greater
  497 +; than zero can represent success (however STATUS EQ 5 may
  498 +; indicate failure to converge). It can have one of the
408 499 ; following values:
409 500 ;
  501 +; -18 a fatal execution error has occurred. More information
  502 +; may be available in the ERRMSG string.
  503 +;
  504 +; -16 a parameter or function value has become infinite or an
  505 +; undefined number. This is usually a consequence of
  506 +; numerical overflow in the user's model function, which
  507 +; must be avoided.
  508 +;
  509 +; -15 to -1
  510 +; these are error codes that either MYFUNCT or ITERPROC
  511 +; may return to terminate the fitting process (see
  512 +; description of MPFIT_ERROR common below). If either
  513 +; MYFUNCT or ITERPROC set ERROR_CODE to a negative number,
  514 +; then that number is returned in STATUS. Values from -15
  515 +; to -1 are reserved for the user functions and will not
  516 +; clash with MPFIT.
  517 +;
410 518 ; 0 improper input parameters.
411 519 ;
412 520 ; 1 both actual and predicted relative reductions
... ... @@ -542,10 +650,14 @@
542 650 ; (the weights were not being applied), CM, 03 Sep 2007
543 651 ; Add COMPATIBILITY section, CM, 13 Dec 2007
544 652 ; Add documentation about NAN behavior, CM, 30 Mar 2009
  653 +; Add keywords BEST_RESIDS, CALC_FJAC, BEST_FJAC, PFREE_INDEX;
  654 +; update some documentation that had become stale, CM, 2010-10-28
  655 +; Documentation corrections, CM, 2011-08-26
  656 +; Additional documentation about explicit derivatives, CM, 2012-07-23
545 657 ;
546   -; $Id: mpfitfun.pro,v 1.1 2009/08/28 14:29:35 bernard Exp $
  658 +; $Id: mpfitfun.pro,v 1.19 2012/09/27 23:59:31 cmarkwar Exp $
547 659 ;-
548   -; Copyright (C) 1997-2002, 2003, 2006, 2007, 2009, Craig Markwardt
  660 +; Copyright (C) 1997-2002, 2003, 2006, 2007, 2009, 2010, 2011, 2012, Craig Markwardt
549 661 ; This software is provided as is without any warranty whatsoever.
550 662 ; Permission to use, copy, modify, and distribute modified or
551 663 ; unmodified copies is granted, provided this copyright and disclaimer
... ... @@ -629,6 +741,8 @@ end
629 741  
630 742 function mpfitfun, fcn, x, y, err, p, WEIGHTS=wts, FUNCTARGS=fa, $
631 743 BESTNORM=bestnorm, nfev=nfev, STATUS=status, $
  744 + best_resid=best_resid, pfree_index=ifree, $
  745 + calc_fjac=calc_fjac, best_fjac=best_fjac, $
632 746 parinfo=parinfo, query=query, CASH=cash, $
633 747 covar=covar, perror=perror, yfit=yfit, $
634 748 niter=niter, nfree=nfree, npegged=npegged, dof=dof, $
... ... @@ -733,11 +847,20 @@ function mpfitfun, fcn, x, y, err, p, WEIGHTS=wts, FUNCTARGS=fa, $
733 847 result = mpfit('mpfitfun_eval', p, SCALE_FCN=scalfcn, $
734 848 parinfo=parinfo, STATUS=status, nfev=nfev, BESTNORM=bestnorm,$
735 849 covar=covar, perror=perror, $
  850 + best_resid=best_resid, pfree_index=ifree, $
  851 + calc_fjac=calc_fjac, best_fjac=best_fjac, $
736 852 niter=niter, nfree=nfree, npegged=npegged, dof=dof, $
737 853 ERRMSG=errmsg, quiet=quiet, _EXTRA=extra)
738 854  
739 855 ;; Retrieve the fit value
740 856 yfit = temporary(mc)
  857 +
  858 + ;; Rescale the Jacobian according to parameter uncertainties
  859 + if keyword_set(calc_fjac) AND nfree GT 0 AND status GT 0 then begin
  860 + ec = 1/wc ;; Per-data-point errors (could be INF or NAN!)
  861 + for i = 0, nfree-1 do best_fjac[*,i] = - best_fjac[*,i] * ec
  862 + endif
  863 +
741 864 ;; Some cleanup
742 865 xc = 0 & yc = 0 & wc = 0 & ec = 0 & mc = 0 & ac = 0
743 866  
... ...
src/idl_misc/init_healpix.pro
... ... @@ -38,10 +38,10 @@ pro init_healpix, verbose=verbose
38 38 healpix_sysvar = '!HEALPIX'
39 39  
40 40 ; Healpix version
41   -version = '2.11c'
  41 +version = '2.12a'
42 42  
43 43 ; release data
44   -date = '2009-02-19'
  44 +date = '2009-08-06'
45 45  
46 46 ; Healpix directory
47 47 sv = 'HEALPIX'
... ...
src/idl_misc/isarray.pro 100755 โ†’ 100644
src/idl_misc/plotsym.pro 100755 โ†’ 100644
1   -pro plotsym, psym, psize, FILL=fill,thick=thick ;Define some plotting symbols
2   -;+
  1 +pro plotsym, psym, psize, FILL=fill,thick=thick,Color = color
  2 + ;+
3 3 ; NAME:
4 4 ; PLOTSYM
5 5 ; PURPOSE:
... ... @@ -8,8 +8,10 @@ pro plotsym, psym, psize, FILL=fill,thick=thick ;Define some plotting symbols
8 8 ; After a symbol has been defined with PLOTSYM, a plotting command should
9 9 ; follow with either PSYM = 8 or !P.PSYM = 8 (see USERSYM)
10 10 ;
  11 +; For additional rotationally symmetric plotting symbols, see VSYM.PRO
  12 +; or http://www.dfanning.com/documents/programs.html#SYMCAT
11 13 ; CALLING SEQUENCE:
12   -; PLOTSYM, PSYM,[ PSIZE, /FILL, THICK=]
  14 +; PLOTSYM, PSYM,[ PSIZE, /FILL, THICK=, COLOR=]
13 15 ;
14 16 ; INPUTS:
15 17 ; PSYM - The following integer values of PSYM will create the
... ... @@ -35,7 +37,7 @@ pro plotsym, psym, psize, FILL=fill,thick=thick ;Define some plotting symbols
35 37 ; The default is 0, unfilled symbol. Does not affect arrows
36 38 ; or character symbols.
37 39 ; THICK - Thickness of unfilled symbols. Default is 1.
38   -;
  40 +; COLOR - Color of the symbols, Default is !P.color
39 41 ; OUTPUTS:
40 42 ; None
41 43 ;
... ... @@ -58,12 +60,13 @@ pro plotsym, psym, psize, FILL=fill,thick=thick ;Define some plotting symbols
58 60 ; Written W. Landsman June 1992
59 61 ; 18-JAN-1996 Added a square symbol, HCW.
60 62 ; 98Aug20 Added keyword thick parameter - RCB.
  63 +; April 2001 Added COLOR keyword WBL
61 64 ;-
62 65 On_error,2
63 66  
64 67 if N_elements(psym) LT 1 then begin
65 68 print,'Syntax - PLOTSYM, psym, [ size, /FILL, THICK= ]'
66   - print,' PSYM values 0 - circle, 1 - down arrow, 2 - up arrow, 3 - star
  69 + print,' PSYM values 0 - circle, 1 - down arrow, 2 - up arrow, 3 - star'
67 70 print,' 4 - triangle, 5 - upside down triangle, 6 - left arrow'
68 71 print,' 7 - right arrow, 8 - square'
69 72 return
... ... @@ -90,10 +93,15 @@ pro plotsym, psym, psize, FILL=fill,thick=thick ;Define some plotting symbols
90 93 fill = 0
91 94 end
92 95 3: begin ;Star
93   - r = psize
94   - ang = (720. / 5*findgen(6) + 45) / !RADEG ;Define star angles every 144 deg
95   - xarr = r*cos(ang) & yarr = r*sin(ang)
96   - end
  96 + ang = (360. / 10 * findgen(11) + 90) / !RADEG ;star angles every 36 deg
  97 + r = ang*0
  98 + r[2*indgen(6)] = 1.
  99 + cp5 = cos(!pi/5.)
  100 + r1 = 2. * cp5 - 1. / cp5
  101 + r[2*indgen(5)+1] = r1
  102 + r = r * psize / sqrt(!pi/4.) * 2. / (1.+r1)
  103 + xarr = r * cos(ang) & yarr = r * sin(ang)
  104 + end
97 105 4: begin ;Triangle
98 106 xarr = [-1,0,1,-1]*psize
99 107 yarr = [-1,1,-1,-1]*psize
... ... @@ -119,8 +127,9 @@ pro plotsym, psym, psize, FILL=fill,thick=thick ;Define some plotting symbols
119 127 else: message,'Unknown plotting symbol value of '+strtrim(psym,2)
120 128 endcase
121 129  
  130 + if N_elements(color) GT 0 then $
  131 + usersym, xarr, yarr, FILL = fill,thick=thick, color = color else $
122 132 usersym, xarr, yarr, FILL = fill,thick=thick
123   -
124 133 return
125 134 end
126 135  
... ...
src/idl_misc/strtrans.pro
1   -; ;+ ; NAME: ; STRTRANS ; PURPOSE: ; Translate all occurences of one substring to another. ; CATEGORY: ; text/strings ; CALLING SEQUENCE: ; new = strtrans(oldstr,from,to,ned) ; INPUTS: ; oldstr -- string on which to operate. in ; May be an array. ; from -- substrings to be translated. May be in ; an array. ; to -- what strings in from should be in ; translated to. May be an array. ; KEYWORD PARAMETERS: ; /HELP -- Set this to print useful message and ; exit. ; OUTPUTS: ; new -- Translated string. Array if oldstr is out ; an array. ; ned -- number of substitutions performed in out ; oldstr. Array if oldstr is an array. ; COMMON BLOCKS: ; SIDE EFFECTS: ; NOTES: ; - Any of old, from, and to can be arrays. ; - from and to must have the same number of elements. ; EXAMPLE: ; inp='Many*bad!chars+in_here' ; from=['*','!','+','_'] ; to =[' ',' ',' ',' '] ; out = strtrans(inp,from,to,ned) ; Will produce out='Many bad chars in here', and set ned to 4. ; MODIFICATION HISTORY: ; $Id: strtrans.pro,v 1.4 2001/11/21 19:13:23 mcraig Exp $ ; $Log: strtrans.pro,v $ ; Revision 1.4 2001/11/21 19:13:23 mcraig ; Changed str_sep to strsplit. The former is now considered obsolete by RSI. ; ; Revision 1.3 1996/06/14 20:00:27 mcraig ; Updated Copyright info. ; ; Revision 1.2 1996/05/09 00:22:17 mcraig ; Sped up significantly by using str_sep to handle the translation. No longer ; relies on routines fromother user libraries. ; ; Revision 1.1 1996/01/31 18:47:37 mcraig ; Initial revision ; ; RELEASE: ; $Name: Rel_2_1 $ ; ; COPYRIGHT: ; Copyright (C) 1996 The Regents of the University of California, All ; Rights Reserved. Written by Matthew W. Craig. ; See the file COPYRIGHT for restrictions on distrubting this code. ; This code comes with absolutely NO warranty; see DISCLAIMER for details. ;- ; FUNCTION strtrans, InputString, from, to, ned, $ HELP=Help ; Bomb out to caller if error. On_error, 2 ; Offer help if we don't have at least InputString, from, and to, or ; if the user asks for it. IF (n_params() LT 3) OR keyword_set(help) THEN BEGIN offset = ' ' print, offset+'Translate all occurences of one substring to another.' print, offset+'new = strtrans(oldstr,from,to,ned)' print, offset+'Inputs:' print, offset+offset+'oldstr -- string on which to operate. in' print, offset+offset+' May be an array.' print, offset+offset+'from -- substrings to be translated. May be in' print, offset+offset+' an array.' print, offset+offset+'to -- what strings in from should be in' print, offset+offset+' translated to. May be an array.' print, offset+'Outputs:' print, offset+offset+'new -- Translated string. Array if oldstr is out' print, offset+offset+' an array.' print, offset+offset+'ned -- number of substitutions performed in out' print, offset+offset+' oldstr. Array if oldstr is an array.' print, offset+'Notes:' print, offset+offset+'- Any of old, from, and to can be arrays. ' print, offset+offset+'- from and to must have the same number of elements.' return, -1 ENDIF strn = InputString ; Check that From/To have same number of elements. RETURN if they don't. NFrom = n_elements(from) NTo = n_elements(to) IF (NFrom EQ 0) OR (NTo EQ 0) THEN return, strn IF NFrom NE NTo THEN BEGIN print,'Error: Number of elements in from/to unequal' return,-1 ENDIF ; Make sure there are no null strings in From. RETURN if there are. FromLen = strlen(From) IF (total(FromLen EQ 0) GT 0) THEN BEGIN print, 'Error: elements of From must have nonzero length.' return, -1 ENDIF NStrings = n_elements(strn) ned = lonarr(NStrings) tmpned = 0L ; Say strn='a#b#c', from='#' and to='@'. Then the approach here is to ; first split strn at all occurances of '#', then recombine the pieces ; with '@' inserted instead. Do this for all elements of strn, and ; all elements of from. FOR i = 0L, NStrings-1 DO BEGIN ned(i) = 0L st=strn(i) FOR j=0L, NFrom-1 DO BEGIN strn[i]=textoidl_str_replace(strn[i],from(j),to(j)) ;jpb patch using JD's routine ; SepStr = strsplit(strn(i), from(j)) ;jpb patch ; pos=strposmulti(strn(i),from(j),count) ; SepStr = strsplit(strn(i), from(j),/extract) ;jpb patch ; NSubs = n_elements(SepStr) - 1 ; IF count NE 0 THEN BEGIN ; stop ; SepStr = strsplit(strn(i), from(j),/extract) ; NSubs = n_elements(SepStr) - 1 ; strn(i) = SepStr(0) ; FOR k=1L, NSubs DO strn(i) = strn(i) + To(j) + SepStr(k) ; ned(i) = ned(i) + NSubs ; ENDIF ENDFOR ENDFOR return, strn END
2 1 \ No newline at end of file
  2 +; ;+ ; NAME: ; STRTRANS ; PURPOSE: ; Translate all occurences of one substring to another. ; CATEGORY: ; text/strings ; CALLING SEQUENCE: ; new = strtrans(oldstr,from,to,ned) ; INPUTS: ; oldstr -- string on which to operate. in ; May be an array. ; from -- substrings to be translated. May be in ; an array. ; to -- what strings in from should be in ; translated to. May be an array. ; KEYWORD PARAMETERS: ; /HELP -- Set this to print useful message and ; exit. ; OUTPUTS: ; new -- Translated string. Array if oldstr is out ; an array. ; ned -- number of substitutions performed in out ; oldstr. Array if oldstr is an array. ; COMMON BLOCKS: ; SIDE EFFECTS: ; NOTES: ; - Any of old, from, and to can be arrays. ; - from and to must have the same number of elements. ; EXAMPLE: ; inp='Many*bad!chars+in_here' ; from=['*','!','+','_'] ; to =[' ',' ',' ',' '] ; out = strtrans(inp,from,to,ned) ; Will produce out='Many bad chars in here', and set ned to 4. ; MODIFICATION HISTORY: ; $Id: strtrans.pro,v 1.4 2001/11/21 19:13:23 mcraig Exp $ ; $Log: strtrans.pro,v $ ; Revision 1.4 2001/11/21 19:13:23 mcraig ; Changed str_sep to strsplit. The former is now considered obsolete by RSI. ; ; Revision 1.3 1996/06/14 20:00:27 mcraig ; Updated Copyright info. ; ; Revision 1.2 1996/05/09 00:22:17 mcraig ; Sped up significantly by using str_sep to handle the translation. No longer ; relies on routines fromother user libraries. ; ; Revision 1.1 1996/01/31 18:47:37 mcraig ; Initial revision ; ; RELEASE: ; $Name: Rel_2_1 $ ; ; COPYRIGHT: ; Copyright (C) 1996 The Regents of the University of California, All ; Rights Reserved. Written by Matthew W. Craig. ; See the file COPYRIGHT for restrictions on distrubting this code. ; This code comes with absolutely NO warranty; see DISCLAIMER for details. ;- ; FUNCTION strtrans, InputString, from, to, ned, $ HELP=Help ; Bomb out to caller if error. On_error, 2 ; Offer help if we don't have at least InputString, from, and to, or ; if the user asks for it. IF (n_params() LT 3) OR keyword_set(help) THEN BEGIN offset = ' ' print, offset+'Translate all occurences of one substring to another.' print, offset+'new = strtrans(oldstr,from,to,ned)' print, offset+'Inputs:' print, offset+offset+'oldstr -- string on which to operate. in' print, offset+offset+' May be an array.' print, offset+offset+'from -- substrings to be translated. May be in' print, offset+offset+' an array.' print, offset+offset+'to -- what strings in from should be in' print, offset+offset+' translated to. May be an array.' print, offset+'Outputs:' print, offset+offset+'new -- Translated string. Array if oldstr is out' print, offset+offset+' an array.' print, offset+offset+'ned -- number of substitutions performed in out' print, offset+offset+' oldstr. Array if oldstr is an array.' print, offset+'Notes:' print, offset+offset+'- Any of old, from, and to can be arrays. ' print, offset+offset+'- from and to must have the same number of elements.' return, -1 ENDIF strn = InputString ; Check that From/To have same number of elements. RETURN if they don't. NFrom = n_elements(from) NTo = n_elements(to) IF (NFrom EQ 0) OR (NTo EQ 0) THEN return, strn IF NFrom NE NTo THEN BEGIN print,'Error: Number of elements in from/to unequal' return,-1 ENDIF ; Make sure there are no null strings in From. RETURN if there are. FromLen = strlen(From) IF (total(FromLen EQ 0) GT 0) THEN BEGIN print, 'Error: elements of From must have nonzero length.' return, -1 ENDIF NStrings = n_elements(strn) ned = lonarr(NStrings) tmpned = 0L ; Say strn='a#b#c', from='#' and to='@'. Then the approach here is to ; first split strn at all occurances of '#', then recombine the pieces ; with '@' inserted instead. Do this for all elements of strn, and ; all elements of from. FOR i = 0L, NStrings-1 DO BEGIN ned(i) = 0L st=strn(i) FOR j=0L, NFrom-1 DO BEGIN strn(i)=textoidl_str_replace(strn(i),from(j),to(j)) ;jpb patch using JD's routine ; SepStr = strsplit(strn(i), from(j)) ;jpb patch ; pos=strposmulti(strn(i),from(j),count) ; SepStr = strsplit(strn(i), from(j),/extract) ;jpb patch ; NSubs = n_elements(SepStr) - 1 ; IF count NE 0 THEN BEGIN ; stop ; SepStr = strsplit(strn(i), from(j),/extract) ; NSubs = n_elements(SepStr) - 1 ; strn(i) = SepStr(0) ; FOR k=1L, NSubs DO strn(i) = strn(i) + To(j) + SepStr(k) ; ned(i) = ned(i) + NSubs ; ENDIF ENDFOR ENDFOR return, strn END
3 3 \ No newline at end of file
... ...
src/idl_misc/textoidl.pro
1   -; ;+ ; NAME: ; TEXTOIDL ; PURPOSE: ; Convert a valid TeX string to a valid IDL string for plot labels. ; CATEGORY: ; text/strings ; CALLING SEQUENCE: ; new = textoidl(old) ; INPUTS: ; old -- TeX string to be converted. Will not be in ; modified. old may be a string array. ; KEYWORD PARAMETERS: ; FONT -- Set to 0 to use hardware font, -1 to use ; vector. Note that the only hardware font ; supported is PostScript. ; /TEX_SEQUENCES -- return the available TeX sequences ; /HELP -- print out info on use of the function ; and exit. ; OUTPUTS: ; new -- IDL string corresponding to old. out ; COMMON BLOCKS: ; SIDE EFFECTS: ; NOTES: ; - Use the procedure SHOWTEX to get a list of the available TeX ; control sequences. ; - The only hardware font for which translation is available is ; PostScript. ; - The only device for which hardware font' ; translation is available is PostScript.' ; - The FONT keyword overrides the font selected' ; by !p.font' ; EXAMPLE: ; out = TeXtoIDL('\Gamma^2 + 5N_{ed}') ; The string out may be used in XYOUTS or other IDL text ; display routines. It will be an uppercase Gamma, with an ; exponent of 2, then a plus sign, then an N with the subscript ; ed. ; MODIFICATION HISTORY: ; $Id: textoidl.pro,v 1.4 1996/06/14 20:00:27 mcraig Exp $ ; $Log: textoidl.pro,v $ ; Revision 1.4 1996/06/14 20:00:27 mcraig ; Updated Copyright info. ; ; Revision 1.3 1996/05/09 00:22:17 mcraig ; Added error handling, cleaned up documentation. ; ; Revision 1.2 1996/02/08 18:52:50 mcraig ; Added ability to use hardware fonts for PostScript device. ; ; Revision 1.1 1996/01/31 18:47:37 mcraig ; Initial revision ; ; RELEASE: ; $Name: Rel_2_1 $ ; ; COPYRIGHT: ; Copyright (C) 1996 The Regents of the University of California, All ; Rights Reserved. Written by Matthew W. Craig. ; See the file COPYRIGHT for restrictions on distrubting this code. ; This code comes with absolutely NO warranty; see DISCLAIMER for details. ;- ; FUNCTION Textoidl, InputString, $ FONT=fnt, $ HELP=hlp, $ TEX_SEQUENCES=tex_seq ; Return to caller if there is an error. On_error, 2 ; We begin by deciding on the font. PostScript = 0 means use vector. PostScript = 0 IF n_elements(fnt) EQ 0 THEN BEGIN ; get font from !p.font IF !p.font NE -1 THEN BEGIN ; User wants hardware font. PostScript=1 ENDIF ENDIF ELSE BEGIN ; get font from FONT keyword IF fnt NE -1 THEN PostScript = 1 ENDELSE ; Bomb out if user wants non-PostScript hardware font. IF (PostScript EQ 1) AND (!d.name NE 'PS') THEN BEGIN ; Device isn't postscript ; and user wants hardware ; font. Not good. print,'Warning: No translation for device: ',!d.name return,InputString ENDIF IF keyword_set (tex_seq) THEN BEGIN table=textable() return,table(0,*) ENDIF IF keyword_set(hlp) OR (n_params() EQ 0) THEN BEGIN print, ' Convert a TeX string to an IDL string' print, ' new = TeXtoIDL(old)' print, ' old = TeX string to translate. in' print, ' new = resulting IDL string. out' print, ' Keywords:' print, ' FONT set to -1 to translate for vector fonts ' print, ' (DEFAULT) . Set to 0 to translate for' print, ' hardware font.' print, ' /TEX_SEQUENCES -- return the available TeX sequences' print, ' /HELP print this message and exit.' print, ' NOTES: ' print, ' - Use SHOWTEX to obtain a list of the available' print, ' TeX control sequences.' print, ' - old may be a string array. If so, new is too.' print, ' - The only device for which hardware font' print, ' translation is available is PostScript.' print, ' - The FONT keyword overrides the font selected' print, ' by !p.font' return, -1 ENDIF ; PostScript has been set to 1 if PostScript fonts are desired. strn = InputString table = textable(POSTSCRIPT=PostScript) ; Greek sub/superscripts need to be protected by putting braces ; around them if they are unbraced. This will have the result the ; it will be difficult to use \ as a sub/superscript. Get over it. strn = strtrans(strn, '^'+table(0, *), '^{'+table(0, *)+'}') strn = strtrans(strn, '_'+table(0, *), '_{'+table(0, *)+'}') ; First we translate Greek letters and the like. This makes guessing ; alignment of sub/superscripts easier, as all special characters will then ; be one character long. strn = strtrans(strn, table(0, *), table(1, *)) FOR i = 0L, n_elements(strn)-1 DO $ strn[i] = translate_sub_super(strn[i]) ; Take care of sub/superscripts return,strn END
2 1 \ No newline at end of file
  2 +; ;+ ; NAME: ; TEXTOIDL ; PURPOSE: ; Convert a valid TeX string to a valid IDL string for plot labels. ; CATEGORY: ; text/strings ; CALLING SEQUENCE: ; new = textoidl(old) ; INPUTS: ; old -- TeX string to be converted. Will not be in ; modified. old may be a string array. ; KEYWORD PARAMETERS: ; FONT -- Set to 0 to use hardware font, -1 to use ; vector. Note that the only hardware font ; supported is PostScript. ; /TEX_SEQUENCES -- return the available TeX sequences ; /HELP -- print out info on use of the function ; and exit. ; OUTPUTS: ; new -- IDL string corresponding to old. out ; COMMON BLOCKS: ; SIDE EFFECTS: ; NOTES: ; - Use the procedure SHOWTEX to get a list of the available TeX ; control sequences. ; - The only hardware font for which translation is available is ; PostScript. ; - The only device for which hardware font' ; translation is available is PostScript.' ; - The FONT keyword overrides the font selected' ; by !p.font' ; EXAMPLE: ; out = TeXtoIDL('\Gamma^2 + 5N_{ed}') ; The string out may be used in XYOUTS or other IDL text ; display routines. It will be an uppercase Gamma, with an ; exponent of 2, then a plus sign, then an N with the subscript ; ed. ; MODIFICATION HISTORY: ; $Id: textoidl.pro,v 1.4 1996/06/14 20:00:27 mcraig Exp $ ; $Log: textoidl.pro,v $ ; Revision 1.4 1996/06/14 20:00:27 mcraig ; Updated Copyright info. ; ; Revision 1.3 1996/05/09 00:22:17 mcraig ; Added error handling, cleaned up documentation. ; ; Revision 1.2 1996/02/08 18:52:50 mcraig ; Added ability to use hardware fonts for PostScript device. ; ; Revision 1.1 1996/01/31 18:47:37 mcraig ; Initial revision ; ; RELEASE: ; $Name: Rel_2_1 $ ; ; COPYRIGHT: ; Copyright (C) 1996 The Regents of the University of California, All ; Rights Reserved. Written by Matthew W. Craig. ; See the file COPYRIGHT for restrictions on distrubting this code. ; This code comes with absolutely NO warranty; see DISCLAIMER for details. ;- ; FUNCTION Textoidl, InputString, $ FONT=fnt, $ HELP=hlp, $ TEX_SEQUENCES=tex_seq ; Return to caller if there is an error. On_error, 2 ; We begin by deciding on the font. PostScript = 0 means use vector. PostScript = 0 IF n_elements(fnt) EQ 0 THEN BEGIN ; get font from !p.font IF !p.font NE -1 THEN BEGIN ; User wants hardware font. PostScript=1 ENDIF ENDIF ELSE BEGIN ; get font from FONT keyword IF fnt NE -1 THEN PostScript = 1 ENDELSE ; Bomb out if user wants non-PostScript hardware font. IF (PostScript EQ 1) AND (!d.name NE 'PS') THEN BEGIN ; Device isn't postscript ; and user wants hardware ; font. Not good. print,'Warning: No translation for device: ',!d.name return,InputString ENDIF IF keyword_set (tex_seq) THEN BEGIN table=textable() return,table(0,*) ENDIF IF keyword_set(hlp) OR (n_params() EQ 0) THEN BEGIN print, ' Convert a TeX string to an IDL string' print, ' new = TeXtoIDL(old)' print, ' old = TeX string to translate. in' print, ' new = resulting IDL string. out' print, ' Keywords:' print, ' FONT set to -1 to translate for vector fonts ' print, ' (DEFAULT) . Set to 0 to translate for' print, ' hardware font.' print, ' /TEX_SEQUENCES -- return the available TeX sequences' print, ' /HELP print this message and exit.' print, ' NOTES: ' print, ' - Use SHOWTEX to obtain a list of the available' print, ' TeX control sequences.' print, ' - old may be a string array. If so, new is too.' print, ' - The only device for which hardware font' print, ' translation is available is PostScript.' print, ' - The FONT keyword overrides the font selected' print, ' by !p.font' return, -1 ENDIF ; PostScript has been set to 1 if PostScript fonts are desired. strn = InputString table = textable(POSTSCRIPT=PostScript) ; Greek sub/superscripts need to be protected by putting braces ; around them if they are unbraced. This will have the result the ; it will be difficult to use \ as a sub/superscript. Get over it. strn = strtrans(strn, '^'+table(0, *), '^{'+table(0, *)+'}') strn = strtrans(strn, '_'+table(0, *), '_{'+table(0, *)+'}') ; First we translate Greek letters and the like. This makes guessing ; alignment of sub/superscripts easier, as all special characters will then ; be one character long. strn = strtrans(strn, table(0, *), table(1, *)) FOR i = 0L, n_elements(strn)-1 DO $ strn(i) = translate_sub_super(strn(i)) ; Take care of sub/superscripts return,strn END
3 3 \ No newline at end of file
... ...