;pro Find_Leaky_Pixels 
;
;PURPOSE:
;	To try to find the pixels that appear to leak in flat frame images 
;	and 'get leaked into' in dark images.  These pixels are usually at the
;	center of a cross pattern and have a very large difference with respect
;	to the pixels above, below, to the left, and to the right of them.
;
;	The method of finding them will be to take the difference between
;	a frame and the same frame shifted up, down, left, and right by 1 pixel
;	and make a cut on the difference of all values.
;
;INPUTS:
;
;OUTPUTS:
;
;KEYWORDS:
;       ROOTDIR: 
;         The Directory holding the directories of Raw files
;       DATE:
;         The Date during which they were taken.  Also the subdirectory that 
;         the files are in.
;       REDUCEDDIR:
;         The directory where the processed images and plots will be placed in.
;       BLOCKLENGTH:
;         An offset for files that were written improperly.  The readu 
;         function reads the values with this offset in place.
;       OBJECTNAME:
;         The string that indicates what files are being sought.  The filenames
;         should begin with this string ('Dark', 'Raw', etc.).
;       NREADS:
;         The number of reads (NAXIS3) that are present in the file.  This
;         is also a string in the filename that will be used as a regular
;         expression in searching for matched files.
;       FIRSTREAD:
;         The first read to be used in the difference 
;             Diff = LastRead - FirstRead
;       LASTREAD: 
;         The last read to be used in the difference
;       THISFILTER:
;         The filter through which the files were taken. ('I', 'G', or 'Y')
;	OVERRIDE: 
;	  Do the processing even if the output file already exists
;	ALLFILES:
;	  1 - Process all files matching the #Reads, Filter, and Object
;	  0 - Only process one file (the first by default)
;**************************************************************************

