;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Lance Simms, Stanford University 2009
;pro Find_Dead_Pixels 
;
;PURPOSE:
;	To try to find the pixels that do not change in signal at all during illumination.
;     
;	The method of finding them will be to take the difference between the first and 
;       last read of a flat field exposure, where the luminance should cause the signal 
;       to rise significantly, and flag pixels that have not accumulated a value that is 
;       3sigma above 0.
;
;INPUTS:
;   FITSFILENAMEORLIST: string
;       MODE = 0 or MODE = 1
;	The path to the fits file that should be used to find the dead pixels.
;       Ideally, this should be a flat field.
;       MODE = 2
;       The path to the file that contains the list of fits files that will be used
;       to generate the mask.
;OUTPUTS:
;   FILE 1: 
;     KeyStrDeadDir+'DeadPix_'+KeyStr.RawObjectKey+'_'+KeyStr.Date+'_'+KeyStr.ThisFilter+'.fits'
;       This file will be a fits image that shows 1s where the DeadPix are and 
;       0s elsewhere.
;
;KEYWORDS:
;       DATE:
;         The Date during which they were taken.  Also the subdirectory that 
;         the files are in.
;       OFFSET:
;         An offset for files that were written improperly.  The readu 
;         function reads the values with this offset in place.
;       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.
;       THISFILTER:
;         The filter through which the files were taken. ('I', 'G', or 'Y')
;	OVERRIDE: 
;	  Do the processing even if the output file already exists
;	BATCHMODE: 
;	  0 - Process only the file specified
;	  1 - Process all of the files in the LeakyFileList
;	ALLFILES:
;	  1 - Process all files matching the #Reads, Filter, and Object
;	  0 - Only process one file (the first by default)
;	MODE:
;	  0 - Just plot a dead pixel and its 4 nearest neighbors
;	  1 - Search for all of the dead pixels in the file
;	ROW: int
;	  If MODE = 0, this will be the row of the ead pixel
;	COL: int
;	  If MODE = 0, this will be the column of the dead pixel
;	USEREF: int
;	  0 - Don't subtract the reference pixels
;	  1 - Subtract the reference pixels
;	ADDBIAS: int
;	  0 - Don't add the bias back to the data cube 
;	  1 - Add the bias back to the data cube if it's a median file
; 
;EXAMPLES:
;  GENERATE THE DEAD MASK FROM INDIVIDUAL FILES
;  find_leaky_pixels_xrg, '/nfs/slac/g/ki/ki03/lances/H2RG-32-147/DeadPix/DeadFiles.txt', mode=2
;  find_dead_pixels_xrg, '/nfs/slac/g/ki/ki03/lances/H2RG-32-147/DeadPix/DeadFiles.txt', mode=2
;
;**************************************************************************

pro Find_Dead_Pixels_xRG, FitsFileNameOrList, $ 
         Mode=Mode, Row=Row, Col=Col, $
	 Offset = Offset, $
	 UseRef = UseRef, TvFlag = TvFlag

If N_Elements(Mode)          eq 0 then Mode          = 1
If N_Elements(Col)	     eq 0 then Col	     = 20
If N_Elements(Row)	     eq 0 then Row	     = 20
If N_Elements(AddBias)       eq 0 then AddBias       = 0

if Mode ne 2 then begin

  ;No lists are used in this mode
  FitsFileName = FitsFileNameOrList

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

  ;Get a Few Kewyords
  FileCheck = Return_File_Params_xRG(FitsFileName)

  ;Form the output filenames
  DeadValsFileName = KeyStr.DeadDir+'DeadPix_'+KeyStr.RawObjectKey+'_'+$
		   KeyStr.Date+'_'+KeyStr.ThisFilter+'.fits'

  ;Indices with skipping of reference pixels and channel 0
  Threshold    = KeyStr.ReadNoiseMax
  NAxis1       = KeyStr.NAxis1
  NAxis2       = KeyStr.NAxis2
  Ref          = KeyStr.Ref

  ;If H4RG is used, take first channdel as obsolete
  If DetStr eq 'H4RG-10-007' then begin 
    Ch0W   = KeyStr.Ch0W
  EndIf Else Begin
    Ch0W   = Ref/2
  EndElse

  ;Don't include the reference pixels
  XMin   = Ch0W
  YMin   = KeyStr.Ref/2
  XMax   = KeyStr.Naxis1-KeyStr.Ch0W-KeyStr.Ref/2
  YMax   = KeyStr.Naxis2-KeyStr.Ref/2
