;+
;GRAFIT.PRO
; IDL program to
; 1. read in a list of line locations
; 2. figure out best initial parameters for each line
; using spectrum (YCT(XWV)) already read in.
; 3. fit each line to data within the spectrum
; 4. write out the results
;
;USAGE
; read in spectrum and store in variables YCT and XWV
; LWIDTH0=0.05 & LWIDTH_MAX=0.1 & PSROOT='capella'
; .run grafit
;
;expected to be of use in Chandra HETG/LETG analyses
;
;SUBROUTINES
; wc
; setcolor
; nary2dec
; num2str
; fit_levmar
; x3model
; mk_model
; mk_gauss
; mk_lorentz
; adjustie
; levmarq
; lmcoeff
;
;vinay kashyap (Aug99)
;-
; plotting stuff
window,0 & window,1
loadct,3
setcolor,'#ff0000',2
setcolor,'#ffff00',3
; initialize those fit parameters as necessary
if not keyword_set(LWIDTH0) then LWIDTH0=0.01 ;[Ang]
if not keyword_set(LWIDTH_max) then LWIDTH_max=0.05 ;[Ang]
if not keyword_set(functyp) then functyp='lorentz'
if not keyword_set(psroot) then psroot='PLOT'
; is spectrum available?
nxwv=n_elements(xwv) & nyct=n_elements(yct) & ok='ok'
if nxwv eq 0 then ok='XWV not defined' else $
if nyct eq 0 then ok='YCT(XWV) not defined' else $
if nxwv ne nyct then ok='YCT(XWV) and XWV incompatible' else $
if nxwv lt 2 then ok='too few elements to bother!'
if ok ne 'ok' then message,ok else plot,xwv,yct,psym=10,/xs,/ys,$
xtitle='Wavelength [Ang]',ytitle='Counts [ct]'
wset,0
; initialize input line list filename..
if not keyword_set(linefil) then linefil='linelist.txt'
; expect the input file to have the following format:
; wavelength [Ang] (f8.3)
; Element Ion (a10)
; e- configuration (a20)
; level designation (a20)
; counts in line (f8.0)
; of which only the first 2 columns are of relevance
;
;example print statement to make the linelist
;print,format='(f8.3,2x,a10,2x,a50)',wave,z_ion,stuff
; .. and read in the line list
nlin=wc(linefil) & lwvl=fltarr(nlin) & lelem=strarr(nlin)
openr,ulin,linefil,/get_lun
klin=0L
for i=0L,nlin-1L do begin
cc='' & readf,ulin,cc & c1=strmid(cc,0,1)
if c1 ne '#' and c1 ne ';' then begin
aa=0. & bb='' & reads,cc,aa,bb,format='(f8.3,2x,a10)'
lwvl(klin)=aa & lelem(klin)=bb
klin=klin+1L
endif
endfor
if klin lt nlin then begin
lwvl=lwvl(0:klin-1L) & lelem=lelem(0:klin-1L) & nlin=klin
endif
close,ulin & free_lun,ulin
; initialize parameter arrays
lpos=lwvl & lwdt=0.*lwvl+LWIDTH0(0) & lhgt=0.*lwvl+1. ;to hold best-fit values
lpos_e=0.*lpos & lwdt_e=0.*lwdt & lhgt_e=0.*lhgt ;errors
lquality=strarr(n_elements(lpos)) ;quality flag
oldlpos=lpos
xline=intarr(n_elements(lpos)) ;dealt with line(1) or no(0)?
; and array to hold chisq
lchi=0.*lwvl & lrchi=lchi
; run specific initializations
xmin=min(XWV,max=xmax) & nycte=n_elements(YCT_E)
YCT_E=sqrt(abs(YCT)+0.75)+1. ;assume poisson errors
dXWV=XWV(1:*)-XWV & delX=median(dXWV)
if n_elements(dumb) eq 0 then dumb=1 ;see FIT_LEVMAR
; remove lines
bkgval=0.*YCT & bkgerr=bkgval
;bg=linerem(XWV,YCT,sig=YCT_E,nsigma=1,cell=[1,1,1,0,0,0,1,1,1],$
;bg=linerem(XWV,YCT,sig=YCT_E,nsigma=1,cell=[-1.,-1.,0,0,0,0,-1.,-1.],$
; bkgval=bkgval,bkgerr=bkgerr,quiet=0)
; step through and fit
ilin = 0L & dlin=1L
while ilin lt nlin do begin ;{step through linelist
loopbegin: i = ilin
lxrng=lpos(i)+1*LWIDTH0*[-1.,1.] ;range to check for nearby lines
sxrng=lpos(i)+3*LWIDTH0*[-1.,1.] ;range in which to fit the line
pxrng=lpos(i)+7*LWIDTH0*[-1.,1.] ;range in which to display plots
sxrng=((sxrng>xmin) ',cidx
idx=ol([long(strtrim(cidx,2))])
aa=[lpos(idx),LWIDTH0,lhgt(idx)] & ool=ol & ol=[idx] & mol=1L
endelse ;MOL)
ihgt=lindgen(mol)*3+2
; renormalize to get approximate heights
; this has to be more intelligent in the case of multiple lines
call_procedure,'x3model',xx,aa,ymod,/norm,type=functyp
;tmod=total((0.5*(ymod(1:*)+ymod))*dx)
;renorm=total(0.5*(yy(1:*)+yy)*dx)/tmod
tmod=total(ymod)
renorm=total(yy)/tmod
aa(ihgt)=aa(ihgt)*renorm
erra=0*aa
plot,XWV,YCT,/xs,psym=10,xr=pxrng
oplot,xx,ymod*renorm+bkgval(ow),col=2
if mol gt 1 then goto,nextline
; set constraints
ties=strarr(3L*mol)
for j=0L,mol-1L do begin
k=3L*j+0L
ap='A'+strtrim(k,2) & aw='A'+strtrim(k+1,2) & ah='A'+strtrim(k+2,2)
ties(k)=ap+'=(('+ap+' < ('+strtrim(lpos(ol(j))+2*LWIDTH0,2)+')) > ('+$
strtrim(lpos(ol(j))-2*LWIDTH0,2)+'))'
ties(k+1)=aw+'=(('+aw+' < ('+strtrim(LWIDTH_max,2)+')) > ('+$
strtrim(delX,2)+'))'
ties(k+2)=ah+'=('+ah+' > 0)'
endfor
; fit
fit_levmar,xx,yy,aa,erra=erra,chisq=chisq,funcs='x3model',$
sig=yy_e,/norm,type=functyp,ties=ties,dumb=dumb,$
jumpup=jumpup,jumpdn=jumpdn
lchi(i)=chisq & if mow gt 3 then lrchi(i)=chisq/(mow-3.)
; plot
call_procedure,'x3model',xx,aa,ymod,/norm,type=functyp
plot,XWV,YCT,/xs,psym=10,xr=pxrng,$
title=lelem(i),xtitle='[Ang]',ytitle='[counts]'
for j=0L,mow-1L do oplot,XWV(ow(j))*[1,1],YCT(ow(j))+YCT_E(ow(j))*[-1,1]
xyouts,pxrng(0)+delX,max(YCT(ow))*0.95,$
'!4v!3!u2!dr!n='+strtrim(lrchi(i),2)+$
'; !3C='+strtrim(total(ymod),2)
oplot,xx,ymod+bkgval(ow),col=3,psym=-1
oplot,xx,bkgval(ow),col=2
nextline:
; save the fit parameters
if mol eq 1 then begin ;(one line to worry about
lpos(i)=aa(0) & lpos_e(i)=erra(0)
lwdt(i)=aa(1) & lwdt_e(i)=erra(1)
lhgt(i)=aa(2) & lhgt_e(i)=erra(2)
endif else begin ;)(more than one line
tmp=min(abs(lpos(ol)-lpos(i)),idx)
lpos(i)=aa(3*idx+0) & lpos_e(i)=erra(3*idx+0)
lwdt(i)=aa(3*idx+1) & lwdt_e(i)=erra(3*idx+1)
lhgt(i)=aa(3*idx+2) & lhgt_e(i)=erra(3*idx+2)
;lpos(i)=lpos(i)
;lwdt(i)=LWIDTH0
;lhgt(i)=lhgt(i)*renorm
message,'cannot handle this case yet!',/info
endelse ;MOL)
LWIDTH0=lwdt(i)
; add parameters and errors to plot
xyouts,pxrng(0)+delX,max(YCT(ow))*0.8,$
'POS: '+strtrim(lpos(i),2)+' +- '+strtrim(lpos_e(i),2)
xyouts,pxrng(0)+delX,max(YCT(ow))*0.7,$
'WDT: '+strtrim(lwdt(i),2)+' +- '+strtrim(lwdt_e(i),2)
xyouts,pxrng(0)+delX,max(YCT(ow))*0.6,$
'HGT: '+strtrim(lhgt(i),2)+' +- '+strtrim(lhgt_e(i),2)
endif ;MOW)
ilin0=ilin
if not keyword_set(trust) then begin
print,'hit any key to continue, t/T for thinner/thicker line,'
c='p for previous, q/x to stop, r to repeat, e for errors'
print,c & c=get_kbrd(1)
endif else c='ok'
if c eq 'p' or c eq 'P' then begin
print,'current line is: '+strtrim(ilin,2),lwvl(ilin),' ',lelem(ilin)
ilin = ilin - dlin
xline(ilin)=0
print,'new line is: '+strtrim(ilin,2),lwvl(ilin),' ',lelem(ilin)
goto, loopbegin
endif
if c eq 'q' or c eq 'Q' then c='x'
if c eq 'x' or c eq 'X' then stop,'HALTING. type .CON to continue'
if c eq 't' or c eq 'T' then begin
if c eq 't' then LWIDTH0=LWIDTH0/2. else LWIDTH0=LWIDTH0*1.1
c='x'
endif
if c eq 'e' then begin ;(compute errors
wset,1
erors,xx,yy,aa,erraa,ysig=yy_e,dchi=2.7,verbose=10,$
funcs='x3model',/norm,type=functyp,ties=ties,/dumb,$
jumpup=jumpup,jumpdn=jumpdn
print,'OLD:',erra & erra=erraa & print,'NEW:',erra
wset,0
if mol eq 1 then begin ;(one line to worry about
lpos_e(i)=erra(0)
lwdt_e(i)=erra(1)
lhgt_e(i)=erra(2)
endif else begin ;)(more than one line
tmp=min(abs(lpos(ol)-lpos(i)),idx)
lpos_e(i)=erra(3*idx+0)
lwdt_e(i)=erra(3*idx+1)
lhgt_e(i)=erra(3*idx+2)
message,'cannot handle this case yet!',/info
endelse ;MOL)
endif ;C='E')
if c ne 'r' and c ne 'R' and c ne 'x' and c ne 'X' then ilin=ilin+dlin
if ilin gt ilin0 and mow gt 0 then begin ;(all done, final convulsions
cqual='' & read,prompt='type in a quality comment> ',cqual
lquality(i)=strtrim(cqual,2)
;
xline(ool)=1
;
if keyword_set(psroot) then begin
psfil=strtrim(psroot,2)+'_'+$
num2str(oldlpos(i),len=strlen(strtrim(oldlpos(i),2)))+'.ps'
gifil=strtrim(psroot,2)+'_'+$
num2str(oldlpos(i),len=strlen(strtrim(oldlpos(i),2)))+'.gif'
message,'Writing figure to postscript file: '+psfil,/info
message,'Writing figure to GIF file: '+gifil,/info
tvlct,r,g,b,/get
set_plot,'ps' & device,file=psfil
endif
plot,XWV,YCT,/xs,psym=10,xr=pxrng,thick=2,$
title=lelem(i),xtitle='Wavelength [Ang]',ytitle='counts/pix'
for j=0L,mow-1L do oplot,XWV(ow(j))*[1,1],YCT(ow(j))+YCT_E(ow(j))*[-1,1]
xyouts,pxrng(0)+delX,max(YCT(ow))*0.95,$
'!4v!3!u2!dr!n='+strtrim(lrchi(i),2)+$
'; !3C='+strtrim(total(ymod),2)
oplot,xx,ymod+bkgval(ow),col=3,psym=10 & oplot,xx,bkgval(ow),col=3
; add parameters and errors to plot
xyouts,pxrng(0)+delX,max(YCT(ow))*0.8,$
'POS: '+strtrim(lpos(i),2)+' +- '+strtrim(lpos_e(i),2)
xyouts,pxrng(0)+delX,max(YCT(ow))*0.7,$
'WDT: '+strtrim(lwdt(i),2)+' +- '+strtrim(lwdt_e(i),2)
xyouts,pxrng(0)+delX,max(YCT(ow))*0.6,$
'HGT: '+strtrim(lhgt(i),2)+' +- '+strtrim(lhgt_e(i),2)
if keyword_set(psroot) then begin
device,/close & set_plot,'x'
write_gif,gifil,tvrd(),r,g,b
endif
endif ;ILIN>ILIN0 && MOW>0)
endwhile ;ILIN < NLIN}
; summarize
print,'OUTPUTS in:-' & help,lpos,lwdt,lhgt,lpos_e,lwdt_e,lhgt_e,lchi,lrchi,lelem
print,string("7b)
print,'Fit to spectrum:-' & help,YCT,XWV,YCT_E,functyp,linefil
print,string("7b)
print,'Other variables of interest:-' & help,LWIDTH0,LWIDTH_max,psroot,outfil
if keyword_set(outfil) then begin
message,'saving to file: '+outfil,/info
save,file=outfil
endif
end