function potem_tool,idstr,flux,logT=logT,abund=abund,ldir=ldir,dwvl=dwvl,$ okmult=okmult,kettle=kettle,outid=outid,multid=multid,$ wdth=wdth,verbose=verbose, _extra=e ;+ ;function potem_tool ; return emission measures EM(LOGT,WVL) for all lines that have been ID'd ; (but see keyword OKMULT) ; ; for each temperature, assume a delta-function emission measure, ; compute line fluxes seen through some instrument, account for ; interstellar absorption, and scale to match the observed flux. ; ; in case of multiple IDs for a single observed line, the emissivities ; of the IDs are added together, and assumed for all practical purposes ; to be the strongest line modified by the other IDs. ; in case of IDs spanning different elements, the emissivities are ; added as before, but weighted with their relative abundances. ; ;syntax ; EM=potem_tool(idstr,flux,logT=logT,abund=abund,ldir=ldir,$ ; dwvl=dwvl,/okmult,/kettle,outid=outid,wdth=wdth, pres=pres,$ ; logP=logP,n_e=n_e, chifil=chifil,chidir=chidir,eqfile=eqfile,$ ; NH=NH,/noph,defEM=defEM, thresh=thresh,/temp,/ikev,effar=effar,$ ; wvlar=wvlar,fh2=fh2,He1=He1,HeII=HeII,/fano, level=level,$ ; verbose=verbose) ; ;parameters ; idstr [INPUT; required] the ID structure that comes out of LINEID ; flux [INPUT] observed fluxes ; * if not given, taken from IDSTR.(*).FLUX ; (if zero, forcibly set to 1 [(ph|erg)/s/cm^2]) ; * size is forced to match IDSTR.WVL ; if <, filled out with 1s ; if >, extra elements are ignored ; ;keywords ; logT [INPUT] temperatures at which to compute the emission measures ; * default is findgen(81)*0.05+4. ; abund [INPUT] abundances ; * default is to use Anders & Grevesse ; ldir [INPUT] string array containing line database directory ; names, one for each ID. ; * if given, will NOT use the embedded emissivities in ; IDSTR.EMIS (default is to use them) ; * if size < N(ALLMATCHES), the last element is replicated ; as often as necessary ; * to selectively use IDSTR.(#).EMIS, set to '0' within a ; string array (e.g., ['$CHIANTI','$SPEX','0','0','$SCAR'] ; * if set to a number, assumes "$SCAR" ; dwvl [INPUT; default=5e-3] search the line database for the ; wavelength of interest with this assumed roundoff error ; okmult [INPUT] if set, then multiple IDs (if any) are >not< ; collapsed, and the output will be of the form EM(LOGT,ALLWVL) ; * automatically set if size of FLUX matches the total number ; of matches ; kettle [INPUT] if set, does NOT do Pottasch corrections ; outid [OUTPUT] if defined on input, returns the IDs with new ; emissivities in an ID structure ; * multiple IDs are "collapsed" unless OKMULT is set ; multid [OUTPUT] number of IDs for each observed line (this is ; of use in, e.g., PLOTEM) ; wdth [OUTPUT] the full width in logT of the emissivity curve, ; as calculated by POTTASCH() ; verbose [INPUT] controls chatter ; _extra [INPUT ONLY] use to pass defined keywords to subroutines: ; RD_LINE: PRES,LOGP,N_E,VERBOSE ; FOLD_IONEQ: CHIFIL,CHIDIR,EQFILE,VERBOSE ; FLUX_TO_EM: NH,NOPH,DEFEM,THRESH ; LINEFLX: TEMP,IKEV,EFFAR,WVLAR ; ISMTAU: FH2,HE1,HEII,FANO ; POTTASCH: LEVEL ; ;subroutines ; INICON ; RD_LIST ; RD_LINE ; FOLD_IONEQ ; READ_IONEQ ; RD_IONEQ (CHIANTI routine) ; FLUX_TO_EM ; LINEFLX ; ISMTAU ; POTTASCH ; ;history ; vinay kashyap (Nov98; "concatenated" id_to_emis and flux_to_em) ; changed default behavior of FLUX; added keyword MULTID; changed ; OUTID.().Z and OUTID.().ION to floats in case multiple IDs have ; been collapsed to one emissivity (VK; Dec98) ; added field FLUXERR to output IDSTR (VK; Mar99) ; changed call to INITSTUFF to INICON (VK; 99May) ; no need to read in ion balance info in POTTASCH again (VK; JanMMI) ; added keyword WDTH to carry the emissivity width info outside ; (VK; SepMMVII) ;- ; usage nid=n_tags(idstr) if nid eq 0 then begin print,'Usage: EM=potem_tool(idstr,flux,logT=logT,abund=abund,ldir=ldir,$' print,' dwvl=dwvl,/okmult,/kettle,outid=outid,wdth=wdth, print,' RD_LINE:pres,logp,n_e; FOLD_IONEQ:chifil,chidir,eqfile;' print,' FLUX_TO_EM:NH,noph,defEM,thresh; LINEFLX:temp,ikev,effar,wvlar;' print,' ISMTAU:fh2,He1,HeII,fano; POTTASCH:level,' print,' verbose=verbose) print,' constructs emission measure predictions for each observed line' return,[-1L] endif ; trivial errors check nf=n_elements(flux) & nT=n_elements(logT) tid=tag_names(idstr) & owvl=idstr.(0) & nwvl=n_elements(owvl) ok='ok' if tid(0) ne 'WVL' then ok='input structure of unknown form' else $ if nwvl ne nid-1 then ok='ID structure not in standard format' else $ if tid(1) eq 'WVL_COMMENT' then ok='ID structure contains no data' if ok ne 'ok' then begin em=[-1.D] & if nT gt 0 then em=dblarr(nT)-1 message,ok,/info & return,em endif ; how many matched wavelengths, really? multid=intarr(nwvl) & mwvl=0L for i=0,nwvl-1 do multid(i)=n_elements(IDSTR.(i+1).WVL) mwvl=long(total(multid)) ; are the fluxes given? fx=fltarr(nwvl) for i=0,nwvl-1 do begin ;{default is to use fluxes from IDSTR tmpid=idstr.(i+1) & fx(i)=total(tmpid.FLUX) if fx(i) eq 0 then fx(i)=1. ;if zero, set to 1 endfor ;I=0,NWVL-1} if nf gt 0 and nf lt nwvl then fx(0:nf-1)=flux if nf ge nwvl then begin if nf eq mwvl then begin okmult=1 k=0L for i=0,nwvl-1 do begin tmpid=idstr.(i+1) & mw=multid(i) fx(i)=total(flux(k:k+mw-1L)) k=k+mw endfor endif else fx=flux(0:nwvl-1) endif ; keywords if nT eq 0 then begin ;define temperature grid nT=81L & logT=findgen(nT)*0.05+4. endif ; if n_elements(abund) lt 30 then abund=getabund('anders & grevesse') ; if not keyword_set(dwvl) then dwvl=5e-3 ; ; define line database directories ldbdir=strarr(mwvl)+'0' & ndir=n_elements(ldir) if ndir ne 0 then begin szd=size(ldir) & nszd=n_elements(szd) & ndir=szd(nszd-1) if szd(nszd-2) ne 0 then ldbdir(*)='$SCAR' ;e.g., if /LDIR is set if szd(nszd-2) eq 7 then begin kdir=0L for i=0,nwvl-1 do begin mw=n_elements(idstr.(i+1).wvl) if ndir eq nwvl then ldbdir(kdir:kdir+mw-1)=ldir(i) else $ ldbdir(kdir)=ldir([kdir]) kdir=kdir+mw endfor endif endif ; v=0 & if keyword_set(verbose) then v=long(verbose(0))>1 ; initialize atom=1 & rom=1 & inicon,atom=atom,roman=rom & atom=['X',atom] & rom=['',rom] ;atomic symbols and ionization states, allow for "Unknown" sep=' ' ;separator, here a if arg_present(outid) then outid=create_struct('WVL',owvl) ; define the output if keyword_set(okmult) then em=dblarr(nT,mwvl) else em=dblarr(nT,nwvl) ; now step through the IDs and compute the emissivities ;basically, for each observed wavelength, get the IDs, and get the ;line emissivity for each line, then fold in ion balance, then ;interpolate to the required grid, then call FLUX->EM to get the emission ;measures, then apply the pottasch correction. kwvl=0L for i=0,nwvl-1 do begin idi=idstr.(i+1) ww=idi.WVL & zz=idi.Z & jon=idi.ION & labl=idi.LABL & mw=n_elements(ww) fjmx=dblarr(mw) if v gt 0 then print,'ID '+strtrim(i+1,2)+':' if v gt 5 then junk=cat_id(idstr,pick=[i]) if zz(0) eq 0 or jon(0) eq 0 or labl(0) eq 'Unknown' then begin ; ID is unknown -- nothing to calculate! em(*,kwvl)=dblarr(nT)-1. if keyword_set(outid) then outid=create_struct(outid,'ID'+strtrim(i,2),idi) endif else begin ;(compute EMs if keyword_set(okmult) then emis=dblarr(nT,mw) else emis=dblarr(nT) for j=0,mw-1 do begin ;{for each match ; if ldbdir(kwvl+j) eq '0' then begin ;(use IDSTR.(#).EMIS nam_idi=tag_names(idi) oi=where(nam_idi eq 'EMIS',moi) if moi eq 0 then ldbdir(kwvl+j)='$SCAR' else begin ff=idi.EMIS & tlog=idi.LOGT & ff=reform(ff(*,j)) endelse endif ;use IDSTR.(#).EMIS) if ldbdir(kwvl+j) ne '0' then begin ;(go read databse lnlst=atom(zz(j))+rom(jon(j))+sep+strtrim(ww(j),2)+' ? '+$ strtrim(dwvl,2)+sep+ldbdir(kwvl+j) lstr=rd_list(lnlst,sep=sep,/incieq, _extra=e) ff=lstr.LINE_INT & tlog=lstr.LOGT if n_elements(lstr.WVL) gt 1 then begin ; too many? collapse them ff=0*logT for k=0,n_elements(lstr.WVL)-1 do ff=ff+reform((lstr.LINE_INT(*,k))) endif endif ;read databse) ; if ff(0) le -1 then begin ; if line is missing, no help for it tlog=logT & ff=0*logT endif ; interpolate emissivities from TLOG to LOGT fmin=min(ff,max=fmax) & fjmx(j)=fmax tmp=((interpol(ff,tlog,logT)>(fmin))<(fmax)) if keyword_set(okmult) then emis(*,j)=tmp(*) else $ emis(*)=emis(*)+abund(zz(j)-1)*tmp(*) endfor ;J=0,MW-1} fjmax=max(fjmx,jmx) & tfjmx=total(fjmx) if keyword_set(okmult) then begin emis=emis;/abund(zz(jmx)-1) if tfjmx gt 0 then fxj=fx(i)*fjmx/total(fjmx) else $ fxj=fltarr(mw)+fx(i)/mw endif else begin emis=emis/abund(zz(jmx)-1) fxj=fx(i) if tfjmx gt 0 then ww=total(fjmx*ww)/tfjmx else ww=total(ww)/mw if mw gt 1 then zz=[float(zz(jmx))] else zz=[zz(jmx)] if mw gt 1 then jon=[float(jon(jmx))] else jon=[jon(jmx)] endelse tmp=flux_to_em(emis,flux=fxj,logT=logT,wvl=ww,Z=zz, abund=abund, _extra=e) if keyword_set(okmult) then em(*,lindgen(mw)+kwvl)=tmp else $ em(*,i)=tmp if keyword_set(kettle) then pot=0*zz+1. else $ pot=pottasch(emis,logT,wdth=wdth, _extra=e) ;pot=pottasch(emis,logT,Z=zz,ion=jon, _extra=e) if v ge 10 then print,'Pottasch correction: ',pot npot=n_elements(pot) for k=0,npot-1 do begin if keyword_set(okmult) then begin oo=where(em(*,kwvl+k) ge 0,moo) if moo gt 0 and pot(k) gt 0 then em(oo,kwvl+k)=em(oo,kwvl+k)/pot(k) endif else begin oo=where(em(*,i) ge 0,moo) if moo gt 0 and pot(k) gt 0 then em(oo,i)=em(oo,i)/pot(k) endelse endfor endelse ;ID known) if arg_present(outid) then begin idwvl=create_struct('WVL',ww,'Z',zz,'ION',jon,'LABL',labl,'FLUX',fxj,$ 'FLUXERR',0*fxj,'LOGT',logt,'EMIS',emis) outid=create_struct(outid,'ID'+strtrim(i+1,2),idwvl) endif kwvl=kwvl+mw endfor return,em end