;-------------------------------------------------------------------- PRO fg_shift_pix, index, data, index_out, data_out, mask, $ no_vignet=no_vignet, $ verbose=verbose, quiet=quiet, $ version=progver, name=prognam, $ update =update ;+ ; NAME: ; FG_SHIFT_PIX ; ; PURPOSE: ; Correct the FG CCD camera readout defects. ; This is the first step in the calibration procedure of FG_PREP. ; ; CATEGORY: ; FITS processing ; ; SAMPLE CALLING SEQUENCE: ; FG_SHIFT_PIX, index, data, index_out, image_out, mask $ ; [, /no_vignet, /update, name=name, version=version $ ; , /verb ] ; ; INPUTS: ; INDEX: an SSW header index structure for the image contained in DATA. ; DATA: a 2-D image from the SOT/FG CCD camera. ; ; OUTPUTS: ; INDEX_OUT: the SSW header index structure for the corrected image. ; DATA_OUT: the corrected SOT/FG CCD camera data array. ; ; OUTPUTS (Optional): ; MASK: a 2-D image showing valid and invalid pixels. This array ; is used when filling the bad pixels in fg_bad_pix. ; ; OPTIONAL INPUT KEYWORD PARAMETERS: ; NO_VIGNET : If set, do not mask the LHS vignetting of NFI ; UPDATE: If set, update history record in INDEX_OUT ; ; OPTIONAL OUTPUT KEYWORD PARAMETERS: ; VERSION: the version number of this routine. ; NAME: the name of this routine. ; ; RESTRICTIONS: INDEX must be an SSW image index structure with appropriate ; keywords for treating the image. ; DATA must be a 2- or 3-D image array. ; ; PROCEDURE: ; ; ; MODIFICATION HISTORY: ;v1.0 Created 23-Feb-2007, T. Berger LMSAL ;v1.1 Bug fixes and added SHIFT keyword for 2x2 summed readouts. ; 2-April-2007, T. Berger LMSAL. ;v1.2 Correction of top column pixel shift is added. ; Bug fixes for missing central row in part. readout with 2x2 summing. ; INDEX is updated if necessary. Add a mask keyword for dead ; pixels. Shift keyword is deleted. 12-April-2007, YK ;v1.3 Bug fix for mask data, etc. 16-April-2007, YK ;v1.4 Bug fix of outer rows mask for 2x2 data 2-May-2007, YK ;v1.5 Modify to handle NFI multi-image data files. ; Added 4x4 summing readout corrections. 24-Oct-2007, TEB. ;v1.51 Corrected pass-through of binned image mask. TEB 28-Jul-2008. ;v1.6 Update to handle binned images. 28-Oct-2008, YK ;v1.61 Added a keyword NO_VIGNET to enable/disable the LHS vignetting ; of NFI. YK 3-Feb-2009 ;- ;----------------------------------------------------------------------------- ; ;Name, version, and timing information progver = 'V1.6.1' prognam = 'FG_SHIFT_PIX.PRO' ;Keyword processing quiet = 1 loud = 1 - KEYWORD_SET(quiet) verbose = KEYWORD_SET(verbose) if (verbose eq 1) then loud = 1 if (loud) then PRINT, 'Running ', prognam, ' ', progver ;Determine image properties and type img_nx0 = gt_tagval(index,/naxis1) img_ny0 = gt_tagval(index,/naxis2) img_ssum = gt_tagval(index,/camssum) img_psum = gt_tagval(index,/campsum) img_binx = gt_tagval(index,/fgbinx) img_biny = gt_tagval(index,/fgbiny) img_ix0 = gt_tagval(index,/fgccdix0) img_iy0 = gt_tagval(index,/fgccidy0) img_ix1 = gt_tagval(index,/fgccdix1) ; image x0 on ccd array img_iy1 = gt_tagval(index,/fgccdiy1) ; image y0 on ccd array img_roi0 = gt_tagval(index,/roistart,missing=0) ;CCD readout codes. Flats are missing these. img_roi1 = gt_tagval(index,/roistop,missing=1025) genid = gt_tagval(index,/gen_id) ;BFI or NFI data: if gt_tagval(index,/waveid) le 6 then nfi = 0 else nfi = 1 ;convert image corners to solar image orientation x0 = (4095-img_ix1)/img_psum x1 = x0+img_nx0*img_binx-1 y0 = (2047-img_iy1)/img_ssum y1 = y0+img_ny0*img_biny-1 ;Full FOV or partial? img_roi0 = 0 and img_roi1 = 1025 can be fooled ;by ROI offsets. See e.g. 25-Apr-2007 H-alpha 1024x1024 2x2 straddling ;center of CCD unequally. if (img_roi0 eq 0) and (img_roi1 eq 1025) then full_fov = 1 else full_fov = 0 ; output data & index data_out = data index_out = index ; mask array for non-existing or anomalous data mask = BYTE(data)*0b ; for pixel shift along X-axis xarr = INDGEN(img_nx0*img_binx) + x0 yarr = INDGEN(img_ny0*img_biny) + y0 ;Determine number of images in DATA array and effective exposures. nexp = fg_num_eff_exp(index, quiet=(1-loud)) nimage = N_ELEMENTS(nexp) ;Loop through images in data array for i=0,nimage-1 do begin image = data[*,*,i] imask = BYTE(image)*0B + 1B image_type = fg_image_type(index,i) ; for binning data if img_binx gt 1 then begin image = rebin(image, img_nx0*img_binx, img_ny0*img_biny) imask = rebin(imask, img_nx0*img_binx, img_ny0*img_biny) endif ;1. Top column anomaly correction, full or partial readout. ;Note that img_ssum = img_psum is implicitly assumed. case img_ssum of 1: begin ; no summing if y1 eq 2047 and y0 eq 0 then begin ; top column to bottom image = SHIFT(image,0,1) ; 1 pixel shift at the bottom column ;left side: ss = WHERE(xarr lt 2048, ns) if ns gt 0 then begin image[ss[0:ns-2],0] = image[ss[1:ns-1],0] image[ss[ns-1],0] = 0 imask[ss[ns-1],0] = 0 end ;right side: ss = WHERE(xarr ge 2048, ns) if ns gt 0 then begin image[ss[1:ns-1],0] = image[ss[0:ns-2],0] image[ss[0],0] = 0 imask[ss[0],0] = 0 end endif else if y1 eq 2047 then begin ; top column to bottom image = SHIFT(image,0,1) ; mask the bottom column image[*,0] = 0 imask[*,0] = 0 endif else begin ; no shift, but update header index_out.fgccdiy0 -= 1 index_out.fgccdiy1 -= 1 endelse end ;case 1 2: begin ; 2x2 summing if y1 eq 1023 and y0 eq 0 then begin ;full FOV ; top column to bottom, 3 pixel shift image = SHIFT(image,0,3) ; mask the bottom 2 columns. image[*,0:1] = 0 imask[*,0:1] = 0 ; 1 pixel shift at the 3rd bottom column ;left side: ss = WHERE(xarr lt 1024, ns) if ns gt 0 then begin image[ss[0:ns-2],2] = image[ss[1:ns-1],2] image[ss[ns-1],2] = 0 imask[ss[ns-1],2] = 0 end ;right side: ss = WHERE(xarr ge 1024, ns) if ns gt 0 then begin image[ss[1:ns-1],2] = image[ss[0:ns-2],2] image[ss[0],2] = 0 imask[ss[0],2] = 0 end endif else if y1 ge 1021 then begin ; top column to bottom dy = y1-1020 image = SHIFT(image,0,dy) ; mask the bottom column image[*,0:(dy-1)<1] = 0 imask[*,0:(dy-1)<1] = 0 ; update header index_out.fgccdiy0 -= (3-dy)*2 index_out.fgccdiy1 -= (3-dy)*2 endif else begin ; no shift, but update header index_out.fgccdiy0 -= 3*2 index_out.fgccdiy1 -= 3*2 endelse end ;case 2 4: begin ;4x4 summing if (y0 eq 0) and (y1 eq 511) then begin ;full FOV image = SHIFT(image,0,4) image[*,0:1]=0 imask[*,0:1]=0 ; 1 pixel shift for 2:3 columns ;left side ss = WHERE(xarr lt 512, ns) if ns gt 0 then begin image[ss[0:ns-2],2:3] = image[ss[1:ns-1],2:3] image[ss[ns-1],2:3] = 0 imask[ss[ns-1],2:3] = 0 end ;right side: ss = WHERE(xarr ge 512, ns) if ns gt 0 then begin image[ss[1:ns-1],2:3] = image[ss[0:ns-2],2:3] image[ss[0],2:3] = 0 imask[ss[0],2:3] = 0 end end else MESSAGE,/INFO,'Partial frame readout with 4x4 summing not yet implemented.' end ;case 4 else: begin MESSAGE,/INFO,'Unrecognized camera summing mode. Returning un-shifted data...' RETURN end endcase ;on summing ;2. Missing central row correction if not (full_fov) then begin ;partial frame readout. ; Add blank rows in the middle. These are interpolated later by fg_bad_pix. ; Note that 2x2 images are also missing just one CCD row in the middle of the image. ; middle of image array: xm = 2048/img_psum ;left side: ss = WHERE(xarr lt xm, ns) if ns gt 0 then begin case img_psum of 1: begin ; if no summing, shift -1 pixel image[ss[0:ns-2],*] = image[ss[1:ns-1],*] image[ss[ns-1],*] = 0 imask[ss[0:ns-2],*] = imask[ss[1:ns-1],*] imask[ss[ns-1],*] = 0 end 2: begin ; if 2x2 summing, no shift but update header index_out.fgccdix0 += 1 index_out.fgccdix1 += 1 imask[ss[0],*] = 0 end 4: MESSAGE,/info,'Partial frame readout with 4x4 summing not yet implemented.' endcase end ;right side: ss = WHERE(xarr ge xm, ns) if ns gt 0 then begin image[ss[1:ns-1],*] = image[ss[0:ns-2],*] image[ss[0],*] = 0 imask[ss[1:ns-1],*] = imask[ss[0:ns-2],*] imask[ss[0],*] = 0 end end else begin ;Full-frame read-out. Bright central rows handled in flat-fielding. Mask outer rows. ss = WHERE((xarr le 1) or (xarr ge 4096/img_psum-2),ns) if ns gt 0 then begin image[ss,*] = 0 imask[ss,*] = 0 endif end ;3. NFI vignetting on LHS: if (not keyword_set(no_vignet)) and (nfi) and (img_ix1 eq 4095) then begin image[0:27,*] = 0 xim = xarr # REPLICATE(1,img_ny0) yim = REPLICATE(1,img_nx0) # yarr if img_iy0 eq 0 then ss = WHERE( yim lt (120-2*xim) ) else ss = 0 image[ss]=0 imask[0:27,*] = 0 imask[ss] = 0 end ; restore binning if img_binx gt 1 then begin image = rebin(image, img_nx0, img_ny0) imask = rebin(imask, img_nx0, img_ny0) endif data_out[*,*,i] = image*imask mask[*,*,i] = imask end ;main for loop on data array ; Update history record in the index if requested if KEYWORD_SET(update) then begin tagval = 'Corrected CCD readout anomalies.' update_history,index_out, tagval, version=progver if (loud) then MESSAGE, /INFO, 'HISTORY record updated: '+tagval endif RETURN END