pro Find_Leaky_Pixels, RootDir=RootDir, Date=Date, $
         ReducedDir = ReducedDir, BlockLength = BlockLength, $
         ObjectName=ObjectName, NReads = NReads, ThisFilter = ThisFilter,$
         OverRide = OverRide, FirstRead = FirstRead, LastRead = LastRead, $
	 Threshold = Threshold

  ;Include KeywordStruct.pro file with all the defaults for keywords
  @KeywordStruct.pro

  ;Parameters
  If Not keyword_set(Threshold) then Threshold = 100

  ;Make the directories if they don't exist
  File_Mkdir, LeakyDir & File_Mkdir, HotDir
 
  ;Start in the RootDir/Date directory
  cd, Rootdir+Date

  ;Get all of the Dark Files for this Number of Reads
  If ObjectName eq 'Dark' then begin
    RawFiles = File_Search('Dark*'+strtrim(NReads,2)+'_Reads*.fits')
  EndIf else if ObjectName eq 'Flat' then begin
    NReads = 2
    RawFiles = File_Search('Flat*2*Reads*.fits')
  Endif 
   
  If RawFiles(0) eq '' then begin
     print, 'Found No Files for input parameters' 
     stop
  EndIf

  ;Remove Files that don't match the filter we want
  RawFiles = Return_File_List(RawFiles, ThisFilter = ThisFilter)
  if AllFiles then NumFiles = N_elements(RawFiles) else NumFiles = 1 

  ;Get a Few Kewyords
  Fits_Read,  RawFiles(0), NoData, FitsHeader, /header_only
  Naxis1     = long(sxpar(FitsHeader, 'NAXIS1'))
  Naxis2     = long(sxpar(FitsHeader, 'NAXIS2'))
  TotalReads = long(sxpar(FitsHeader,'NAXIS3'))
  ArrSize = long(Naxis1*Naxis2)  

  ;Indices with skipping of reference pixels and channel 0
  RPix = 8
  Ch0W = 128
  PosThreshold = 10000.
  NegThreshold = -7000.
  XSizeM = Naxis1-Ch0W-RPix/2-2
  YSizeM = Naxis2-RPix-2

  ;Form an array that will keep track of how many times this pixel was leaky
  LeakyPixCenMask = bytarr(Naxis1, Naxis2)
  HotPixCenMask   = bytarr(Naxis1, Naxis2)
  ;Also form arrays to track nearest neighbors so that averaging can take place
  LeakyPixNNMask  = bytarr(Naxis1, Naxis2)
  HotPixNNMask    = bytarr(Naxis1, Naxis2)

  ;Form arrays to keep average values
  LeakyPixVals = fltarr(Naxis1, Naxis2)
  HotPixVals   = fltarr(Naxis1, Naxis2)

  ;FileNames and headers for masks and value leaky files
  If ObjectName eq 'Flat' then NReads = 2
  LeakyMaskFileName  = LeakyDir+'LeakyPixelMaskFor_'+Strtrim(NumFiles,2)+'_'$
		  +ObjectName+'_'+ThisFilter+'_Files_'+$
		  '_'+Strtrim(NReads,2)+'Reads.fits'
  LeakyValsFileName = LeakyDir+'LeakyPixelValuesFor_'+Strtrim(NumFiles,2)+'_'$
                  +ObjectName+'_'+ThisFilter+'_Files_'+$
                  '_'+Strtrim(NReads,2)+'Reads.fits'

  MkHdr, LeakyHeader, LeakyPixVals
  FxAddPar, LeakyHeader, 'DIFTHRESH', NegThresHold, $
	'Diff. Threshold between center and nearest neighbors'
  For FileNum = 0, NumFiles - 1 do begin 
    FxAddPar, LeakyHeader, 'FILE'+Strtrim(FileNum,2) , RawFiles(FileNum), $
	'Name of Files used to draw map'
  Endfor
  FxAddPar, LeakyHeader, 'NUMLEAKY', 0, $
	'Number of pixels THRESHOLD below nearest neighbors'
 
  ;FileNames and headers for masks and value leaky files
  HotMaskFileName = HotDir+'HotPixelMask_'+Strtrim(NumFiles,2)+'_'$
                   +ObjectName+'_'+ThisFilter+'_Files_'+$
                   '_'+Strtrim(NReads,2)+'Reads.fits'

  HotValsFileName = HotDir+'HotPixelValues_'+Strtrim(NumFiles,2)+'_'$
		   +ObjectName+'_'+ThisFilter+'_Files_'+$
                   '_'+Strtrim(NReads,2)+'Reads.fits'
  MkHdr, HotHeader, HotPixVals
  FxAddPar, HotHeader, 'DIFTHRESH', PosThresHold, $
        'Diff. Threshold between center and nearest neighbors'
  For FileNum = 0, NumFiles - 1 do begin
    FxAddPar, HotHeader, 'FILE'+Strtrim(FileNum,2) , RawFiles(FileNum), $
        'Name of Files used to draw map'
  Endfor
  FxAddPar, HotHeader, 'NUMIPC', 0, $
        'Number of pixels THRESHOLD above nearest neighbors'

  ;Open fits files for leaky and hot values
  LeakyPos = Fits_Open_DataCube(LeakyValsFileName, LeakyFCB, LeakyHeader, 'Write')
  HotPos   = Fits_Open_DataCube(HotValsFileName, HotFCB, HotHeader, 'Write')

  ;***************************************************************************
  ;Begin the main loop for the files and read numbers
  FrameNum = 0
  For FileNum = 0, NumFiles -1 do begin
   
    ;Verbose
    print, 'Reading frame: ' + strtrim(FrameNum,2) 
    print, 'For file '+strtrim(FileNum,2)+' of '+strtrim(NumFiles,2)+ $
	   ' : '+RawFiles(FileNum)
      
    ;Open up the raw image whether dark, flat, or object
    RawPos = Fits_Open_DataCube(RawFiles(FileNum), RawFCB, RawHeader, 'Read')
    
    Frame = long(Fits_Read_DataCube_Region(RawFiles(FileNum), RawFCB, RawHeader, $
		0, Naxis1 -1, 0, Naxis2-1, 0, 0))

    RawClose = Fits_Close_DataCube(RawFCB)
    delvarx, RawFCB

    ;****************************************************************************
    ;Form difference frames. Waste of memory, but ease of use with where function
    FrameUpOne    = LonArr(XSizeM, YSizeM)
    FrameDownOne  = LonArr(XSizeM, YSizeM)
    FrameRightOne = LonArr(XSizeM, YSizeM)
    FrameLeftOne  = LonArr(XSizeM, YSizeM) 

    ;Do the differences
    FrameUpOne(*,*) = $
	long(Frame(1+Ch0W:Naxis1-RPix/2-2, 1+RPix/2:Naxis2-RPix/2-2)) - $
	long(Frame(1+Ch0W:Naxis1-RPix/2-2, 2+RPix/2:Naxis2-RPix/2-1))

    FrameDownOne(*,*) = $
	long(Frame(1+Ch0W:Naxis1-RPix/2-2, 1+Rpix/2:Naxis2-RPix/2-2)) - $
	long(Frame(1+Ch0W:Naxis1-RPix/2-2, 0+RPix/2:Naxis2-RPix/2-3))

    FrameLeftOne(*,*) = $
	long(Frame(Ch0W+1:Naxis1-RPix/2-2 , 1+RPix/2:Naxis2-RPix/2-2)) - $
	long(Frame(Ch0W+2:Naxis1-RPix/2-1 , 1+RPix/2:Naxis2-RPix/2-2))
 
    FrameRightOne(*,*) = $
	long(Frame(Ch0W+1:Naxis1-RPix/2-2 , 1+RPix/2:Naxis2-RPix/2-2)) - $
        long(Frame(Ch0W+0:Naxis1-RPix/2-3 , 1+RPix/2:Naxis2-RPix/2-2))

    ;Form a mask showing the number of differences that are greater than threshold
    FrameBadMask = IntArr(XSizeM, YSizeM)

    ;Find pixels above neighbors
    FrameBadMask(where(FrameUpOne gt PosThreshold))    += 1
    FrameBadMask(where(FrameDownOne gt PosThreshold))  += 1
    FrameBadMask(where(FrameLeftOne gt PosThreshold))  += 1
    FrameBadMask(where(FrameRightOne gt PosThreshold)) += 1

    ;Find pixels below neighbors
    FrameBadMask(where(FrameUpOne lt NegThreshold))    -= 1
    FrameBadMask(where(FrameDownOne lt NegThreshold))  -= 1
    FrameBadMask(where(FrameLeftOne lt NegThreshold))  -= 1
    FrameBadMask(where(FrameRightOne lt NegThreshold)) -= 1

    ;Indices where center pixel was PosThreshold above nearest neighbors; reform 
    ;indices for the full array
    PosCrPix  = where(FrameBadMask eq 4)
    XPosCrPix = (PosCrPix mod XSizeM) + Ch0W + 1 
    YPosCrPix = (PosCrPix/XSizeM)+RPix/2 + 1
    PosCrPix  = XPosCrPix+long(YPosCrPix)*Naxis2

    ;Now form all the Indices of the nearest neighbors
    PosCrPixNN = [PosCrPix+Naxis1-1, PosCrPix+Naxis1, PosCrPix+Naxis1+1,$
		  PosCrPix-1       , PosCrPix       , PosCrPix+1,$
		  PosCrPix-Naxis1-1, PosCrPix-Naxis1, PosCrPix-Naxis1+1]

    ;Indices where center pixel was NegThreshold below nearest neighbors
    NegCrPix  = where(FrameBadMask eq -4)
    XNegCrPix = (NegCrPix mod XSizeM) + Ch0W + 1             
    YNegCrPix = (NegCrPix/XSizeM)+RPix/2 + 1
    NegCrPix  = XNegCrPix+long(YNegCrPix)*Naxis2
   
    ;Now forma all the Indices of the nearest neighbors
    NegCrPixNN = [NegCrPix+Naxis1-1, NegCrPix+Naxis1, NegCrPix+Naxis1+1,$
                  NegCrPix-1       , NegCrPix       , NegCrPix+1,$
                  NegCrPix-Naxis1-1, NegCrPix-Naxis1, NegCrPix-Naxis1+1]

    ;Increment the mask 
    LeakyPixCenMask(NegCrPix) += 1
    HotPixCenMask(PosCrPix)   += 1

    ;Also form arrays to track nearest neighbors so that averaging can take place
    LeakyPixNNMask(NegCrPixNN) +=1
    HotPixNNMask(NegCrPixNN)   +=1

    ;Increment the values where necessary
    LeakyPixVals(NegCrPixNN) = LeakyPixVals(NegCrPixNN) + float(Frame(NegCrPixNN))
    HotPixVals(PosCrPixNN)   = HotPixVals(PosCrPixNN) +   float(Frame(PosCrPixNN))

  EndFor

  ;Average the frames over the number of times hotpixels occured
  HotPixNZ = where(HotPixNNMask ne 0)
  HotPixVals(HotPixNZ) = HotPixVals(HotPixNZ)/HotPixNNMask(HotPixNZ)
  LeakyPixNZ = where(LeakyPixNNMask ne 0)
  LeakyPixVals(LeakyPixNZ) = LeakyPixVals(LeakyPixNZ)/LeakyPixNNMask(LeakyPixNZ)

  ;Write the Values
  HotPixWrite = Fits_Append_DataCube(HotFCB, HotPixVals)
  LeakyPixWrite = Fits_Append_DataCube(LeakyFCB, LeakyPixVals)

  ;***********************************************************
  ;Close the Files
  HotPixClose = Fits_Close_DataCube(HotFCB)
  LeakyPixClose = Fits_Close_DataCube(LeakyFCB)

  ;Write the number of leaky pixels to the header
  LeakyHeader = HeadFits(LeakyValsFileName)
  FxAddPar, LeakyHeader, 'NUMLEAKY', N_Elements(NegCrPix)
  ModFits,  LeakyValsFileName, 0, LeakyHeader

  ;Change the header slightly for the mask
  FxAddPar, LeakyHeader, 'BITPIX', 8
  Fits_Write, LeakyMaskFileName, LeakyPixCenMask, LeakyHeader

  ;Write the number of hot pixels to the header
  HotHeader = HeadFits(HotValsFileName)
  FxAddPar, HotHeader, 'NUMIPC', N_Elements(PosCrPix)
  ModFits, HotValsFileName, 0, HotHeader

  ;Change the header slightly for the mask 
  FxAddPar, HotHeader, 'BITPIX', 8 
  Fits_Write, HotMaskFileName, HotPixCenMask, HotHeader

  SampleDark = 0
  If SampleDark then begin 
    NReads = 30
    DarkFiles = File_Search('Dark*'+strtrim(NReads,2)+'_Reads*.fits')
  EndIf
 
  stop  

  ;*******************************************************************OUTPUT
  ;Form a string designating what type of Bad Pixel test was run
  ;and what date it's from, etc. 
  BadPixStr = 'DeadPixelMap_'+strtrim(NumFiles,2)+$+
            ObjectName+'s_Threshold_'+strtrim(Threshold,2)+$
            '_'+Date

  ;Make a Histogram of the Number of times that the pixel did not meet the 
  ;threshold
 
  ;Write a .txt file that shows the pixel number and how many times it was 
  ;flagged, sorted from highest to least
  TextFile = 1
  If TextFile then begin

    BadPixNoCh0NoRef = BadPix(128:Naxis2-5,4:Naxis2-5)	;Skip Ch0 and ref pixels
    XSize = long((size(BadPixNoCh0NoRef))[1])
    YSize = long((size(BadPixNoCh0NoRef))[2])
    DeadPixInd = where(BadPixNoCh0NoRef eq NumFiles*(TotalReads-1))
    DeadPixInd = DeadPixInd(reverse(sort(DeadPixInd)))
    DeadPix = BadPixNoCh0NoRef(DeadPixInd)
    RowNum  = DeadPixInd/XSize+4
    ColNum  = (DeadPixInd mod XSize)+128

    get_lun, BadPixTxtFile
    openw,   BadPixTxtFile, BadPixDir+BadPixStr+'.txt'
    printf,  BadPixTxtFile, FORMAT = '(%"%s\t%s\t%s\t%s")',$
	'Row', 'Column', 'Pixel Number', 'Times Flagged'
    for PixInd = 0L, N_Elements(DeadPix)-1 do begin
    printf, BadPixTxtFile, FORMAT = '(%"%I\t%I\t%I\t%I")', $
	RowNum(PixInd), ColNum(PixInd), $
	DeadPixInd(PixInd), DeadPix(PixInd)
  endfor

  close,    BadPixTxtFile
  free_lun, BadPixTxtFile

EndIf


stop

end
