;- ; docformat = 'rst' ;+ ; Wrapper to correct NIRCam dark ramps for 1/f noise and derive dark map and RON ;- ;+ ; Wrapper to correct NIRCam dark ramps for 1/f noise and derive dark map and RON ; :Categories: ; JWST Data Processing - NIRCam Cryo tests ; :Examples: ; IDL> analyze_dark_ramp ; :uses: ; Common blocks:: ; ; COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask; ; ; :History: created by M. Robberto, 25 Apr. 201 ;- pro analyze_dark_ramp COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask st=systime(1) ;on robberto2 DIR_OUT = '~/FUNCTIONAL/JWST/NIRCAM/Studies/2013/2013.NIRCAM.Noise/Results/' ;on witserv ;DIR_OUT = '/witserv/data15/data_analysis_results/' ; ;set detector parameters SET_DETECTOR_PARAMS ; ;get ready to find files DATA_PATH= '/Volumes/witserv' DATA_PATH = DATA_PATH+'/witserv/data14/nrc/nrc_cryo2' OBS_ID = 'NRC_2D6-DARK' DETECTOR = '486' FIND_FILES,DATA_PATH,OBS_ID,DETECTOR,FILES ; ;DATA_PATH = '~/FUNCTIONAL/JWST/2011/RauscherReadOut/NIRSPEC_data' ;files = FILE_SEARCH(DATA_PATH+'/*.fits',count=nfiles) ; ;read the first file and process N_FILES = N_ELEMENTS(FILES) FOR jf = 0, N_files-1 do begin print,'begin reading ramp: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' data0 = float(readfits(files[jf],/silent))*gain print,' end reading ramp: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ; ; ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;EXTRACT THE DIR AND FILE STRINGS AND SET THE DIRECTORY IN OUTPUT ;first the position of the bar in the filename bar = STREGEX(files[jf],'/') ; ;then the last character, before the .fits extension dfits = STREGEX(files[jf],'.fits') ; ;now get the directory name filedirname = strmid(files[jf],0,bar-1) ; ;and the filebasename filebasename = strmid(files[jf],bar+1,dfits-bar-1) ; ;put dire and filebasename in a single variable for the output fileinfo = [DIR_OUT,filedirname, filebasename] ;done with the dir and file strings ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; ;run the analysis STOP RAMP_COMMON_LEVEL, data0 RAMP_FIXSECTORS, data0 correct_Evenodd_ramp, data0 ramp_OPTIMAL_FILTER, data0 ;make dark datacube RAMP_BasicLinFit, data0, darkcube RAMP_PlotBasicLinFit, darkcube, dark_averages, fileinfo RAMP_GETRON, data0, darkcube, RON RAMP_PLOT_4histo,RON, RON_AVERAGES, MASK, fileinfo STOP PRINT_RESULTS,fileinfo,darkcube,ron, dark_averages,ron_averages ENDFOR END ;;------------------------------------------------------------- ;;+ ;; NAME: ;; DETECTOR_PARAMS ;; PURPOSE: ;; Specifies main detector parameters ;; CATEGORY: ;; JWST Data Processing ;; CALLING SEQUENCE: ;; detector_params ;; INPUTS: ;; none ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; none ;; COMMON BLOCKS: ;; COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask ;; NOTES: ;; The detector parameters are transmitted out through the common block ;; MODIFICATION HISTORY: ;; M. Robberto, created 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO DETECTOR_PARAMS ;COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask ;gain=2 ;h =lindgen(2048,2048) ;h1mask = h[0:511,*] ;h2mask = rotate(h[512:1023,*],5) ;h3mask = h[1024:512*3-1,*] ;h4mask = rotate(h[512*3:*,*],5) ;END ;;------------------------------------------------------------- ;;+ ;; NAME: ;; FIND_FILES ;; PURPOSE: ;; Select a set of fits files to be processed, all in a given directory ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; find_files, data_path, obs_id, detector, files ;; INPUTS: ;; data_path: Directory where the fits files are stored ;; obs_id: Initial String common to all filenames, e.g. 'NRC_2D6-DARK' ;; detector: Detector ID number, e.g. '485' (string) ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; files: string array of fits files with ames matching the obs_id and detector strings ;; COMMON BLOCKS: ;; COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask; ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; The detector parameters are transmitted out through the common block ;; Example: ;; DATA_PATH = '/Volumes/witserv/witserv/data14/nrc/nrc_cryo2' ;; OBS_ID = 'NRC_2D6-DARK' ;; DETECTOR = '486' ;; FIND_FILES,DATA_PATH,OBS_ID,DETECTOR,FILES ;; MODIFICATION HISTORY: ;; M. Robberto, created 25 Apr. 201 ;;- ;;------------------------------------------------------------- ;PRO FIND_FILES,DATA_PATH,OBS_ID,DETECTOR,FILES ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask ;print,'begin reading ramp: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;cd, DATA_PATH ;;for test purposes ;; OBS_ID = 'NRC_2D6-DARK' ;; DETECTOR = '486' ;files = FILE_SEARCH(OBS_ID+'*'+'/*'+DETECTOR+'*.fits',count=nfiles) ;; ;;;read datacube, assume gain=2 ;;;jf = 0 ;; data0 = float(readfits(file,/silent))*gain ;;print,' end reading ramp: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;print,' end reading ramp: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;END ;;------------------------------------------------------------- ;;+ ;; NAME: ;; READ_RAMP ;; PURPOSE: ;; Read a single fits file in multiaccum format ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; READ_RAMP, data0 ;; INPUTS: ;; none ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; data0: ramp datacube, typical format [2048,2048,Ngroups] ;; COMMON BLOCKS: ;; COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask; ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; This routine is used to read a single file, identified inside (editing needed); ;; used for debugging ;; MODIFICATION HISTORY: ;; M. Robberto, created 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO READ_RAMP,data0 ;;to test: find and read only one file ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask ;st=systime(1) ;print,'begin reading ramp: ',st,' sec ',memory(/high)/1e9,' GB' ;Cross_correlation = 0 ; ;DATA_PATH= '/Volumes/witserv' ;DATA_PATH = DATA_PATH+'/witserv/data14/nrc/nrc_cryo2' ;cd, DATA_PATH ; OBS_ID = 'NRC_2D6-DARK' ; DETECTOR = '486' ;file = FILE_SEARCH(OBS_ID+'*'+'/*'+DETECTOR+'*.fits',count=nfiles) ;; ;;read datacube, assume gain=2 ;gain=2 ;jf = 0 ; data0 = float(readfits(file[jf],/silent))*gain ;print,' end reading ramp: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;END ;;------------------------------------------------------------- ;;+ ;; NAME: ;; RAMP_FIXSECTORS ;; PURPOSE: ;; Correct for the amplifier reset of NIRCam ASICs by matching the top/bottom reference pixes of adjacent groups ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; ramp_fixsectors, data0 ;; INPUTS: ;; data0; ramp datacube to be corrected, assumes format [2048,2048,Ngroup] ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; data0: ramp datacube after correction, assumes format [2048,2048,Ngroups] ;; COMMON BLOCKS: ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; This routine assumes that the average of the 4 bottom rows of group N+1 is the same of the average of the ;; top rows of group N+1, and equalizes accordingly. ;; The comparison is performed after subtraction of the average level of each pixel. ;; => Clearly, this assumption becomes rather weak/false if the groups are "real groups", i.e. if the frame is an average ;; of 2,4,8 single frames. ;; MODIFICATION HISTORY: ;; M. Robberto, created 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO RAMP_FIXSECTORS,data0 ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;print,'begin fixing sectors: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;; ;;x because of the amplifier reset, need to homogenize the signal ramps ;;x h =lindgen(2048,2048) ;;x h1mask = h[0:511,*] ;;x h2mask = rotate(h[512:1023,*],5) ;;x h3mask = h[1024:512*3-1,*] ;;x h4mask = rotate(h[512*3:*,*],5) ; ;; ;;Find the global averages of the bottom and top pixels, as we will work on the differences from the average ;mbottom1=MEAN(data0[0:511,0:3,*],dim=3) & mtop1=MEAN(data0[0:511,2044:2047,*],dim=3) ;mbottom2=MEAN(data0[512:1023,0:3,*],dim=3) & mtop2=MEAN(data0[512:1023,2044:2047,*],dim=3) ;mbottom3=MEAN(data0[1024:1535,0:3,*],dim=3) & mtop3=MEAN(data0[1024:1535,2044:2047,*],dim=3) ;mbottom4=MEAN(data0[1536:2047,0:3,*],dim=3) & mtop4=MEAN(data0[1536:2047,2044:2047,*],dim=3) ;; ;;perform the correction of the ramp ;for i=1,107 do begin & $ ;data0[0:511,*,i]=data0[0:511,*,i]-MEAN(data0[0:511,0:3,i]-mbottom1)+MEAN(data0[0:511,2044:2047,i-1]-mtop1) & $ ;data0[512:1023,*,i]=data0[512:1023,*,i]-MEAN(data0[512:1023,0:3,i]-mbottom2)+MEAN(data0[512:1023,2044:2047,i-1]-mtop2) & $ ;data0[1024:1535,*,i]=data0[1024:1535,*,i]-MEAN(data0[1024:1535,0:3,i]-mbottom3)+MEAN(data0[1024:1535,2044:2047,i-1]-mtop3) & $ ;data0[1536:2047,*,i]=data0[1536:2047,*,i]-MEAN(data0[1536:2047,0:3,i]-mbottom4)+MEAN(data0[1536:2047,2044:2047,i-1]-mtop4) & $ ;endfor ;print,' end fixing sectors: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;END ;;------------------------------------------------------------- ;;+ ;; NAME: ;; RAMP_COMMON_LEVEL ;; PURPOSE: ;; Match the four sectors of the detector to a common, average DC level ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; common_level, data0 ;; INPUTS: ;; data0; ramp datacube to be corrected, assumes format [2048,2048,Ngroup] ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; data0: ramp datacube after correction, assumes format [2048,2048,Ngroups] ;; COMMON BLOCKS: ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; This routine uses the average of the top and bottom reference pixels to establish the global supermean level of the ramp. ;; Then the reference pixels (top&bottom) of each sector&frame are tuned to match the global supermean. ;; MODIFICATION HISTORY: ;; M. Robberto, created 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO RAMP_COMMON_LEVEL,data0 ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;print,'begin setting common level: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;s = size(data0) ;nn = lindgen(s[3]) ;an array of 108 intgers, 0 to 107 ;; ;;REFPIXDOWN ;;refpix1down = data0[0:511,0:3,*] ;isolate the datacubes of ref pixels ;refpix2down = data0[512:1023,0:3,*] ;& refpix2down = refpix2down[rev,*,*] ;refpix3down = data0[1024:1535,0:3,*] ;refpix4down = data0[1536:2047,0:3,*] ;& refpix4down = refpix4down[rev,*,*] ;;REFPIXUP ;refpix1up = data0[0:511,2044:2047,*] ;isolate the datacubes of ref pixels ;refpix2up = data0[512:1023,2044:2047,*] ;& refpix2up = refpix2up[rev,*,*] ;refpix3up = data0[1024:1535,2044:2047,*] ;refpix4up = data0[1536:2047,2044:2047,*] ; & refpix4up = refpix4up[rev,*,*] ;; ;;HERE ONE CAN CORRECT FOR THE EVEN AND ODD PIXE:S. here is a template ;;rp1 = [(refpix1down+refpix1up)/2.] & rp1=avg(rp1,1) & rp1=avg(rp1,1) ;array of 512 elements ;;rp1even=rp1[indgen(256)*2] & rp1odd=rp1[indgen(256)*2+1] ;;rp1_DELTA = AVG(rp1even)-AVG(rp1odd) ;;data0[indgen(256)*2,*,*]-=rp1_DELTA/2. & data0[indgen(256)*2+1,*,*]+=rp1_DELTA/2. ;; ;;rp2 = [(refpix2down+refpix2up)/2.] & rp2=avg(rp2,1) & rp2=avg(rp2,1) ;array of 512 elements ;;rp2even=rp2[indgen(256)*2+512] & rp2odd=rp2[indgen(256)*2+1+512] ;;rp2_DELTA = AVG(rp2odd)-AVG(rp2even) ;;data0[indgen(256)*2+1+512,*,*]+=rp2_DELTA/2. & data0[indgen(256)*2+512,*,*]+=rp2_DELTA/2. ;;etc... ;;stop ;; ;;ALLTOGETHER ;alltogether = [data0[*,0:3,*],data0[*,2044:2047,*]] ;; ;;SUPERMEAN ;resistant_mean,alltogether,3,supermean ;the average of the average is the DC level of the output channel ;;stop ;;CORRECT FOR THE OFFSETS ;for iread=0,s[3]-1 do begin ;;Q1 ; refpix_quad = [refpix1down[*,*,iread],refpix1up[*,*,iread]] ; resistant_mean,refpix_quad,3,mean_quad ;the average of the average is the DC level of the output channel ; data0[0:511,*,iread] = data0[0:511,*,iread] - mean_quad + supermean ;;Q2 ; refpix_quad = [refpix2down[*,*,iread],refpix2up[*,*,iread]] ; resistant_mean,refpix_quad,3,mean_quad ;the average of the average is the DC level of the output channel ; data0[512:1023,*,iread] = data0[512:1023,*,iread] - mean_quad + supermean ;;Q3 ; refpix_quad = [refpix3down[*,*,iread],refpix3up[*,*,iread]] ; resistant_mean,refpix_quad,3,mean_quad ;the average of the average is the DC level of the output channel ; data0[1024:1535,*,iread] = data0[1024:1535,*,iread] - mean_quad + supermean ;;Q4 ; refpix_quad = [refpix4down[*,*,iread],refpix4up[*,*,iread]] ; resistant_mean,refpix_quad,3,mean_quad ;the average of the average is the DC level of the output channel ; data0[1536:2047,*,iread] = data0[1536:2047,*,iread] - mean_quad + supermean ;endfor ;print,'end setting common level: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;;image data0 is now on a even ground ;end ;;------------------------------------------------------------- ;;+ ;; NAME: ;; OPTIMAL_FILTER ;; PURPOSE: ;; Perform an optimal filtering of the vertical reference pixel to reduce 1/f noise (horizontal stripes) ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; optimal filter, data0 ;; INPUTS: ;; data0; ramp datacube to be corrected, assumes format [2048,2048,Ngroup] ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; data0: ramp datacube after correction, assumes format [2048,2048,Ngroups] ;; COMMON BLOCKS: ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; Calls the routing optimal_smooth_fft.pro ;; MODIFICATION HISTORY: ;; M. Robberto, created 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO OPTIMAL_FILTER,data0 ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;print,'begin optimal filtering: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;s = size(data0) ;nn = lindgen(s[3]) ;an array of 108 intgers, 0 to 107 ;;-extract the side reference pixels ;refpixleft = data0[0:3,*,*] ;refpixright = data0[2044:2047,*,*] ;;- set to zero the average of ALL pixels ;AVEdata0=avg(data0,2) ;;-set to zero the average of each reference pixel ;mrefpixleft = avg(refpixleft,2) ;mrefpixright = avg(refpixright,2) ;for igroup=0,s[3]-1 do begin & $ ; refpixleft[*,*,igroup]=refpixleft[*,*,igroup]-mrefpixleft[*,*] & $ ; refpixright[*,*,igroup]=refpixright[*,*,igroup]-mrefpixright[*,*] & $ ;endfor ;refpix = (MEAN(refpixleft,DIM=1)+MEAN(refpixright,DIM=1) ) / 2. ;; ;optimal_smooth_fft, refpix, 10.6*510, Smoothed_refpix ;for i=0,s[3]-1 do begin & $ ; optimal_smooth_fft, refpix[0+(i*2048):2047+(i*2048)], 10.6*510, smrp & $ ; Smoothed_Refpix[i*2048:2047+(i*2048)]=smrp & $ ; wait,0.1 ;endfor ;wait,1 ;for ix=0,2047 do begin ; print,ix ; data0[ix,*,*]-=smoothed_refpix ;endfor ;print,'end optimal filtering: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;end ;;------------------------------------------------------------- ;;+ ;; NAME: ;; RAMP_BasicLinFit ;; PURPOSE: ;; Basic linear fit, returns intercept and slope for each pixel ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; ramp_BasicLinFit, data0, fit_params ;; INPUTS: ;; data0; ramp datacube to be corrected, assumes format [2048,2048,Ngroup] ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; fit_params: datacube with dark information, size [2048,2048,2] ;; intercept => [2048,2048,0] ;; slope => [2048,2048,1] ;; COMMON BLOCKS: ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; none ;;; MODIFICATION HISTORY: ;; - Based on clever code exploiting matrix operators from GSFC ;; - Adapted by M. Robberto, 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO RAMP_BasicLinFit, data0, fit_params ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;print,'begin darkcube creation: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;; ;;remove linear trend per pixel; ;;first get the size ; s = size(data0) ; nn = lindgen(s[3]) ;an array of 108 intgers, 0 to 107 ;; ;;then reform data0 to arrange the reads in a time series. ;;The dimension of data0 is now (4194304,108), i.e. pixels values are now ordered in ;;a 2-d matrix with 108 rows and 4M columns ;; ;data0 = reform(data0,s[1]*s[2],s[3],/over) ;; ;; Here starts the ramp fitting procedure, elegantly done exploiting the IDL capabilities of dealing with matrixes. ;; ; sxy = [nn##data0[0:1999,*],nn##data0[2000:*,*]] ; nn##data ;; ;; For obscure IDL reasons, this calculation is faster when done in two parts. ;; ;;sxy is 4M vector, the result of a [88] rows x [4M,88] matrix multiplication. ;;Each element, for each pixel, is the sum of the (i x y_i) products, where i=1..88; the other 3 terms are then obvious… ;; ; sx = total(nn) ; sxx = total(nn^2) ; sy =[(nn*0+1)##data0[0:1999,*],(nn*0+1)##data0[2000:*,*]] ; total(data,2) ;; ;;the slope and intercept can now be calculated using the 4 sums (equations for the linear regression can be found in any book on data analysis, see also a WFC3 ISR by Robberto for derivation and discussion) ;; ; m = (s[3]*sxy-sx*sy)/(s[3]*sxx-sx^2) ;slope ; b = (sy*sxx-sxy*sx)/(s[3]*sxx-sx^2) ;intercept ;; ;; m is the slope and b is the intercept, of each pixel. These are still 1d vectors each 4M values ;; ;;restore the sizes at 2048x2048 ;data0 = reform(data0,s[1],s[2],s[3],/over) ;m = reform(m,s[1],s[2],/over) ;b = reform(b,s[1],s[2],/over) ;fit_params=[[[b]],[[m]]] ;intercept & slope ;print,' end darkcube creation: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ;END ;;------------------------------------------------------------- ;;+ ;; NAME: ;; RAMP_PlotBasicLinFit ;; PURPOSE: ;; Plot the histograms of the twi linear fit parameters, returning alsi gaussian fit results ;; CATEGORY: ;; JWST Data Processing - NIRCam Cryo tests ;; CALLING SEQUENCE: ;; RAMP_PlotBasicLinFit,darkcube,dark_averages ;; INPUTS: ;; fit_params: datacube with dark information, size [2048,2048,2] ;; intercept => [2048,2048,0] ;; slope => [2048,2048,1] ;; KEYWORD PARAMETERS: ;; none ;; OUTPUTS: ;; gaussfit_results: datacube with gaussfit results [5,2] ;; intercept => [*,0] ;; slope => [*,1] ;;Let us remember the 5 values returned by gaussfit,array,aa ;; aa = coefficients of the Gaussian fit: Height, mean, sigma,... ;; aa[0]= the height of the Gaussian ;; aa[1]= the mean ;; aa[2]= the standard deviation ;; aa[3]= the half-width of the 95% conf. interval of the standard ;; mean ;; aa[4]= 1/(N-1)*total( (y-mean)/sigma)^2 ) = a measure of ;; normality ;; COMMON BLOCKS: ;; COMMON SYSTEM_PARAMS,st,DIR_OUT ;; NOTES: ;; none ;;; MODIFICATION HISTORY: ;; - Adapted by M. Robberto, 25 Apr. 2013 ;;- ;;------------------------------------------------------------- ;PRO RAMP_PlotBasicLinFit,fit_params,dark_averages ; window,1 ; !p.multi = [0,1,2] ; histogauss,fit_params[4:2043,4:2043,0],aa1 ;intercept HISTOGAUSS is in the IDLASTRO library at http://idlastro.gsfc.nasa.gov ; histogauss,fit_params[4:2043,4:2043,1],aa2 ;slope ; gaussfit_results = [[aa1],[aa2]] ;intercept, slope fit parameters ;end ;PRO PLOT_RONMAP,RON,RON_AVERAGES, MASK, file ;COMMON SYSTEM_PARAMS,st,DIR_OUT ;COMMON DETECTOR_PARAMS,gain,h,h1mask,h2mask,h3mask,h4mask ;print,' begin RONMAP creation: ',systime(1)-st,' sec ',memory(/high)/1e9,' GB' ; ;;==================================================================== ;;Masks outliers with especially high or low standard deviation ;;Before moving forward with the analysis, we clean the data set. We look for outliers, with threshold set at 4 sigma ; ;;Prepare the output 2x2 window ;; mask outliers with especially high or low stddev ; wset,0 ; !p.multi = [0,2,2] ; ;; ;;We now look at the four “quadrants”, or sectors of the array; their indexes have been previously labeled h1mask…h4mask. ;;We plot the histogram of the standard deviations; the mean of the histogram is the readout noise, in electrons. ;;The histogauss function produces a plot, fits a Gaussian profile and returns the parameters of the fit. ;; ; sig_data=RON ; histogauss,sig_data[h1mask],aa1 ; HISTOGAUSS is in the IDLASTRO library at http://idlastro.gsfc.nasa.gov ; ;;Let us remember the values of aa ;; aa = coefficients of the Gaussian fit: Height, mean, sigma ;; aa[0]= the height of the Gaussian ;; aa[1]= the mean ;; aa[2]= the standard deviation ;; aa[3]= the half-width of the 95% conf. interval of the standard ;; mean ;; aa[4]= 1/(N-1)*total( (y-mean)/sigma)^2 ) = a measure of ;; normality ; ;;Next we isolate the pixels that are within +/-4 sigma from the average readout noise: mask1=1 if the condition is satisfied, ;;0 otherwise. ;;Again, we extract from h1mask the indexes of the pixels with a discrepancy <4sigma (with respect to the average of the quadrant). ;;Mask 1 has values 1 or 0 ; mask1 = abs(sig_data[h1mask]-aa1[1]) lt (4*aa1[2]) ; ;;idl returns 1 if the LT condition is satisfied, 0 otherwise. This procedure extracts from h1mask the values with ;;discrepancy <4sigma (with respect to the full array). Mask 1 has values 1 or 0 ; ;;Repeat for the other 3 sectors. There is here a “counter-reflection” around the y axis to have the pixels oriented normally; ;;this because h2mask and h4mask have been originally defined flipped with respect to the horizontal (fast readout) direction ; ; histogauss,sig_data[h2mask],aa2;_extra={charsize:0.6} ; mask2 = rotate(abs(sig_data[h2mask]-aa2[1]) lt (4*aa2[2]),5) ; histogauss,sig_data[h3mask],aa3 ; mask3 = abs(sig_data[h3mask]-aa3[1]) lt (4*aa3[2]) ; histogauss,sig_data[h4mask],aa4 ; mask4 = rotate(abs(sig_data[h4mask]-aa4[1]) lt (4*aa4[2]),5) ;;...again the “counter-reflection” ; ;;THE RESULTS CAN BE EXTRACTED HERE ; RON_AVERAGES=[[aa1],[aa2],[aa3],[aa4]] ;;The variable mask contains now the indexes of all “good” pixels ; mask = [mask1,mask2,mask3,mask4] ; ;END ;DIR_OUT = '~/FUNCTIONAL/JWST/NIRCAM/Studies/2013/2013.NIRCAM.Noise/Results/' ;filebasename = '487' ;; ;;set detector parameters ;SET_DETECTOR_PARAMS ;; ;;get ready to find files ; DATA_PATH= '/Volumes/witserv' ; DATA_PATH = DATA_PATH+'/witserv/data14/nrc/nrc_cryo2' ; OBS_ID = 'NRC_2D6-DARK' ; DETECTOR = '486' ; FIND_FILES,DATA_PATH,OBS_ID,DETECTOR,FILES PRO PRINT_RESULTS,fileinfo,darkcube,ron, dark_averages,ron_averages ; ; writefits,fileinfo[0]+'/'+fileinfo[1]+'/'+fileinfo[2]+'_darklinfit.fits',darkcube writefits,fileinfo[0]+'/'+fileinfo[1]+'/'+fileinfo[2]+'_RON.fits',ron openw,1,fileinfo[0]+'/'+fileinfo[1]+'/'+fileinfo[2]+'_RONresults.txt' printf,1,RON_AVERAGES close,1 openw,2,fileinfo[0]+'/'+fileinfo[1]+'/'+fileinfo[2]+'_DARKresults.txt' printf,2,dark_averages close,2 END pro openeps,nomefile on_error,2 print,'out to ps on the file:', nomefile set_plot,'ps' device,bits=8,filename=nomefile,/ENCAPSULATED end pro closeps on_error,2 device,/close set_plot,'x' end pro analyze_dark COMMON SYSTEM_PARAMS,st,DIR_OUT OBS_ID = 'NRC2D6-DARK_' DETECTOR = '487' cd, DIR_OUT ; OBS_ID = 'NRC_2D6-DARK' ; DETECTOR = '486' files = FILE_SEARCH(OBS_ID+'*_'+DETECTOR+'_*DARKresults.txt',count=nfiles) ; ;SORT THE FILES ACCORDING TO THEIR OBS_ID NUMBER=STRARR(N_ELEMENTS(files)) for ij=0,N_ELEMENTS(files)-1 do begin & $ ; ij=0 & file=files[ij] & $ from = STRLEN(OBS_ID) & $ to = STREGEX(file,'_'+DETECTOR) & $ number[IJ] = strmid(file,from,to-from) & $ endfor number(WHERE(strlen(number) EQ 1)) = '0'+number(WHERE(strlen(number) EQ 1)) print,number FILES = FILES(SORT(NUMBER)) ; ; alldarks=fltarr(2,N_ELEMENTS(files)) for ij=0,N_ELEMENTS(files)-1 do begin & $ READCOL, FILES[ij],Peaks,Means,STDevs,mean2sigmaerror,normality,FORMAT='(F,F,F,F,F)' & $ alldarks[*,ij]=[means[1],STDevs[1]] & $ endfor plot,alldarks[0,*],psym=3 oploterr,alldarks[0,*],alldarks[1,*] end PRO FOURIER ; ;FOURIER ANALYSYS ;For the Fourier Analysis, also the 4 pixels nearest to each outlier ;For better cleanup, we remove the 4 pixels adjacent to each outlier. ;This is simply done by shifting the bad pixel mask of +/-1 in all directions mask *= shift(mask,-1,0)*shift(mask,1,0)*shift(mask,0,-1)*shift(mask,0,1) ;and back to single window !p.multi = 0 ;wset,5 ;finally take data0 and set to 0 the values of the pixels flagged as bad, frame by frame. for i=0,s[3]-1 do data0[*,*,i] *= mask ;apply the mask to filter out the bad data. ;The figure below shows the bottom-left 1Mx1M corner of the mask, with two sectors: tvscl,mask[0:1023,0:1023] ; ; ;Fill in for the masked pixels ;Uses the nmean data from the +/-12 pixels n time domain, to avoid artifacts in the power spectrum ;The pixels set to 0 in data0 will create problems when we do the Fourier Transforms. ;The idea here is to fill in by using the mean of the +/- 12 pixels in the readout sequence (time domain) for i=0,3 do begin & $; This fills in masked pixels with the mean of data from +/- 12 pix in the time domain. ;(helps avoid artifacts in the power spectra) ;The index i labels the quadrant, so for quadrant 1 (i=0) we have [0:511,*]. The bad pixels have index h h = where(mask[i*512:(i+1)*512-1,*] eq 0,nh) & $ ; ;for the current quadrant, we run through the entire ramp for k=0,s[3]-1 do begin & $ mn = fltarr(nh) & $ nn = fltarr(nh) & $ ;mn sums over the values of the +/- 12 pixels. Some of them will be zero, so to find the average we will need ;to divide by the numbers of pixels different from 0. They are counted by nn, a counter (1 or 0) that ticks only ;if the pixel is good (i.e. non 0). It is the same operation, but the NE command makes the second statement a logical one for j=-12,12 do begin & $ mn += (data0[i*512:(i+1)*512-1,*,k])[h-j] & $ nn += (data0[i*512:(i+1)*512-1,*,k])[h-j] ne 0 & $ endfor & $ ;find the average dividing by the number of good pixels: mn /= (nn>1) & $ ;reorganize the data substituting the average values at the positions of the bad pixels; the indexes are arranged to reproduce the [512,2048] sector for j=0L,nh-1 do data0[(h[j] mod (s[1]/4))+(i*512),h[j]/(s[1]/4),k] = mn[j] & $ endfor & $ endfor ; ;out of the loop on the quadrants we get a new time print,'mark3: ',systime(1)-st ; ; ;Set the spatial average of each output to zero ; ;We are moving closer to the Fourier analysis. At the moment we have that each pixel has been fitted ;by a linear ramp and subtracted; this has facilitated finding the outliers. New we need to go spatial ;across the frame to have time sequences that have zero mean. ; set means to 0.0 for each output (4) for each frame (108) ;subtract to each sector its own average to have spatial average to zero for j=0,s[3]-1 do begin & $ for i=0,3 do begin & $ frame = data0[i*512:(i+1)*512-1,*,j] & $ h = where(frame ne 0) & $ frame[h] -= mean(frame[h]) & $ data0[i*512:(i+1)*512-1,*,j] = frame & $ endfor& $ endfor ; ;data0 now has zero average, quadrant by quadrant, for each frame. print,'mark4: ',systime(1)-st ;5.5 Reform data ;From [2048,2048,n] to [512,4,2048,n], ; then reorder to [512,2048,n,4], ; then rearrange quadrants 1 and 3 of the array, so that the pixels are oriented according to the readout directions. ; then add padding rows ;Sectors 2 and 4 need to be flipped to have them in sync with quadrants 1 and 3. Start with sector 2: ; reform the data, add padding on the rows, and take FFT ;let’s start with the creation of the reverted indexes: rev = reverse(lindgen(s[1]/4)) ; ;and prepare the datacube. First, reform data0 from [2048,2048,n] to [512,4,2048,n] data0 = reform(data0,s[1]/4,4,s[2],s[3],/over) ; ;then reform again to [512,2048,n,4]. Piece of cake with IDL: data0 = transpose(data0,[0,2,3,1]) ; ;now use the reverted indexes to flip the second and fourth sector data0[*,*,*,1] = data0[rev,*,*,1] data0[*,*,*,3] = data0[rev,*,*,3] ; ; ;Add pad=12 pixels at the end of each row pad=12 ;A final extra step: we need to expand the x size of data0 to add 12 pixels cycles, ;needed each time we move to the next line. There are the padding rows; the data look ;better in the Fourier space. ; ;First modify data0 to a fatter datacube: 512->524, i.e. [524,2048,n,4] data0 = [data0,fltarr(pad,s[2],s[3],4)] ; ;We need to put something into these extra pixels. ;For each sector [0-3], frame [0-87] and row [0:2046] we insert the average of the last 12 pixels ;of each row and the first 12 pixels of next rows. for k=0,3 do for j=0,s[3]-1 do for i=0L,s[2]-2 do $ data0[512:*,i,j,k] = total(data0[500:511,i,j,k])/24+total(data0[0:11,i+1,j,k])/24 ; fixed minor bug here (i+1) ; ;where we go up to 2046 to jump at 2047 at a valid row. ; ;At this point we can reform again the data to have a [1M, 108,4] datacube. ;We will work on the 1M array as a 1-d signal to be analyzed with Fourier. data0 = reform(data0,(s[1]/4+pad)*s[2],s[3],4,/over) print,'mark5: ',systime(1)-st ; ; ; ;Fourier transform ;========================================= ;;Overwriting the data; ;pay attention to the normalization factor SQRT(nr.of pixels=524*2028) ; data0 = fft(data0,dim=1,/overwrite)*sqrt((s[1]/4+pad)*s[2]) print,'mark6: ',systime(1)-st ;We can now plot the FFT for a e.g. the first sector of the first frame plot,data0[*,0,0] ; ; ;5.8 Calculation of the Power and Cross correlation spectra ; Calculate power and cross power for each output (RAW DATA). ;.. if (option) then begin ;Calculate here the Power spectrum, one for each sector; it is calculated as a mean over the 108 frames, ;since the total has a keyword 2, which means sum over the second dimension. These are 1-d arrays of ;512x2048 elements that we can plot scipix_n = 512L refpix_r = 0L row = 512L+pad+(refpix_r+2)*(512/scipix_n) ; LONG 716 = 512 + 12 + (4+2)*(512/16) f = dindgen(2048L*row)/2048L/row ; frequency array ; DOUBLE = Array[1466368] f5 = f*1e5 ;set the highest frequency is at 100KHz (10ms/frame) f0 = dindgen(2048L*512L)/2048L/512L ; frequency array for normal pixels only (ignoring all gaps and references); f05 = f0*1e5 q1_0 = fltarr(2048L*row) q2_0 = fltarr(2048L*row) q3_0 = fltarr(2048L*row) q4_0 = fltarr(2048L*row) q1_0 += total(abs(data0[*,*,0])^2,2)/s[3] q2_0 += total(abs(data0[*,*,1])^2,2)/s[3] q3_0 += total(abs(data0[*,*,2])^2,2)/s[3] q4_0 += total(abs(data0[*,*,3])^2,2)/s[3] print,'mark7: ',systime(1)-st !y.title = 'Power (e!u2!n) [Raw, single ended]' density,/ylog,f*1e5,q1_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 1: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q1_0)/8.031746),2) density,/ylog,f*1e5,q2_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 2: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q2_0)/8.031746),2) density,/ylog,f*1e5,q3_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 3: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q3_0)/8.031746),2) density,/ylog,f*1e5,q4_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 4: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q4_0)/8.031746),2) density,/ylog,f*1e5,q1_0,xran=[0,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 1: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q1_0)/8.031746),2) density,/ylog,f*1e5,q2_0,xran=[0,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 2: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q2_0)/8.031746),2) density,/ylog,f*1e5,q3_0,xran=[0,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 3: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q3_0)/8.031746),2) density,/ylog,f*1e5,q4_0,xran=[0,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 4: sqrt(!12<!3P!12>!3/8.031746) = '+strtrim(sqrt(mean(q4_0)/8.031746),2) ;The figure on the left shows the power spectrum of the first sector measured single ended, ;There is a strong 1/f component that extends up to about 3KHz. On the right the same figure for the reference output, ;quite noisy as well. ;Calculate the Cross correlation spectrum; with 4 sectors, we have 6 spectra, one for each pair of sectors. ;Again, they are averaged over 108 ramps if Cross_correlation EQ 1 THEN BEGIN c12_0 = fltarr(2048L*row) c13_0 = fltarr(2048L*row) c14_0 = fltarr(2048L*row) c23_0 = fltarr(2048L*row) c24_0 = fltarr(2048L*row) c34_0 = fltarr(2048L*row) c12_0 += total(data0[*,*,1]*conj(data0[*,*,0]),2)/s[3] c13_0 += total(data0[*,*,2]*conj(data0[*,*,0]),2)/s[3] c14_0 += total(data0[*,*,3]*conj(data0[*,*,0]),2)/s[3] c23_0 += total(data0[*,*,2]*conj(data0[*,*,1]),2)/s[3] c24_0 += total(data0[*,*,3]*conj(data0[*,*,1]),2)/s[3] c34_0 += total(data0[*,*,3]*conj(data0[*,*,2]),2)/s[3] ; density,/ylog,f*1e5,c12_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 1x2' ; density,/ylog,f*1e5,c13_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 1x3' ; density,/ylog,f*1e5,c14_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 1x4' ; density,/ylog,f*1e5,c23_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 2x3' ; density,/ylog,f*1e5,c24_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 2x4' ; density,/ylog,f*1e5,c34_0,xran=[8e-7,0.5]*1e5,psym=3,yra=[1e1,1e7],charsiz=1,xsty=1,/dlog,/xlog,xminor=9,ct=-1,dsize=[2048,2048]/4,title=strmid(file[0],0,18)+'*: Output 3x4' ; ; ; ; ; ; 5.9 Calculate the spectrum of the correlation matrix, i.e. the complex coherence matrix ; Calculate correlation matrix ; if (option) then begin h = where(f5 ne 0 and f5 lt 2e3,nh) mqq0 =[[1.0 ,total(c12_0[h]/sqrt(q1_0[h]*q2_0[h]))/nh,total(c13_0[h]/sqrt(q1_0[h]*q3_0[h]))/nh,total(c14_0[h]/sqrt(q1_0[h]*q4_0[h]))/nh],$ [total(c12_0[h]/sqrt(q2_0[h]*q1_0[h]))/nh,1.0 ,total(c23_0[h]/sqrt(q2_0[h]*q3_0[h]))/nh,total(c24_0[h]/sqrt(q2_0[h]*q4_0[h]))/nh],$ [total(c13_0[h]/sqrt(q3_0[h]*q1_0[h]))/nh,total(c23_0[h]/sqrt(q3_0[h]*q2_0[h]))/nh,1.0 ,total(c34_0[h]/sqrt(q3_0[h]*q4_0[h]))/nh],$ [total(c14_0[h]/sqrt(q4_0[h]*q1_0[h]))/nh,total(c24_0[h]/sqrt(q4_0[h]*q2_0[h]))/nh,total(c34_0[h]/sqrt(q4_0[h]*q3_0[h]))/nh, 1.0 ]] endif ;And the result is print,float(mqq0); ; 1.00000 0.545643 0.558868 0.564672 ; 0.545643 1.00000 0.591492 0.594834 ; 0.558868 0.591492 1.00000 0.611869 ; 0.564672 0.594834 0.611869 1.00000 print,'mark8: ',systime(1)-st ; ; ;5.23 Row Reference pixel subtraction. data4 = float(fft(data0,dim=1,1,/overwrite))/sqrt((s[1]/4+pad)*s[2]) print,'mark15: ',systime(1)-st stop data4 = reform(data4,(s[1]/4+pad),s[2],s[3],4,/over) data4 = data4[0:511,*,*,*] data4[*,*,*,1] = data4[rev,*,*,1] data4[*,*,*,3] = data4[rev,*,*,3] data4 = transpose(data4,[0,3,1,2]) data4 = reform(data4,s[1],s[2],s[3],/over) ; Row Reference pixel subtraction. ; Extract corrected reference pixels and correlated with data at low freq. rpix = [0,1,2,3] ; [0,1,2,3,2044,2045,2046,2047] nref = n_elements(rpix) even = findgen(nref/2)*2 h1 = [lindgen(s[2]/2),lindgen(s[2]/2)+(s[2]*524)-s[2]/2] ;0...1023: 2 bottom rows? h2 = [lindgen(s[2]/2)+(s[2]*524)/2,lindgen(s[2]/2)+(s[2]*524)/2-s[2]/2] ; 2 top rows...? ref1a = total(data4[rpix,*,*],1)/nref ;average of the 4 leftmost columns [2048, 108] ref2a = (total(data4[rpix[even],*,*],1)-total(data0[rpix[even+1],*,*],1))/nref ;average of difference pairs column [0,2] - column [1,3] : odd/even correction ref1a = fft(ref1a,dim=1,/overwrite)*sqrt(s[2]) ;fft of the refpix signal ref2a = fft(ref2a,dim=1,/overwrite)*sqrt(s[2]) ;fft of the odd/even pair difference rat0ref1a = total(data4[h1,*,0]*conj(ref1a),2)/total(abs(ref1a)^2,2) rat1ref1a = total(data4[h1,*,1]*conj(ref1a),2)/total(abs(ref1a)^2,2) ;rat2ref1a = total(data5[h1,*,2]*conj(ref1a),2)/total(abs(ref1a)^2,2) ;rat3ref1a = total(data5[h1,*,3]*conj(ref1a),2)/total(abs(ref1a)^2,2) rat0ref2a = total(data4[h2,*,0]*conj(ref2a),2)/total(abs(ref2a)^2,2) rat1ref2a = total(data4[h2,*,1]*conj(ref2a),2)/total(abs(ref2a)^2,2) ;rat2ref2a = total(data5[h2,*,2]*conj(ref2a),2)/total(abs(ref2a)^2,2) ;rat3ref2a = total(data5[h2,*,3]*conj(ref2a),2)/total(abs(ref2a)^2,2) ; ; ;5.24 Subtract reference pixel corrections for low frequencies; ; ; Subtract reference pixel corrections for low frequencies. for i=0,s[3]-1 do data4[h1,i,0] -= float(rat0ref1a)*ref1a[*,i] for i=0,s[3]-1 do data4[h1,i,1] -= float(rat1ref1a)*ref1a[*,i] ;for i=0,s[3]-1 do data5[h1,i,2] -= float(rat2ref1a)*ref1a[*,i] ;for i=0,s[3]-1 do data5[h1,i,3] -= float(rat3ref1a)*ref1a[*,i] ; for i=0,s[3]-1 do data4[h2,i,0] -= float(rat0ref2a)*ref2a[*,i] ; for i=0,s[3]-1 do data4[h2,i,1] -= float(rat1ref2a)*ref2a[*,i] ;for i=0,s[3]-1 do data5[h2,i,2] -= float(rat2ref2a)*ref2a[*,i] ;for i=0,s[3]-1 do data5[h2,i,3] -= float(rat3ref2a)*ref2a[*,i] rpix = [2047,2046,2045,2044] ; [0,1,2,3,2044,2045,2046,2047] nref = n_elements(rpix) even = findgen(nref/2)*2 h1 = [lindgen(s[2]/2),lindgen(s[2]/2)+(s[2]*(512+pad))-s[2]/2] h2 = [lindgen(s[2]/2)+(s[2]*524)/2,lindgen(s[2]/2)+(s[2]*524)/2-s[2]/2] ref1a = total(data4[rpix,*,*],1)/nref ref2a = (total(data4[rpix[even],*,*],1)-total(data4[rpix[even+1],*,*],1))/nref ref1a = fft(ref1a,dim=1,/overwrite)*sqrt(s[2]) ref2a = fft(ref2a,dim=1,/overwrite)*sqrt(s[2]) ;rat0ref1a = total(data5[h1,*,0]*conj(ref1a),2)/total(abs(ref1a)^2,2) ;rat1ref1a = total(data5[h1,*,1]*conj(ref1a),2)/total(abs(ref1a)^2,2) ; rat2ref1a = total(data5[h1,*,2]*conj(ref1a),2)/total(abs(ref1a)^2,2) ; rat3ref1a = total(data5[h1,*,3]*conj(ref1a),2)/total(abs(ref1a)^2,2) ;rat0ref2a = total(data5[h2,*,0]*conj(ref2a),2)/total(abs(ref2a)^2,2) ;rat1ref2a = total(data5[h2,*,1]*conj(ref2a),2)/total(abs(ref2a)^2,2) ; rat2ref2a = total(data5[h2,*,2]*conj(ref2a),2)/total(abs(ref2a)^2,2) ; rat3ref2a = total(data5[h2,*,3]*conj(ref2a),2)/total(abs(ref2a)^2,2) end