;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Lance Simms, Stanford University 2009
;pro Return_RefPix_xRG
;
;PURPOSE:
; To return either a set of reference pixel averages or a frame in
; which the reference pixel values have been subtracted from the
; science pixel values.
;
; CALLING SEQUENCE:
;       Ref=Return_RefPix_xRG(FitsFileNameOrDataCube, MODE)
;
; INPUTS:
;       FitsFileNameOrFrame -
;       MODE = 0 - The name of the fits file containing the data cube from
;                  which the reference columns should be extracted
;       MODE = 1 - A frame of pixels
;       MODE = 2 - A cube of pixels
;       MODE = 3 - A (XStop-XStart)x(YStop-YStart)xNAxis3 cube of pixels
;		   along with FitsFileName specified in the keyword
;       MODE = 4 - A ramp for one pixel
;	MODE = 5 - A ramp for one pixel
;
; OUTPUTS:
;       MODE = 0 -  A 2xNaxis2xNaxis3 data cube called
;                   RefColSmooth consisting of the reference pixels on the
;                   left -  RefColSmooth(0,*,*) and
;                   right - RefColSmooth(1,*,*)
;       MODE = 1 -  A single Naxis1xNaxis2 frame that
;                   is the inital data minus the reference pixels
;       MODE = 2 -  An Naxis1xNaxis2xNaxis3 cube that
;                   is the inital data minus the reference pixels.
;       MODE = 3 -  A (XStop-XStart)x(YStop-YStart)xNAxis3 
;                   cube of pixels with CFactor*RefPix subtracted
;       MODE = 4 -  The input ramp with the average of the
;                   reference pixels in that same row subtracted.
;       MODE = 5 -  The reference ramp multiplied by 
;                   CFactor
;
; KEYWORD PARAMETERS:
;       fwindow       - The size of the filter window.
;       order         - Filter order, see the SAVGOL help page
;       degree        - Filter degree, see the SAVGOL help page
;       plot          - Set this =1 to plot the fits
;       simple        - Set this =1 for Maximal Spatial Averaging
;                       (subtract a median reference pixel)
;
;       VERBOSE:      
;		- Set this =1 for verbose mode.
;	MEANOFF:
;		- A mean offset to remove from the reference pixels.  This 
;		  allows for saturation flagging to be applied after 
;		  the reference pixels have been subtracted
;       ROW: int
;         The row from which the reference pixels will be taken in the case that 
;         only a reference ramp is desired.
;       COL: int
;         The column of the pixel for which the ramp is desired.  This will 
;         determine whether the pixels from the left half or the right half 
;         are taken.
;       RAMP: float array
;         The ramp of pixel values that will be used if mode = 3
;       FITSFILENAME: str
;         For the case where MODE=3, FitsFileNameOrFrame is the 
;         datacube, so you must also specify this string that contains 
;         the path to the file
;       XSTART: int
;         If MODE=3, the xstart of the cube
;       XSTOP: int
;         If MODE=3, the xstop of the cube
;       YSTART: int
;         If MODE=3, the xstart of the cube
;       YSTOP: int
;         If MODE=3, the xstop of the cube
; EXAMPLE
;        IDL> fits_read, 'theImage.fits', myData, myHeader
;
; Code borrowed from Don Figer, Ernie Morse, B.J. Rauscher and others at STSCI
;
;*************************************************************************
Function Return_RefPix_xRG, FitsFileNameOrFrame, Mode, $
	 Date=Date, FWindow = FWindow, $
	 Order = Order, Degree = Degree, $
	 TvFlag = TvFlag, MeanOff = MeanOff, Row=Row, $
         Col = Col, Ramp=Ramp, FitsFileName=FitsFileName, $
         XStart=XStart, XStop=XStop, YStart=YStart, YStop=YStop

  If N_Elements(fwindow) eq 0 then fwindow = 64  ; 64 pixels for smoothing
  If N_Elements(order)   eq 0 then order   = 0   ; Use zero to smooth
  If N_Elements(degree)  eq 0 then degree  = 3   ; Three seems reasonable
  If N_Elements(MeanOff) eq 0 then MeanOff = 0
  If N_Elements(XStart)  eq 0 then XStart  = 0  
  If N_Elements(XStop)   eq 0 then XStop   = 0
  If N_Elements(YStart)  eq 0 then XStart  = 0
  If N_Elements(YStop)   eq 0 then YStop   = 0

  Common KeyParams, KeyStr

  if N_Elements(KeyStr) eq 0 then begin
    ;If called independently, then the argument should be a filenmae
    FitsFileName = FitsFileNameOrFrame
    @KeywordStruct_xRG.pro
  endif

  ;Capacitance factor for reference pixels seems to be different for ASIC/LEACH
  CFactor = KeyStr.CFac
  ;**********************************************MODE 0
  Case Mode of
    0: begin
      ;Read In only the reference pixels. Do not use the first reference
      ;pixel on each side. HAWAII-1RG works best like this.

	  ;Right now the LEACH electronics have a bogus column 0 and
	  ;column 1020 is science data
      If KeyStr.ElecStr eq 'LEACH' and KeyStr.DetStr eq 'H1RG-022' then begin
         Fits_Read_DataCube, FitsFileNameOrFrame, RefPixLeft, $
	      XStart = 1, XStop = 3, $
   	      YStart = 0, YStop = KeyStr.Naxis2-1
         Fits_Read_DataCube, FitsFileNameOrFrame, RefPixRight, $
              XStart = KeyStr.Naxis1-4, XStop = KeyStr.Naxis1-2, $
              YStart = 0, YStop = KeyStr.Naxis2-1
      EndIf Else Begin
	 Fits_Read_DataCube, FitsFileNameOrFrame, RefPixLeft, $
	      XStart = 1, XStop = 3, $
   	      YStart = 0, YStop = KeyStr.Naxis2-1
         Fits_Read_DataCube, FitsFileNameOrFrame, RefPixRight, $
          XStart = KeyStr.Naxis1-3, XStop = KeyStr.Naxis1-1, $
          YStart = 0, YStop = KeyStr.Naxis2-1
      EndElse
      
      ;Average the reference columns on left and right hand side
      MeanRefColL = Avg(RefPixLeft,0)
      MeanRefColR = Avg(RefPixRight,0)
      ;Subtract the mean of the zeroth read
      MeanRefVal  = mean([meanrefcolr(*,0),meanrefcoll(*,0)])
      MeanRefColL = MeanRefColL - MeanRefVal
      MeanRefColR = MeanRefColR - MeanRefVal

      SmooRefColL = fltarr(KeyStr.Naxis2, KeyStr.Naxis3) ; Smooth vector on left
      SmooRefColR = fltarr(KeyStr.Naxis2, KeyStr.Naxis3) ; Smooth vector on right
      SavgolFilter = savgol(FWindow, FWindow, Order, Degree)

      ;Go through the reads and smooth the reference pixels for each
      For ReadNum =0, KeyStr.Naxis3-1 do begin
        ;Form Arrays for filtering and subtraction
        SmooRefColL[4:KeyStr.Naxis1-5, ReadNum] = $
	  convol(MeanRefColL(4:KeyStr.Naxis1-5, ReadNum), SavgolFilter, $
	       /edge_truncate)
        SmooRefColR[4:KeyStr.Naxis1-5, ReadNum] = $
	  convol(MeanRefColR(4:KeyStr.Naxis1-5, ReadNum), SavgolFilter, $
	       /edge_truncate)
      EndFor
      if KeyStr.Date eq '04Jun06' then begin
        CFactorLeft  = 16.00
        CFactorRight = 10.00
      endif else begin
        CFactorLeft  = CFactor
        CFactorRight = CFactor
      endelse 
      ;Add in the capacitance factor
      SmooRefColL = SmooRefColL*CFactorLeft
      SmooRefColR = SmooRefColR*CFactorRight

      ;Return the reference pixel arrays as well as place them in the KeyStr
      If (Where(Stregex(Tag_Names(KeyStr), 'LEFTREFPIX', /boolean) eq 1))[0] $
      eq -1 then begin
        KeyStr = Create_Struct(KeyStr, 'LeftRefPix', SmooRefColL, $
				 'RightRefPix', SmooRefColR)
      EndIf Else Begin
        KeyStr.LeftRefPix  = SmooRefColL
        KeyStr.RightRefPix = SmooRefColR
      EndElse

      RefPixSmooth = Fltarr(2,KeyStr.Naxis2, KeyStr.Naxis3)
      RefPixSmooth(0,*,*) = SmooRefColL
      RefPixSmooth(1,*,*) = SmooRefColR
      return, RefPixSmooth

   End
   1: begin
      ;Get the average of the reference pixels on the left and right
      Frame    = FitsFileNameOrFrame
      OutFrame = FitsFileNameOrFrame
      If KeyStr.ElecStr eq 'LEACH' and KeyStr.DetStr eq 'H1RG-022' then begin
         MeanRefColL = Avg(Frame(1:3,*),0)
         MeanRefColR = Avg(Frame(KeyStr.Naxis1-3:KeyStr.Naxis1-1,*),0)
      EndIf Else Begin
         MeanRefColL = Avg(Frame(0:3,*),0)
         MeanRefColR = Avg(Frame(KeyStr.Naxis1-4:KeyStr.Naxis1-1,*),0)
      EndElse
      ;Now Smooth Them
      SavgolFilter = savgol(FWindow, FWindow, Order, Degree)
      SmooRefColL  = Fltarr(KeyStr.Naxis2)
      SmooRefColR  = Fltarr(KeyStr.Naxis2)
      SmooRefColL[4:KeyStr.Naxis1-5] = $
          convol(MeanRefColL(4:KeyStr.Naxis1-5), SavgolFilter, $
               /edge_truncate)
      SmooRefColR[4:KeyStr.Naxis1-5] = $
          convol(MeanRefColR(4:KeyStr.Naxis1-5), SavgolFilter, $
               /edge_truncate)
      For Col = 0, (KeyStr.Naxis1/2)-1 do begin
        OutFrame(Col,*) = Frame(Col,*) - SmooRefColL*CFactor+$
			  CFactor*MeanOff
        OutFrame((KeyStr.Naxis1-1)-Col,*) = Frame((KeyStr.Naxis1-1)-Col,*) - $
					    SmooRefColR*CFactor+$
					    CFactor*MeanOff
      EndFor

      ;Return the reference pixel subtracted frame
      Return, OutFrame

   End
   2: begin

      If size(FitsFileNameOrFrame, /type) eq 7 then begin
        Fits_Read_DataCube, FitsFileNameOrFrame, Cube, Header, zstart=0, zstop=15
        OutCube = long(Cube)
      endif else begin
        ;Get the average of the reference pixels on the left and right
        Cube    = FitsFileNameOrFrame
        OutCube = FitsFileNameOrFrame
      endelse
      For FrameNum = 0, 15 do begin;  (Size(Cube))[3] - 1 do begin
        Frame = Cube(*,*,FrameNum)
        OutFrame = Frame
        If KeyStr.ElecStr eq 'LEACH' and KeyStr.DetStr eq 'H1RG-022' then begin
          MeanRefColL = Avg(Frame(1:3,*),0)
          MeanRefColR = Avg(Frame(KeyStr.Naxis1-3:KeyStr.Naxis1-1,*),0)
        EndIf Else If KeyStr.DetStr eq 'H2RG-001' then begin
          MeanRefColL = Avg(Frame(01:4,*),0)
          MeanRefColR = MeanRefColL
        EndIf Else Begin
          MeanRefColL = Avg(Frame(0:3,*),0)
          MeanRefColR = Avg(Frame(KeyStr.Naxis1-4:KeyStr.Naxis1-2,*),0)
        EndElse
        ;Now Smooth Them
        SavgolFilter = savgol(FWindow, FWindow, Order, Degree)
        SmooRefColL  = Fltarr(KeyStr.Naxis2)
        SmooRefColR  = Fltarr(KeyStr.Naxis2)
        SmooRefColL[4:KeyStr.Naxis1-5] = $
          convol(MeanRefColL(4:KeyStr.Naxis1-5), SavgolFilter, $
               /edge_truncate)
        SmooRefColR[4:KeyStr.Naxis1-5] = $
          convol(MeanRefColR(4:KeyStr.Naxis1-5), SavgolFilter, $
               /edge_truncate)
        For Col = 0, (KeyStr.Naxis1/2)-1 do begin
          OutFrame(Col,*) = long(Frame(Col,*)) -  CFactor*SmooRefColL+$
					    CFactor*MeanOff
          OutFrame((KeyStr.Naxis1-1)-Col,*) = long(Frame((KeyStr.Naxis1-1)-Col,*)) - $
                                            CFactor*SmooRefColR+$
					    CFactor*MeanOff
        EndFor
        OutCube(*,*,FrameNum) = OutFrame
          EndFor
      ;Return the reference pixel subtracted frame
      Fits_Write, '/nfs/slac/g/ki/ki04/lances/Test.fits', OutCube 
      Return, OutCube

   End
   3: begin
      ;Get the full set of reference pixels.  All should be used 
      ;so that smoothing function does not pick up edge discontinuities
      SmooRefCol = Return_RefPix_xRG(FitsFileName, 0)
      If XStart lt KeyStr.NAxis2/2 then RefCol=0 else RefCol=1
      For Row=YStart, YStop do begin
        For Col=XStart, XStop do begin
          SubRow=Row-YStart 
          SubCol=Col-XStart
          FitsFileNameOrFrame(SubCol,SubRow,*) = $
              FitsFileNameOrFrame(SubCol,SubRow,*)-$
              CFactor*SmooRefCol(RefCol,Row,*)
        EndFor
      EndFor
      Return, FitsFileNameOrFrame
   End
   4: begin
      If N_Elements(Row) eq 0 or N_Elements(Col) eq 0 then begin
        print, 'Must Input Reference Row and Column (Row =, Col= )'
        stop
      EndIf
      OutRamp = Ramp
      RampL   = N_Elements(Ramp)
      ;Right now the LEACH electronics have a bogus column 0 and
      ;column 1020 is science data
      If KeyStr.ElecStr eq 'LEACH' and KeyStr.DetStr eq 'H1RG-022' then begin
         If Col lt KeyStr.Naxis1 then begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = 1, XStop = 3, $
                YStart = Row, YStop = Row
         EndIf Else Begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = KeyStr.Naxis1-3, XStop = KeyStr.Naxis1-1, $
                YStart = Row, YStop = Row
	 EndElse
      EndIf Else Begin
         If Col lt KeyStr.Naxis1 then begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = 0, XStop = 3, $
                YStart = Row, YStop = Row
         EndIf Else Begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = KeyStr.Naxis1-4, XStop = KeyStr.Naxis1-1, $
                YStart = Row, YStop = Row
	 EndElse
      EndElse

      MeanRefCol = Avg(RefPix,0)
      OutRamp = Long(Ramp) - CFactor*MeanRefCol+CFactor*MeanOff
      Return, OutRamp

   end
   5: begin
      If N_Elements(Row) eq 0 or N_Elements(Col) eq 0 then begin
        print, 'Must Input Reference Row and Column (Row =, Col= )'
        stop
      EndIf
      ;Right now the LEACH electronics have a bogus column 0 and
      ;column 1020 is science data
      If KeyStr.ElecStr eq 'LEACH' and KeyStr.DetStr eq 'H1RG-022' then begin
         If Col lt KeyStr.Naxis1 then begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = 1, XStop = 3, $
                YStart = Row, YStop = Row
         EndIf Else Begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = KeyStr.Naxis1-3, XStop = KeyStr.Naxis1-1, $
                YStart = Row, YStop = Row
         EndElse
      EndIf Else Begin
         If Col lt KeyStr.Naxis1 then begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = 0, XStop = 3, $
                YStart = Row, YStop = Row
         EndIf Else Begin
            Fits_Read_DataCube, FitsFileNameOrFrame, RefPix, $
                XStart = KeyStr.Naxis1-4, XStop = KeyStr.Naxis1-1, $
                YStart = Row, YStop = Row
         EndElse
      EndElse

      MeanRefCol = Avg(RefPix,0)
      Return, CFactor*MeanRefCol

   end


  EndCase

end
