;+ ;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