EndIf

Case Mode of 
  0: Begin
    ;////////////////////////////////////////////////////////////////////
    ;PLOT PIXELS ////////////////////////////////////////////////////////
    ;Read in the 3x3 area
    Fits_Read_DataCube, FitsFileName, Im, H, XStart=Col-1, XStop=Col+1, $
       YStart = Row-1, YStop = Row+1
    ;Add the bias back to the median if requested
    If AddBias eq 1 then begin
       For ReadNum = 1, KeyStr.NAxis3-1 do begin 
         Im(*,*,ReadNum) = Im(*,*,ReadNum)+Im(*,*,0)
       EndFor
    EndIf Else Begin
         Im = Im(*,*,1:KeyStr.NAxis3-1)
    EndElse
    ;Get the min, max, and fraction w/respect to surrounding pixels
    MaxIm = Max(Im)
    MinIm = Min(Im)
    AvgSr = (Im(0,1,KeyStr.NAxis3-2)+Im(2,1,KeyStr.NAxis3-2)+$
	     Im(1,0,KeyStr.NAxis3-2)+Im(1,2,KeyStr.NAxis3-2))/4
    Frac  = Im(1,1,KeyStr.NAxis3-2)/float(AvgSr) 

    ;Do the plotting
    plot, Im(1,1,*), yrange = [MinIm, MaxIm], $
      ytitle = 'Counts', $
      title='Dead Pixel in : ' + KeyStr.RawObjectBase, /normal, $
      color = fsc_color('black'), background = fsc_color('white')
    oplot, Im(0,1,*), color = fsc_color('Red')
    oplot, Im(2,1,*), color = fsc_color('Blue')
    oplot, Im(1,0,*), color = fsc_color('Green')
    oplot, Im(1,2,*), color = fsc_color('Orange')
    xyouts, 0.20, 0.9, 'Pixel Coordinates',   color = fsc_color('Black'), /normal
    xyouts, 0.20, 0.85, 'X : '+strtrim(Col, 2), color = fsc_color('Black'), /normal
    xyouts, 0.35, 0.85, 'Y : '+strtrim(Row, 2), color = fsc_color('Black'), /normal
    xyouts, 0.20, 0.80, 'Fraction of Neighbors: ' + strtrim(Frac,2), color=fsc_color('black'),$
	    /normal
    xyouts, 0.25, 0.75, 'Upper',  color = fsc_color('Orange') , /normal
    xyouts, 0.25, 0.70, 'Center', color = fsc_color('Black')  , /normal
    xyouts, 0.20, 0.70, 'Left',   color = fsc_color('Red')    , /normal
    xyouts, 0.32, 0.70, 'Right',  color = fsc_color('Blue')   , /normal
    xyouts, 0.25, 0.65, 'Lower',  color = fsc_color('Green')  , /normal
    OrigCharSize = !p.charsize
    !p.charsize  = .75
    xyouts, 0.10, 0.000, KeyStr.RawObjectPath, color=fsc_color('black'), /normal
    !p.charsize  = OrigCharSize
    If KeyStr.TvFlag eq 1 then begin
      Img  = tvread(/tiff, FileName = KeyStr.LeakyDir+'Plots'+KeyStr.PathDelim+$
		           KeyStr.RawObjectKey+'_'+Strtrim(Col,2)+'_'+Strtrim(Row,2)+'.tif',$
                           /nodialog)
    EndIf
    stop
  End
  1: Begin  
    ;////////////////////////////////////////////////////////////////////////////////
    ;*********************** FIND ALL DEAD PIXELS IN FILE **************************
    ;Form an array that will keep track of how many times this pixel was leaky
    DeadPixVals   = bytarr(Naxis1, Naxis2)          ;Array to hold mask
    SciPixBool    = bytarr(XMax-XMin, YMax-YMin)    ;Array to hold mask without reference spaces

    MkHdr, DeadHeader, DeadPixVals
    FxAddPar, DeadHeader, 'DIFTHRESH', ThresHold, $
        'Threshold between first and last read'
    FxAddPar, DeadHeader, KeyStr.Date+'_'+KeyStr.RawObjectBase, $
        'Name of Files used to draw map'
    FxAddPar, DeadHeader, 'NUMDEAD', 0, $
        'Number of pixels with signal increase less than THRESHOLD'

    ;***************************************************************************
    ;Begin the main loop for the files and read numbers
    print, 'Reading File: ' + FitsFileName 
      
    ;Open up the raw image whether dark, flat, or object
    Fits_Read_DataCube, FitsFileName, Im, RawHeader

    if Stregex(KeyStr.RawObjectKey, 'Flat', /boolean) then begin
      FirstFrame = Float(Im(*,*,0))  
      LastFrame  = Float(Im(*,*,KeyStr.NAxis3-1))
      SciPixVals = LastFrame(XMin:XMax-1, YMin:YMax-1)
      DeadPix    = where(SciPixVals lt Threshold)
    endif else begin
      FirstFrame = Float(Im(*,*,0))
      LastFrame  = Float(Im(*,*,KeyStr.NAxis3-1))
      DiffFrame  = LastFrame-FirstFrame
      SciPixVals = DiffFrame(XMin:XMax-1, YMin:YMax-1)
      DeadPix    = where(SciPixVals lt Threshold)
    endelse   

    Print, 'Found : '+strtrim(N_Elements(DeadPix),2) +'Dead Pixels'
    ;Change the header slightly for the mask 
    SciPixBool(DeadPix) = 1
    DeadPixVals(XMin:XMax-1, YMin:YMax-1) = SciPixBool
    ;FxAddPar, DeadHeader, 'BITPIX', 8 
    Fits_Write, DeadValsFileName, DeadPixVals, DeadHeader

  End
  2: Begin
    ;////////////////////////////////////////////////////////////////////
    ;Get the names of fits files that will be used
    readcol, FitsFileNameOrList, FitsFileNames, format='A'

    FitsFileName  = FitsFileNames(0)
    DirName       = File_DirName(FitsFileName)
    DeadFileName = DirName + Path_Sep()+'DeadMask.fits'
 
    fits_read, FitsFileName, D, H, /header_only
    NAxis1 = long(SxPar(H, 'NAXIS1'))
    NAxis2 = long(SxPar(H, 'NAXIS2'))
    DeadMask = BytArr(NAxis1, NAxis2)

    ;FileNames and headers for masks and value leaky files
    MkHdr, DeadHeader, DeadMask
    for FileNum = 0, N_Elements(FitsFileNames)-1 do begin
      FxAddPar, DeadHeader, 'FILENUM'+Strtrim(FileNum,2), $
        File_BaseName(FitsFileNames(FileNum)), $
        'Files used to generate mask'
    endfor

    for FileNum = 0, N_Elements(FitsFileNames)-1 do begin
      Fits_Read, FitsFileNames(FileNum), DeadMaskInd, DeadHeadInd
      DeadMask(where(DeadMaskInd ne 0)) = 1
    endfor
    
    ;Write the fits file
    Fits_Write, DeadFileName, DeadMask, DeadHeader 
  End
EndCase
stop

end
