; NAME: ; pro welldepth_reduce.pro (v1.3) ; ; PURPOSE: ; Produce plot of welldepth and linearity. ; ; CALLING SEQUENCE: ; darkcurrent_reduce, testdir, [outdir [, infile [, valoutfile $ ; [, noref [, ma_refcor [, region [,imgoutfile] [, groupfactor]]]]]] ; ; INPUTS: ; testdir string containing directory name wherein input images and a ; list of the image file names can be found ; ; KEYWORD PARAMETERS: ; outdir directory where output will be written; defaults to ; testdir + '\Results' ; infile input file name. File must be in directory specified by ; testdir. Default name is 'ramps.txt' ; region rectangular region of SCA to consider for analysis. Should ; be entered as 4-element 1-d integer array, i.e. ; [x1,x2,y1,y2] to consider pixels in rows x1 to x2 and ; columns y1 to y2. Default is specified as all non-reference ; pixels ; scaname Name of detector from which input images were obtained. This keyword ; only needs to be supplied if the input images were taken manually (i.e, ; without running the welldepth experiment procedure). ; outfile Name of output plot file. Default is scaname + "_linsat.jpg". ; ; EXAMPLE ; Calculate welldepth and linearity on images listed in file ramps_1.txt, using ; only pixels in rows 100 - 900 and columns 100 - 900. The default output directory ; and file name are used. ; ; IDL> wdir = '\\rabbit\raid2\H1RG-022-SIPIN\cold1\welldepth.14Jun05' ; IDL> welldepth_reduce, wdir, infile="ramps_1.txt", region=[100,900,100,900] ; ; REFERENCE: ; None ; ; MODIFICATION HISTORY: ; Written by: ; Ernie Morse, IDTL, June 16, 2005 ; Modification of original code by Eddie Bergeron (welldepth_reduce_1.0.pro), ; altered for increased generality ; pro welldepth_reduce, testdir, infile = infile, outdir=outdir, $ region = region, rowinc = rowinc, scaname = scaname, outfile = outfile pathdelim = path_sep() ; save the current plot type plottype = !d.name ; check to see if input directory name ends in path delimiter--if not, ; add it to the end if (strmid(testdir, strlen(testdir)-1, 1) ne pathdelim) then begin testdir = testdir + pathdelim endif ; set outdir to testdir + 'Results' if not set by user if (keyword_set(outdir) eq 0) then begin outdir = testdir + 'Results' + pathdelim endif ; check to see if outdirectory name ends in path delimiter--if not, ; add it to the end if (strmid(outdir, strlen(outdir)-1, 1) ne pathdelim) then begin outdir = outdir + pathdelim endif file_mkdir,outdir if (not keyword_set(infile)) then begin infile = 'ramps.txt' endif if (not keyword_set(rowinc)) then begin rowinc = 1 endif ; read the list of ramps readcol, testdir + infile, ramps, format = '(A)' ; get information from the header of the 1st image ; images are assumed to be 3d image cubes fits_read, testdir + ramps[0], 0, h1, /header_only xsize = fix(sxpar(h1, 'naxis1')) ysize = fix(sxpar(h1, 'naxis2')) zsize = fix(sxpar(h1, 'naxis3')) if (not keyword_set(scaName)) then begin scaName = sxpar(h1, 'detname') endif dettemp = strtrim(string(sxpar(h1, 'dettemp'), format = '(F5.1)'), 2) wheel1 = sxpar(h1, 'wheel1') wheel2 = sxpar(h1, 'wheel2') if (not keyword_set(outfile)) then begin fname = outdir + scaName + '_linsat.jpg' endif else begin fname = outdir + outfile endelse ; find the number of pixels in one frame framepix = long(xsize) * long(ysize) ; get the exposure times for each read of the ramp exptime = (sxpar(h1, 'exp_time') / (zsize - 1)) * findgen(zsize) ; extract SCA type from SCA name scaType = strmid(scaName, 0, strpos(scaName, '-')) ; get voltages from the header if (strmid(scaType, 0, 1) eq 'S') then begin biases = ['VDETCOM', 'VDDUC', 'VDDCL', 'VROWOFF', 'VSSUC', $ 'ISLEWREF', 'VDDOUT', 'VSUB', 'VSSOUT1', 'VP', 'VNROW', $ 'VGGCL', 'VNCOL'] endif if (strmid(scaType, 0, 1) eq 'H') then begin biases = ['DSUB', 'VRESET', 'VBIASPWR', 'VBIASGTE', 'DRAIN', $ 'VPULLA7', 'VPULLA15', 'OUTWINA', 'VREF', 'VPULLA23', $ 'VPULLA31', 'VDDA', 'VDD'] endif ; if the user didn't set the region, define default regions based on the ; SCA type if (not keyword_set(region)) then begin case scaType OF 'H1RG' : begin region = [4, 1019, 4, 1019] end 'H2RG' : begin region = [4, 2043, 4, 2043] end 'SB304': begin region = [4, 2051, 0, 2047] end ELSE : begin print, 'Detector type ' + scaType + $ ' not supported. Exiting procedure.' return end endcase endif ; find where images are off both rails. Be conservative ramp_medians = fltarr(n_elements(ramps), zsize) for rampcount = 0, n_elements(ramps) - 1 do begin for readcount = 0, zsize - 1 do begin fits_read, testdir + ramps[rampcount], r, $ first = readcount * framepix, $ last = (readcount + 1) * framepix - 1 r = reform(r, xsize, ysize, /overwrite) ramp_medians[rampcount, readcount] = median(r[region[0]:region[1], $ region[2]:region[3]:rowinc]) endfor endfor ; find offset between each of the ramps ramp_offsets = fltarr(n_elements(ramps) - 1) for i = 1, n_elements(ramps) - 1 do begin ; find nonrailed reads of 1st ramp nonrailed_1 = where(ramp_medians[i - 1, *] gt -31000.0 $ and ramp_medians[i - 1, *] lt 31000.0) ; find nonrailed reads of 2nd ramp nonrailed_2 = where(ramp_medians[i, *] gt -31000.0 $ and ramp_medians[i, *] lt 31000.0) ; use a linear fit to the last 3 good points of the first ramp and ; the first 3 points of the second ramp. p1 = poly_fit(exptime[nonrailed_1[n_elements(nonrailed_1) - 3:*]], $ ramp_medians[i - 1, $ nonrailed_1[n_elements(nonrailed_1) - 3:*]], 1, /double) p2 = poly_fit(exptime[nonrailed_2[0:2]], $ ramp_medians[i, $ nonrailed_2[0:2]], 1, /double) ; match to the midpoint between the ends of the two ramps midtime = mean([exptime[nonrailed_1[n_elements(nonrailed_1) - 1]], $ exptime[nonrailed_2[0]]]) ramp_offsets[i - 1] = poly(midtime, p1) - poly(midtime, p2) endfor ; find out where saturation occurs in the last ramp ; define saturation as the first read whose median signal is within 200 ADU ; of the previous read. ; start by calculating difference of median of each read in last ramp with ; the previous read. nonrailed = where(ramp_medians[n_elements(ramps) - 1, *] gt -31000.0) med_diff = ramp_medians[n_elements(ramps) - 1, nonrailed[0] + 1:*] $ - ramp_medians[n_elements(ramps) - 1, nonrailed[0]:zsize - 2] ; presatread is the read # of the last read prior to saturation presatread = (where(med_diff lt 200.0))[0] + nonrailed[0] ; read in the last non-saturated read and the 1st saturated read fits_read, testdir + ramps[n_elements(ramps) - 1], topend, $ first = presatread * framepix, $ last = (presatread + 2) * framepix - 1 topend = double(topend) topend = reform(topend, xsize, ysize, 2, /overwrite) ; find saturated pixels in region of interest (roi) diff = abs(topend[*,*,1] - topend[*,*,0]) roi = diff[region[0]:region[1], region[2]:region[3]:rowinc] satpix = where(roi lt 200) ; get the baseline read of the 1st ramp, which is the first read ; that is not railed at the low end of the A/D range baseread = (where(ramp_medians[0,*] gt -31000.0))[0] fits_read, testdir + ramps[0], bottomend, $ first = baseread * framepix, $ last = (baseread + 1) * framepix - 1 bottomend = double(bottomend) bottomend = reform(bottomend, xsize, ysize, /overwrite) ; calculate the offset in ADU between the 1st and last ramp and subtract ; it from the first ramp. total_offset = total(ramp_offsets) bottomend = bottomend - total_offset ; find accumulated signal between 1st and last ramps sig_accum = topend[*,*,1] - bottomend roi = sig_accum[region[0]:region[1], region[2]:region[3]:rowinc] ; make a histogram of the accumulated signal in the saturated pixels in the ; region binsize = 100 signal_min = min(roi) - (min(roi) mod binsize) - binsize / 2.0 signal_max = max(roi) - (max(roi) mod binsize) - binsize / 2.0 satpixhist = histogram(roi, binsize = binsize, locations = signal, $ min = signal_min, max = signal_max) ; convert from raw pixel counts to percentage of pixels in region satpixhist = satpixhist / float(n_elements(roi)) * 100.0 ; adjust signal bin values to show the center value of each bin signal = signal + binsize / 2.0 ; find cumulative percentages in each bin cumulative = fltarr(n_elements(signal)) cumulative[0] = satpixhist[0] for bincount = 1, n_elements(signal) - 1 do begin cumulative[bincount] = cumulative[bincount - 1] + satpixhist[bincount] endfor ; find the exposure times and corresponding values of non-railed medians nonrailed = where(ramp_medians gt -31000.0 and ramp_medians lt 31000.0) ; convert to 2-D indices nonrailed_2d = array_indices(ramp_medians, nonrailed) ; get the exposure times for use in fitting fit_times = exptime[nonrailed_2d[1,*]] ; apply the offset to each of the ramp medians for rampcount = 0, n_elements(ramps) - 2 do begin ramp_medians[rampcount, *] = ramp_medians[rampcount, *] $ - total(ramp_offsets[rampcount:*]) endfor fit_signal = ramp_medians[nonrailed] fit_signal = fit_signal[1:*] - fit_signal[0] frac_rate = [fit_signal / fit_times[1:*]] fitvals = where(fit_signal lt max(fit_signal) * 0.8) p = poly_fit(fit_signal[fitvals], frac_rate[fitvals], 2, /double) p1 = p / p[0] ugood = where(fit_signal gt 0.0) ; construct string for display of region region_str = strtrim(string(region, format='(I4)'), 2) region_out = '[' + region_str[0] + ':' + region_str[1] + ', ' $ + region_str[2] + ':' + region_str[3] + ':' $ + strtrim(string(rowinc, format='(I3)'), 2) + ']' ; transform bias values into a string for plot output bias_out = strarr(n_elements(biases)) for i = 0, n_elements(biases) - 1 do begin bias_out[i] = strtrim(string(sxpar(h1, biases[i]), format = '(F7.3)'), 2) endfor black = 0 white = 255 ; Open the z-buffer device set_plot, 'z' ; set resolution and font device, set_resolution=[8000,6000] device, set_font='Courier' !P.MULTI = [0, 1, 2] ; Set up for two plots per page fsub = fname ; set text to print at bottom of plot ; set plot margin & tick marks !Y.MINOR=0 !y.margin=[6,4] !x.margin=[12,12] ; set some size values !p.charsize = 8.0 !p.charthick = 15.0 !p.thick = 10.0 !x.thick = 20.0 !y.thick = 20.0 plottitle = scaName + ' Well Depth Histogram at ' + dettemp + ' K (' $ + wheel1 + ' + ' + wheel2 + ')' ; define x and y coordinates of histogram peak ymax = max(satpixhist, ymax_sub) x_ymax = signal[ymax_sub] ; adjust signal minimum and maximum to enclose the central 95% of the ; cumulative curve signal_min = (signal[where(cumulative ge 2.5)])[0] signal_max = (signal[where(cumulative ge 97.5)])[0] ; set x-axis range so that peak is in center of plot delta_x = (x_ymax - signal_min) > (signal_max - x_ymax) xmax = x_ymax + delta_x xmin = x_ymax - delta_x xwidth = xmax - xmin plot, signal, satpixhist, $ psym = 10, $ xtitle = 'Well Depth (ADU)', $ ytitle = '% Number of Pixels', $ title = plottitle, $ xrange = [xmin, xmax], $ yrange = [0, ymax * 1.1], $ ystyle = 9, $ xstyle = 1, $ background = white, $ color = black ; draw vertical line through histogram peak plots, [x_ymax, x_ymax], [0, ymax], linestyle = 2, color = black ; add annotation of peak value xyouts, x_ymax + xwidth * 0.012, ymax * 0.1, $ strcompress(string(x_ymax, format = '(I8)'), /rem), $ orient = 90, color = black ; add axis for cumulative percentage axis, yaxis = 1, yrange = [0, 100], /save, ytitle = 'Cumulative %', $ ytickv = indgen(11) * 10., $ yticks = 10, $ yminor = 5, $ color = black ; plot the cumulative percentage oplot, signal, cumulative, lines = 3, color = black ; add biases to plot for i = 0, n_elements(biases) - 1 do begin xyouts, x_ymax + xwidth * 0.3, 85. - (i*5), biases[i]+' = ' $ + bias_out[i] + ' V', color = black endfor xyouts, xmin + xwidth * 0.03, 94.0, 'Analysis Region = ' $ + region_out, color = black ; plot linearity plot, fit_signal[ugood], frac_rate[ugood]/p[0], yra = [0.6, 1.15], $ xra = [0, max(fit_signal)*1.1], xstyle = 1, $ ystyle = 1, title = scaName + ' Linearity', xtitle = 'Total DN in Well', $ ytitle = 'Fractional Countrate', xmar = [8, 6], $ background = white, color = black oplot, fit_signal[ugood], frac_rate[ugood]/p[0], psym = 4, color = black, $ symsize = 5.0 circsym, 6, 1 oplot, fit_signal[fitvals], frac_rate[fitvals]/p[0], psym = 8, color = black oplot, findgen(max(fit_signal) * 1.1), $ poly(findgen(max(fit_signal) * 1.1), p1), linestyle = 3, $ color = black plots, [0, max(fit_signal) * 1.1], [1.0, 1.0], linestyle = 2, $ color = black a1 = strcompress(string(p1[1], format = '$(e20.10)'), /rem) a1 = strmid(a1, 0, 5)+strmid(a1, strpos(a1, 'e')) a2 = strcompress(string(p1(2), format = '$(e20.10)'), /rem) a2 = strmid(a2, 0, 5)+strmid(a2, strpos(a2, 'e')) xyouts, max(fit_signal) * 0.1, 0.8, 'fit = 1 + (' + a1 + ' * DN) + (' + $ a2 + ' * DN^2)', color = black xyouts, max(fit_signal) * 0.2, 0.77, ' = included in fit', /data, $ color = black xyouts, max(fit_signal) * 0.2, 0.74, ' = not included in fit', /data, $ color = black xyouts, max(fit_signal) * 0.1, 0.71, 'Analysis Region = ' $ + region_out, color = black circsym, 5, 1 oplot, [max(fit_signal) * 0.17], [0.775], psym = 8, color = black oplot, [max(fit_signal) * 0.17], [0.745], psym = 4, color = black, $ symsize = 5.0 ; write out jpg image jpgimg = tvrd() write_jpeg, fname, $ congrid(jpgimg, 1600, 1200, /center, /interp), quality=100 ; finish up by closing device device, /close !p.multi = 0 !p.font = (-1) end