;+ ; NAME: ; qgemspec.pro ; ; PURPOSE: ; Fully-automated quick reduction of GMOS spectra ; ; CALLING SEQUENCE: ; qgemspec, files ; ; INPUTS: ; files - Text file or array containing list of all arcs, flats, and science exposures. ; ; OPTIONAL INPUTS: ; nocrreject - keyword to skip cosmic ray rejection ; ysearch - array of [min, max] y-coordinates where the afterglow may be. ; ; COMMENTS: ; Automatically identifies the flats and arcs, matches files with like configurations, ; finds the source, extracts the spectrum, gets a wavelength solution. ; Writes out several files: ; [obj]_[config]#.dat : ascii files (four columns: wave, flux, skyflux, pixel) ; specplots.ps : plots ; specplotsnorm.ps : plots normalized to continuum (approximate) ; detectedlines.dat : list of possible spectral lines ; arcplots_c?.fits : arc solution plots (quick sol at left, fine sol at right) ; [filename]z.fits : central part of science exposure with cosmic rays removed ; outflat_c?.fits : normalized flatfield in each configuration ; ; Has been tested only with the R400, B400, and R831 gratings. Failures ; with the wavelength solution for different gratings are plausible. ; Gemini-South only (will not properly process GMOS-N). ; Requires the GSFC IDL libraries. ; ; HISTORY: ; v0.0 2009-11-06 (DAP) - beta release to group ; ; ; Planned features: ; Options to tweak CR rejection ; Checks on tracing (to try to confidently contract the aperture) ; Sky lines (variance spectrum) on plots ; Thoroughput normalization ; Improved normalization and absorption line detection ; Absorption line / redshift identification ; ;- ;------------------------------------------------------------------------------ function countlines, infile openr, 1, infile iline='' nlines = 0l while not eof(1) do begin readf, 1, iline nlines = nlines + 1 endwhile close, 1 return, nlines end function grabcolumn, infile, colnum, extstr=extstr, str=str, skiplines=skiplines nlines = countlines(infile) str = keyword_set(str) if str then arr = strarr(nlines) else arr = dblarr(nlines) if n_elements(skiplines) eq 0 then skiplines = 0 iline = '' ndat = 0 openr, 1, infile for i = 0, nlines-1 do begin readf, 1, iline if i lt skiplines then continue if strmid(iline, 0, 1) eq '#' then continue if n_elements(extstr) eq 0 then $ idata = strtrim(strsplit(iline, /extract),2) $ else $ idata = strtrim(strsplit(iline, extsr, /extract),2) if n_elements(idata) le colnum then continue if str then arr[ndat] = idata[colnum] else arr[ndat] = double(idata[colnum]) ndat = ndat + 1 endfor close, 1 return, arr[0:ndat-1] end function clip, strin, maxlen str = string(strin) if n_params() eq 1 then return, strtrim(str,2) str = strmid(strtrim(str,2),0,maxlen) curlen = strlen(str) if curlen lt maxlen then $ for i = 0, (maxlen-curlen-1) do $ str = str + ' ' return, str end function unique, arr uniquearr = arr n = n_elements(arr) nunique = 0 for i = 0, n-1 do begin known = 0 for j = 0, nunique - 1 do begin if arr[i] eq uniquearr[j] then known = 1 endfor if known eq 0 then begin uniquearr[nunique] = arr[i] nunique = nunique + 1 endif endfor uniquearr = uniquearr[0:nunique-1] return, uniquearr end function loadandmerge, fitsfile, h ; It's easier to do operations once instead of three times, so stick file mosaics together into one image. if n_elements(fitsfile) eq 0 then begin print, 'ERROR: No file specified!' return, 0 endif dummy = mrdfits(fitsfile, 0, h, /silent) ; just to get the header arr1 = mrdfits(fitsfile, 1, h1, /silent, /unsigned) arr2 = mrdfits(fitsfile, 2, h2, /silent, /unsigned) arr3 = mrdfits(fitsfile, 3, h3, /silent, /unsigned) ymax = 2304 a1xmax = 1024-1 ; The array actually goes up to 1055. But only 1025 is visible in the file... a2xmin = 1024 a2xmax = 1024*2-1 a3xmin = 1024*2 arr = fltarr(1024*3-33, ymax) arr[0:a1xmax,*] = float(arr1[0:a1xmax,*]) arr[a2xmin:a2xmax,*] = float(arr2[0:a1xmax,*]) arr[a3xmin:*,*] = float(arr3[33:a1xmax,*]) return, arr end function quickzap, imdata nx = (size(imdata)) [1] ny = (size(imdata)) [2] gain = 1.0 ; 2.2 if not pre-corrected rdnoise = 4 skyimage = fltarr(nx,ny) for x = 0, nx-1 do begin ; could break this down in y too skyimage[x,*] = median(imdata[x,*], /even) endfor skysubimage = imdata - skyimage sourceimage = fltarr(nx, ny) for x = 0, nx-1, 3 do begin for y = 0, ny-1 do begin val = median(skysubimage[x-7>1:x+7 2 ; sensitive to clusters up to a little less than 1/16 of the data set if nd lt 12 then g = 1 minmean = total(d) imean = nd / 2 for i = 0, nd-1 do begin r = [i-g>0,i+g1:x+250:normfitx[b]+100< starti = i endif else begin if lineregions[i] ne lineregions[i-1]+1 then starti = i endelse endthelinehere = 0 if i eq (n_elements(lineregions)-1) then begin endthelinehere = 1 endif else begin if lineregions[i] ne lineregions[i+1]-1 then endthelinehere = 1 endelse if endthelinehere eq 1 then begin endi = i thiswavregion = starti + intarr(endi-starti+1) linecenter = lineregionwav[min(i)] linelist[nline] = linecenter nline = nline + 1 endif if nline ge maxlines then break endfor linelists[nsci,*] = linelist linelist = linelist[0:nline-1] nliness[nsci] = nline endif endfor ; Line matching / printout linelists = transpose(linelists[*,0:max(nliness)]) linelists[where(linelists eq 0)] = 99999 compthreshold = 10 ijk = intarr(ctsci) offset = indgen(ctsci)*((size(linelists)) [1]) ctlines = 0 ctmultlines = 0 openw, 1, 'detectedlines.dat' printf, 1, 'Possible lines:' if ctsci eq 1 then begin for a = 0, n_elements(linelists)-1 do printf, 1, clip(linelists[a]) endif else begin for a = 0, n_elements(linelists)-1 do begin match = intarr(ctsci) aaa = ijk + offset unfinished = where(linelists[aaa] ne 99999, ct) if ct eq 0 then break currentlist = (where(linelists[aaa] eq max(linelists[aaa[unfinished]]) )) [0] match[currentlist] = 1 otherlist = where(indgen(ctsci) ne currentlist) for o = 0, n_elements(otherlist)-1 do begin if abs(linelists[aaa[otherlist[o]]]-linelists[aaa[currentlist]]) lt compthreshold then begin match[otherlist[o]] = 1 endif endfor outstr = '' for c = 0, ctsci-1 do begin if match[c] eq 1 then begin outstr = outstr + clip(linelists[aaa[c]],10) ijk[c] = ijk[c] + 1 endif else begin outstr = outstr + clip('',10) endelse endfor if total(match) ge 1 then ctlines = ctlines + 1 if total(match) ge 2 then ctmultlines= ctmultlines + 1 printf, 1, outstr endfor endelse close, 1 print, 'Detected ', clip(ctlines), ' line candidates (', clip(ctmultlines), ' multiple detections)' print, 'List of possible lines written to detectedlines.dat' ; Plotting ; open the plot plotfilename = 'specplots.ps' xs = 6 ys = 4.5 initdev = !d.name openplot, plotfilename, xs, ys prevgrating = '' col = 2 for nsci = 0, ctsci-1 do begin if nsci eq 0 or grating[nsci] ne prevgrating then begin sspec = allspec[nsci,sort(allspec[nsci,*])] yr = [0,1.05*sspec[fix((n_elements(sspec)-1)*0.99)]] ; set max to 5% above the 99 percentile flux xr = [max(allwav),min(allwav)] plot, [0], [0], xrange=xr, xstyle=1, yrange=yr, ystyle=1, xtitle='Wavelength', ytitle='Flux (counts)', $ title = object[nsci] + ' ('+clip(grating[nsci],4)+')', /nodata ; telluric lines ybox = [yr[0]+yr[1]/1000.,yr[0]+yr[1]/1000.,yr[1]*0.999,yr[1]*0.999,yr[0]+yr[1]/1000.] if min(xr) lt 7594 and max(xr) gt 7621 then $ polyfill, [7594, 7621+35, 7621+35, 7594, 7594], ybox, color=1 if min(xr) lt 6884 and max(xr) gt 6867 then $ polyfill, [6867, 6884+10, 6884+10, 6867, 6867], ybox, color=1 plot, [0], [0], xrange=xr, xstyle=1, yrange=yr, ystyle=1, /nodata, /noerase refscale = nsci ;xyouts, 0.2, 0.86, /norm, object[nsci] ;xyouts, 0.2, 0.8, /norm, strmid(grating[nsci],0,4) endif else begin col = col ;; + 1 endelse ;other lines ??? ; rescale = total(allspec[refscale,*])/total(allspec[nsci,*]) oplot, allwav[nsci,*], allspec[nsci,*]*rescale, color=col col = col + 1 if ctsci eq 1 then begin spec = (allspec[nsci,*]) [*] smoothspec = convol(spec, [0.075,0.2,0.45,0.2,0.075], /edge_truncate) oplot, allwav[nsci,5:nc-5], smoothspec[5:nc-5], psym=10 break endif prevgrating = grating[nsci] if nsci ne ctsci-1 then nextgrating = grating[nsci+1] if nsci ne ctsci-1 then nextcwave = cwave[nsci+1] if nsci eq ctsci-1 or grating[nsci] ne nextgrating or cwave[nsci] ne nextcwave then begin avspec = fltarr(nc) for x = 0, nc-1 do begin avspec[x] = total(allspec[where(grating eq grating[nsci] and cwave eq cwave[nsci]),x]) endfor avspec = avspec * total(allspec[refscale,*])/total(avspec) smoothspec = convol(avspec, [0.075,0.2,0.45,0.2,0.075], /edge_truncate) oplot, allwav[nsci,5:nc-5], smoothspec[5:nc-5] endif endfor psclose print, 'Reduced spectra plotted to ', plotfilename plotfilename = 'specplotsnorm.ps' xs = 6 ys = 4.5 initdev = !d.name openplot, plotfilename, xs, ys col = 2 sspec = allnorm[sort(allnorm)] yr = [0,min([1.15*sspec[fix((n_elements(sspec)-1)*0.992)],1.3])] ; set max to 15% above the 99.2 percentile flux xr = [max(allwav),min(allwav)] plot, [0], [0], xrange=xr, xstyle=1, yrange=yr, ystyle=1, xtitle='Wavelength', ytitle='Normalized flux', $ title = object[0], /nodata ybox = [yr[0]+yr[1]/1000.,yr[0]+yr[1]/1000.,yr[1]*0.999,yr[1]*0.999,yr[0]+yr[1]/1000.] if min(xr) lt 7594 and max(xr) gt 7621 then $ polyfill, [7594, 7621+35, 7621+35, 7594, 7594], ybox, color=1 if min(xr) lt 6884 and max(xr) gt 6867 then $ polyfill, [6867, 6884+10, 6884+10, 6867, 6867], ybox, color=1 plot, [0], [0], xrange=xr, xstyle=1, yrange=yr, ystyle=1, /nodata, /noerase for nsci = 0, ctsci-1 do begin spec = (allnorm[nsci,*]) [*] smoothspec = convol(spec, [0.075,0.2,0.45,0.2,0.075], /edge_truncate) oplot, allwav[nsci, 5:nc-5], smoothspec[5:nc-5], color=col, psym=10 col = col + 1 endfor minwavall = fix(min(allwav))+1 maxwavall = fix(max(allwav))-1 nwav = fix(maxwavall-minwavall) interpwav = findgen(nwav) + minwavall ; rebin to 1 A-pix interpfluxall = fltarr(ctsci,nwav) for nsci = 0, ctsci-1 do begin minwav = min(allwav[nsci,*]) maxwav = max(allwav[nsci,*]) interpok = where(interpwav gt minwav and interpwav lt maxwav) interpfluxall[nsci,interpok] = interpol(allnorm[nsci,*], allwav[nsci,*], interpwav[interpok]) endfor interpflux = fltarr(nwav) for x = 0, nwav-1 do begin fluxknown = where(interpfluxall[*,x] ne 0, ct) if ct gt 0 then interpflux[x] = median(interpfluxall[fluxknown,x], /even) endfor kernel = [0.1,0.2,0.6,0.9,1.0,1.0,1.0,0.9,0.6,0.2,0.1] ; ideally use aperture size kernel = kernel/total(kernel) interpfluxsmooth = convol(interpflux, kernel, /edge_truncate) oplot, interpwav, interpfluxsmooth psclose print, 'Normalized spectra plotted to ', plotfilename set_plot, initdev print print, 'All done.' print end