;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Lance Simms, Stanford University 2009
;pro PlotSlope
;
;a routine to plot the slopes of pixels for diagnostic or presentation
;purposes
pro PlotSlope, Col, Row, Raw, Dark, TypeString

       Slope = Raw - Dark
       plot, Slope, yrange=[min(Slope), max(Slope)],$
             title = 'Row : '+Strtrim(Row,2) + ', Col : '+Strtrim(Col,2)
       stop

end

;pro SlopeFit
;
;PURPOSE:
;
;   To fit a slope to each of the pixels in a datacube from the
;   H1RG, H2RG, or H4RG detectors.  The slope of
;   the pixel value should represent the signal seen by that pixel,
;   whether it is darkcurrent or light.
;
;   This routine should properly handle saturated pixels in a multi-read
;   exposure with the exception of pixels that were already 
;   saturated in the first read.
;
;NOTES:
;   This should accomodate both raw images and median dark frames if the
;   filenames are set correctly.  That is, if the file name contains the
;   word 'Bias' or 'Dark', there will be no attempt to subtract a dark
;   frame.
;
;INPUTS (Necessary Keywords):
;       The script is run in one of three ways, depending on the inputs
;
;       1) A combination of:
;          DetStr       - 'H1RG-022', 'H2RG-32-147', 'H4RG-007' 
;          ElecStr      - 'ASIC', 'LEACH'
;	   Date         - The string with the date the exposures were taken
;          NReads       - Number of reads in all of the files
;          ObjectName   - The name of the object ('M1', 'M44', etc.)
;          ThisFilter   - The filter used to observe ('G', 'I', 'Y')
;          [ObjectText] - Optional string for LEACH files
;
;       OR
;       
;       2) FitsFileName - string
;          The name of the file to be slopefitted.  The program will 
;	   attempt to write the output to the proper directory.
;
;	OR
;	
;	3) FitsFileList - string
;	   A file with extension .lst.  This file should contain
;	   a list of the files to be slopefitted, one filename per line.
;
;OUTPUTS:
;	Slope-fitted file with name:
;         [Base of FitsFileName]Slope.fits
;	Slope-fitted and flat fielded file with name
;	  [Base of FitsFileName]SlopeFlatFielded.fits
;
;KEYWORDS:
;       DETSTR: string
;         The name of the detector used ('H1RG-022', 'H2RG-32-147', 'H4RG-007')
;       ELECSTR: string
;         The name of the electronics used ('ASIC', 'LEACH')
;       DATE: string
;         The Date during which they were taken.  Also the subdirectory that
;         the files are in ('07Dec18', '07Apr25', etc.)
;       BLOCKLENGTH: int
;         An offset for files that were written improperly.  The readu
;         function reads the values with this offset in place.
;       OFFSET: int
;         An offset for files that were written improperly.  The readu
;         function reads the values with this offset in place.
;       OBJECTNAME: string
;         The string that indicates what files are being sought.  The filenames
;         should begin with this string ('Dark', 'Flat', etc.).
;       OBJECTTEXT: string
;         A string that contains extra parameters in the filename for 
;         exposures taken with the LEACH ('Bfilter_300_1_0_0_0', etc.)
;       NREADS: string
;         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. It is a string because
;         certain files were recorded with floats (i.e. '30' or '30.0000')
;       THISFILTER: string 
;         The filter through which the files were taken ('I','G','Y','Blank')
;       OVERRIDE: int
;         0 - Don't overwrite the median file if it already exists
;         1 - Overwrite the file even if it exists
;       USEREF: int
;         0 - Don't subtract the reference pixels from the science pixels
;         1 - Subtract scaled, averaged, and filtered reference pixels
;	USESKYFLAT: int
;	  0 - Use the regular flat field taken with the big white spot
;	  1 - Use the flat field taken on the sky
;	SPECIFYFLAT: str
;         The full path to a slopefit that will be used as the flat for all slopefits
;	SKIPFLAT: int
;	  0 - Create a flat fielded image
;	  1 - Don't make a flat fieleded image
;       DARKSUB: int
;         0 - Don't subtract a dark exposure with matching cadence before median
;         1 - Subtract a dark exposure with matching cadence before median
;       THISNDROPS: int
;         The number of drops used in the exposures going into the median
;       WINDOWMODE: int
;         A boolean stating whether or not the exposures were taken in 
;         windowmode.  
;         0 - indicates full frame mode  
;         1 - indicates window mode.
;	SINGLECTHRESH: int
;	  The threhsold for flagging a suspected single hit cosmic ray to
;	  be included in the database in ADU.  
;	UPDATECOSDB: int
;	  0 - Update the cosmic ray MySQL database
;	  1 - Don't update the cosmic ray MySQL database
; 	WAITROW:
;          If TVFLAG is set, the slope will not be plotted until Row >= WAITROW
; 	WAITCOL: 
;          If TVFLAG is set, the slope will not be plotted until Col >= WAITCOL
;   	TVFLAG: 
;	  0 - Default, Don't plot anything
;	  1 - Plot to the X window	
;	  2 - Plot to postscript
;	  3 - Plot to a .png
;   	TVPPT:	Tv Plot Pixel Type - Designates the type of pixel to be plotted
;	  1 - Plot all pixels
;	  2 - Plot the cosmic rays
;	  3 - Plot the electrical spikes that are flagged in the linefitting
;	  4 - Plot the first read cosmics or potentially hot pixels
;	  5 - Only plot the single hit cosmic rays
;       TVROW: int
;         The minimum row at which the TvFlag will take effect
;       TVCOL: int
;         The minimum column at which the TvFlag will take effect
;       ZERONEGATIVE: int
;         0 - Don't set the negative slopes to zero
;         1 - Set the negative slopes to zero
;
;CALLING SEQUENCE:
;         slopefit_xrg, [FitsFileName=]
;	or
;	  slopefit_xrg, [DetStr=], [ElecStr=], [ObjectName=], [ObjectText=]
;
;EXAMPLES:
; BATCH SLOPEFIT of NGC2683 in filter G
;   slopefit_xrg,objectname='NGC2683',date='07Dec12',nreads=30,thisfilter='G',DetStr='H2RG-32-147',ElecStr='ASIC',/darksub,/useref
;slopefit_xrg,objectname='HorseHead',date='07Dec14',nreads=30,thisfilter='G',DetStr='H2RG-32-147',ElecStr='ASIC',/darksub,/useref,/updatecosdb
; LEACH:
;   slopefit_xrg, objectname='NGC2537', date='2007Nov13_2', nreads=200, thisfilter='G', DetStr='H1RG-022', ElecStr='LEACH', /darksub, /useref, objecttext='200_1_'
;
; SINGLE FILE SLOPEFIT
;   slopefit_xrg,fitsfilename='/nfs/slac/g/ki/ki03/lances/H2RG-32-147/ASIC/Reduced/07Dec12/Flat/MedianFlat_I_30_Reads_30_Reads_RPS.fits', /darksub
;	
; SLOPEFIT WITH SKY FLAT ON 07DEC19
;   slopefit_xrg,fitsfilename='/nfs/slac/g/ki/ki04/lances/H2RG-32-147/ASIC/07Dec19/NGC956/SaturationRamp_G_H2RG_SIPIN_20_Reads_Dec19_2007_21_03_58.fits', /darksub, /useref, specifyflat='/nfs/slac/g/ki/ki04/lances/H2RG-32-147/ASIC/Reduced/07Dec18/Flat/MedianFlatSky_G_30_Reads_RPS_G_Slope.fits'
;
; BATCH SLOPEFITS TO DARKS
;  slopefit_xrg, objectname='DarksAfterForwardBiases', thisfilter='Blank', date='08Jun28', nreads=50, detstr='H1RG-022', elecstr='ASIC'
;REFRENCES:
;   Based on code used in CalnicA for the NICMOS Data Reduction
;****************************************************************************
pro Slopefit_xRG, FitsFileName=FitsFileName, $
	 FitsFileList=FitsFileList, $
	 DetStr = DetStr, ElecStr = ElecStr, Date = Date, $
         ObjectName = ObjectName, ObjectText=ObjectText, $
	 DarkSub = DarkSub, UseBadMask = UseBadMask, $
	 NReads = NReads, ThisNDrops = ThisNDrops, $
	 ThisFilter = ThisFilter, SkipFileNum=SkipFileNum, $
	 UseRef= UseRef, UseSkyFlat = UseSkyFlat, $
         SpecifyFlat = SpecifyFlat, $
	 SkipFlat = SkipFlat, Offset = Offset, $
	 TvFlag = TvFlag, TvPPT = TvPPT, $
         TvRow  = TvRow, TvCol = TvCol,$
	 UpdateCOSDB=UpdateCosDB , $
	 SingleCThresh = SingleCThresh, $
         ZeroNegative = ZeroNegative

If N_Elements(SkipFileNum)  eq 0 then SkipFileNum  = 0
If N_Elements(TvPPT)        eq 0 then TvPPT        = 0
If N_Elements(TvRow)        eq 0 then TvRow        = 4
If N_Elements(TvCol)        eq 0 then TvCol        = 4
If N_Elements(UseRef)       eq 0 then UseRef       = 0
If N_Elements(UpdateCosDB)  eq 0 then UpdateCosDB  = 0
If N_Elements(UseSkyFlat)   eq 0 then UseSkyFlat   = 0
If N_Elements(SkipFlat)	    eq 0 then SkipFlat     = 0
If N_Elements(ZeroNegative) eq 0 then ZeroNegative = 0
If N_Elements(SpecifyFlat)  eq 0 then SpecifyFlat  = ''

;See if a list of files was provided first
If N_Elements(FitsFileList) ne 0 then begin
  ;If filename ends in .lst, slopefit all of the filenames in that file
  ReadCol, FitsFileList, RawFiles, Format = 'A'
  FitsFileName = RawFiles(0)
EndIf

Common KeyParams, KeyStr
;Include all of the keywords from the KeywordStruct file

@KeywordStruct_xRG.pro
@PlotSettings_xRG.pro

;******1) BATCH MODE or 3) FILELIST (.lst)****************************************
If N_Elements(FitsFileList) ne 0 then begin
   ;If filename ends in .lst, slopefit all of the filenames in that file
   ReadCol, FitsFileList, RawFiles, Format = 'A'
   FitsFileName = RawFiles
   FitsFileName = FitsFileName(SkipFileNum:N_Elements(FitsFileName)-1)
EndIf Else If N_Elements(FitsFileName) eq 0 then begin
   ;If filename is blank, search for matching files in the directory
   FitsFileName = File_Search(KeyStr.RawObjectDir+KeyStr.PathDelim+$
			      KeyStr.ObjectName+'*'+KeyStr.ObjectText+'*.fits')
   FitsFileName = Return_File_List_xrg(FitsFileName, ThisFilter=ThisFilter,$
		 		       ThisNDrops=ThisNDrops, $
				       ThisNAxis3=NReads)
   FitsFileName = FitsFileName(SkipFileNum:N_Elements(FitsFileName)-1)
EndIf

;Give the user info
print, 'About to calculate slopes for: '
print,  FitsFileName
print, 'Enter .continue to proceed'
stop

;**************************************************BEGIN LOOP OVER FILES
;Batch mode for given filter or single image
For FileNum = 0, N_Elements(FitsFileName)-1 do begin

  print, 'Working on File :' + FitsFileName(FileNum)

  ;Get the current file that's being operated on and some keys
  KeyStr.RawObjectPath = FitsFileName(FileNum)

  ;Get the Parameters necessary to fit this file
  FileParam= Return_File_Params_xRG(FitsFileName(FileNum), $
				    UseSkyFlat=UseSkyFlat)

  ;Make sure we have the right flat name
  if SpecifyFlat ne '' then KeyStr.FlatName = SpecifyFlat

  ;Warn about the dark begin used
  if FileNum eq 0 then begin
    print, ''
    print, 'With median dark file: '
    print,  KeyStr.DarkName
    print, 'With flat file: '
    print,  KeyStr.FlatName
    print, ''
  endif

  SlopeStr = Return_Slope_Params_xRG(RawHeader)

  ;Only the median files should have already been 0th read subtracted
  If not (stregex(FitsFileName(FileNum),'Median',/boolean)) then $
	 KeyStr.BiasSub=0

  ;Make a temporary mask that can be chopped to save time
  BadInd        = 0L
  NumNonLin     = 0L
  NReads        = KeyStr.TotalReads
  TimePoints    = SlopeStr.ReadTimes(1:NReads-1)
  LowerLinLim   = KeyStr.LowerLinLim
  UpperLinLim   = KeyStr.UpperLinLim
  FullLinLim    = UpperLinLim - LowerLinLim
  ;Make arrays for the Slopes and what have you
  Slopes      = Fltarr(KeyStr.Naxis1, KeyStr.Naxis2)
  Intercepts  = Fltarr(KeyStr.Naxis1, KeyStr.Naxis2)
  Errors      = Fltarr(KeyStr.Naxis1, KeyStr.Naxis2)
  Cosmics     = Fltarr(KeyStr.Naxis1, KeyStr.Naxis2)
  CosmicReads = BytArr(KeyStr.Naxis1, KeyStr.Naxis2)
  CosmicTypes = BytArr(KeyStr.Naxis1, KeyStr.Naxis2)
  SatMask     = BytArr(KeyStr.Naxis1, KeyStr.Naxis2)

  ;Attempt to remove fixed noise using channel 0
  If KeyStr.UseRef then begin
     SmooRefCols = Return_RefPix_xRG(KeyStr.RawObjectPath,0)
     SmooRefColL = (SmooRefColR = Fltarr(KeyStr.Naxis2,KeyStr.Naxis3))
     SmooRefColL(*,*) = Float(SmooRefCols(0,*,*))
     SmooRefColR(*,*) = Float(SmooRefCols(1,*,*))
  EndIf
 
  ;Take in Frames one half at a time to avoid memory crash
  For FrHalf = 0, 1 do begin
    print, 'Computing Slopes for frame half : '+strtrim(FrHalf,2)

    ;Read in Half of the raw/median image
    Fits_Read_DataCube, KeyStr.RawObjectPath , RawHalf , RawHeader, $
		XStart= 0, XStop = KeyStr.Naxis1-1, $
		YStart= FrHalf*KeyStr.Naxis2/2, $
		YStop = (FrHalf+1)*KeyStr.Naxis2/2-1, $
		Offset = Offset
    ;Read in Half of the dark image if dark subtraction is requested
    If KeyStr.DarkSub then begin $
      Fits_Read_DataCube, KeyStr.DarkName, DarkHalf, DarkHeader, $
        XStart= 0, XStop = KeyStr.Naxis1-1, $
        YStart= FrHalf*KeyStr.Naxis2/2, $
        YStop = (FrHalf+1)*KeyStr.Naxis2/2-1
    EndIf Else Begin
      DarkHalf = LonArr(KeyStr.Naxis1, KeyStr.Naxis2/2, KeyStr.Naxis3)
    EndElse

    ;Loop over the pixels and slope fit them individually and iteratively,
    ;rejecting cosmic rays
    For Row = Double(FrHalf*KeyStr.Naxis2/2), $
	      Double((FrHalf+1)*KeyStr.Naxis2/2 - 1) do begin

      ;Get the index for the half frame
      RowH = Row-FrHalf*KeyStr.Naxis2/2
      print, Row

      ;Remove the common mode from each row in each frame
      For Col = 0D, KeyStr.Naxis1-1 do begin
	 PixelInd = Col+KeyStr.Naxis1*Row

 	 If KeyStr.DarkSub then begin
	    DarkRamp = DarkHalf(Col,RowH,1:KeyStr.TotalReads-1)
	 EndIf Else begin
            DarkRamp = LonArr(KeyStr.TotalReads)
         EndElse

	 ;Take the Raw Ramp in to check for Saturation without any
	 ;subtration taking place
	 RawRamp    = RawHalf(Col,RowH,1:NReads-1)
	 RawBias    = RawHalf(Col,RowH,0)

         If Not KeyStr.BiasSub then begin
	    ;Find values in the linear regim
	    GoodMask = where(RawRamp gt LowerLinLim and $
			     RawRamp lt UpperLinLim, NumGood)
	    DarkFirstRead = DarkHalf(Col,RowH,1)
            DarkBias      = DarkHalf(Col,RowH,0)
	    RawFirstRead  = RawHalf(Col,RowH,1)

	    ;Check for saturated pixels and add them to the saturation mask
            SatVals  = where( RawRamp gt UpperLinLim, NumSat)
            If SatVals(0) ne -1 then SatMask(Col,Row) = NumSat

	    ;Subtract the Reference Ramp after the limits of linearity
	    ;have been checked
            If KeyStr.UseRef eq 1 then begin
	           RawRamp = RawRamp - $
			     SmooRefCols(Col/(KeyStr.Naxis1/2), Row, $
					       1:KeyStr.TotalReads-1)
	       	   RawBias = RawBias - $
			     SmooRefCols(Col/(KeyStr.Naxis1/2), Row, 0)
	    EndIf
 	 EndIf Else Begin
            GoodMask = where((RawRamp +RawBias) gt LowerLinLim and $
                             (RawRamp +RawBias) lt UpperLinLim, NumGood)
	    RawFirstRead  = RawHalf(Col,RowH,1)+RawHalf(Col,RowH,0)
	    DarkBias      = DarkHalf(Col,RowH,0)
	    DarkFirstRead = DarkHalf(Col,RowH,0)+DarkHalf(Col,RowH,1)
	 EndElse

 	 ;Perform a line fit to the points in the linear region
	 If NumGood le 1 then begin
	    NumNonLin +=1
            ;If pixel is saturated, check neigbhors to see if it's at the
	    ;center of a star.  If so, use read 0 as an estimate of flux
	    ;Make sure that borders of array are not a problem
	    ColLeft = 1 & ColRight = 1 & RowDown = 1 & RowUp = 1
	    If Col  eq 0 or Col eq KeyStr.Ch0W          then ColLeft  = 0
	    If Col  eq KeyStr.Naxis1 - 1 then ColRight = 0
            If RowH eq KeyStr.Ref/2 or RowH eq 0	  then RowDown  = 0
	    If RowH eq KeyStr.Naxis2/2-1		  then RowUp    = 0
	    ;Get the 3x3 (or smaller) region around
            RegCheck = RawHalf(Col-ColLeft:Col+ColRight,$
			         RowH-RowDown:RowH+RowUp,0)

	    ;Get the counts of the flagged pixel
	    CenFlux  = RegCheck(ColLeft,RowDown)

	    ;Set it to zero and look at the avg. value of neighbors
	    RegCheck(ColLeft,RowDown) = 0
            SurrPix = where(RegCheck ne 0, NumSurrPix)
            If NumSurrPix ne 0 then begin
               djs_iterstat, RegCheck(where(RegCheck ne 0)), $
                   mean = SurMean, sigma = SurSigma
	    Endif Else begin
               SurMean = 0 & SurSigma = 0
            EndElse
	      ;If it's an outlier, flag it as a cosmic hit or a bad pixel
	      ;that hasn't been discovered yet
	      If CenFlux gt SurMean+2.5*SurSigma and $
		 Not KeyStr.DarkSlope then begin
                 Slopes(Col,Row) = 0
		 print, 'Hot Pixel or Cosmic at : ', Col, Row
		 If KeyStr.TvFlag and KeyStr.TvPPT eq 4 then $
		    PlotSlope, Col, Row, RawHalf(Col,Row,*), $
		        DarkHalf(Col,Row,*), 'Hot Pixel'
              EndIf else begin
                 ;If the first read is still in the linear regime and it's
		 ;less than half the way there, use the single cds
		 If NumGood eq 1 and $
		  RawBias lt (float(FullLinLim)/2+LowerLinLim) $
		  then begin
	            Slopes(Col,Row)= $
			((RawFirstRead-RawBias)-$
			  DarkFirstRead)/$
			  (SlopeStr.GroupTimes(1)-SlopeStr.GroupTimes(0))
		 EndIf Else begin
		 ;If the first read is already saturated, subract
		 ;the median dark bias and divide by a frame time
                    Slopes(Col,Row)=(RawBias-DarkBias)/$
			  SlopeStr.FrameTime
                 EndElse
		  print, 'SatPix approx slope = ', Slopes(Col,Row) , $
			 '    at Col='+strtrim(long(Col),2)+$	
			 '    Row='+strtrim(long(Row),2)
	       EndElse
	    EndIf else begin
	       LineFit_xRG, TimePoints, RawRamp, m, b, $
		sigm, sigb, Error, CosmicEDep, CosmicRead, $
		CosmicType, Y2=DarkRamp, Mask=GoodMask, $
		Col=Col, Row=Row, $
		ThresholdFactor = KeyStr.SlopeSigThresh, $
		TvFlag=KeyStr.TvFlag, TvPPT=KeyStr.TvPPT, $
		WaitRow = TvRow, WaitCol = TvCol
	       
	       ;Reject negative slopes
               If m lt 0 and ZeroNegative eq 1 then m = 0
	
	       ;Fill the arrays
	       Slopes(Col,Row)      = m
	       Intercepts(Col,Row)  = b
	       Errors(Col,Row)      = Error
	       Cosmics(Col,Row)     = CosmicEDep
	       CosmicReads(Col,Row) = CosmicRead
	       CosmicTypes(Col,Row) = CosmicType
	    EndElse
      EndFor
    EndFor
    ;===========================================================================
    ;LOOK FOR SINGLE HIT COSMICS AND USE THEM AS A MEASURE OF IPC
    If UpdateCosDB eq 1 then begin
      ;Open a pipe to the SingleCRHits MySQL database and form the table name
      openmysql, MySQLlun, 'SingleCRHits', MyQLErr
      TableName = KeyStr.DetStr+'_'+KeyStr.ElecStr+'_'+'SinCRHits'
      strreplace, TableName, '-','_'
      strreplace, TableName, '-','_'

      ;Now find the single htis and insert them into the table
      CosmicHits = where(Cosmics gt 0, NumCosmics)
      If NumCosmics gt 0 then begin
         CosmicCenter    = Bytarr(KeyStr.Naxis1,KeyStr.Naxis2/2)
         CosmicNeighbors = Bytarr(KeyStr.Naxis1,KeyStr.Naxis2/2,9)
         CosmicCenter(CosmicHits) = 1
         ;Locate the surrounding values
         For NeighborInd = 0, 8 do begin 
           NeighborRow = NeighborInd/3 & NeighborCol = NeighborInd mod 3
           CosmicNeighbors(1:KeyStr.Naxis1-2,1:KeyStr.Naxis2/2-2, NeighborInd)=$
     	     CosmicCenter(NeighborCol:KeyStr.Naxis1+NeighborCol-3, $
  		          NeighborRow:KeyStr.Naxis2/2+NeighborRow-3)
         EndFor
	 ;Determine where single hits are located
         NumNeighbors = Total(CosmicNeighbors,3)
         SingleHits = where(NumNeighbors eq 1 and CosmicCenter eq 1, NumSingleHits)
         If NumSingleHits gt 0 then begin
	    ;Find the relative coordinates of FullCol, HalfRow
            SingleHitX = SingleHits mod KeyStr.Naxis1
  	    SingleHitY = SingleHits/KeyStr.Naxis1

	    ;Loop through all single hits and add them to database with neighbor values
  	    For HitNum = 0 , NumSingleHits - 1 do begin
	      HalfRow  = SingleHitY(HitNum)
	      FullRow  = Double(FrHalf*KeyStr.Naxis2/2)+SingleHitY(HitNum)
	      FullCol  = SingleHitX(HitNum)
	      HitRead  = CosmicReads(FullCol,FullRow)
	      ThisType = CosmicTypes(FullCol,FullRow) 
              Cosmic11 = (RawHalf(FullCol,HalfRow,HitRead+1)-$
			 long(RawHalf(FullCol,HalfRow,HitRead)))-$
			 (SmooRefCols(FullCol/(KeyStr.Naxis1/2), FullRow, HitRead+1)-$
                          SmooRefCols(FullCol/(KeyStr.Naxis1/2), FullRow, HitRead))
	      ;Only tag those above SingleCThresh
	      If Cosmic11 gt KeyStr.SingleCThresh then begin
                 SingleCRArr = LonArr(3,3)
		 For i=-1,1 do begin
		  For j=-1,1 do begin
		   SingleCRArr(i+1,j+1) = (RawHalf(FullCol+i,HalfRow+j,HitRead+1)-$
                         		  long(RawHalf(FullCol+i,HalfRow+j,HitRead)))-$
                         (SmooRefCols(FullCol/(KeyStr.Naxis1/2), FullRow+j, HitRead+1)-$
                          SmooRefCols(FullCol/(KeyStr.Naxis1/2), FullRow+j, HitRead))
		  EndFor
                 EndFor
                 mysqlcmd, MySQLLun, 'INSERT INTO '+TableName+' VALUES('+$
                  strtrim(long(HitRead),2)         +','+$
		  strtrim(long(FullCol),2)         +','+$
		  strtrim(long(FullRow),2)         +','+$
		  "'"+strtrim(KeyStr.RawObjectKey,2)+"'"+','+$
                  strtrim(long(SingleCRArr(0,0)),2)+','+$
		  strtrim(long(SingleCRArr(1,0)),2)+','+$
		  strtrim(long(SingleCRArr(2,0)),2)+','+$
		  strtrim(long(SingleCRArr(0,1)),2)+','+$
                  strtrim(long(SingleCRArr(1,1)),2)+','+$
		  strtrim(long(SingleCRArr(2,1)),2)+','+$
                  strtrim(long(SingleCRArr(0,2)),2)+','+$
		  strtrim(long(SingleCRArr(1,2)),2)+','+$
		  strtrim(long(SingleCRArr(2,2)),2)+');', Answer, NLines
              EndIf

	      If TvFlag eq 1 and TvPPT eq 5 then begin
  	        plot, RawHalf(FullCol,HalfRow,*)-long(RawHalf(FullCol,HalfRow,0))-$
                           SmooRefCols(FullCol/(KeyStr.Naxis1/2), FullRow, *)

	        print, 'Single Cosmic Hit at: ' + strtrim(long(FullCol),2) + '  ,  ' + $
		     strtrim(long(FullRow),2)
	        print, '    ADU: ' + strtrim(Cosmic11,2)
	        print, 'At Read: ' + strtrim(long(HitRead),2)
	        if Cosmic11 gt KeyStr.SingleCThresh then begin
		  print, '  Type : Cosmic'
	        endif 
		stop
	      EndIf
            EndFor
         EndIf
      EndIf
      Free_Lun, MySQLLun
    EndIf
  EndFor

  ;***************************************************************************
  ;SLOPEFIT OUTPUT FITS FILE *************************************************
  ;0 = Slope fit			;2 = Error in Fit
  ;1 = Y Intercept		        ;3 = Cosmic Rays
  ;Form a header with some of the necessary keywords
  SlopeArray=[[[Slopes]],[[Intercepts]],[[Errors]],[[Cosmics]]]
  MkHdr, SlopeRawHeader, SlopeArray
  SlopeRawHeader = Update_Header_1RG(SlopeRawHeader)
  FxAddPar, SlopeRawHeader, 'FRAME1', 'Slope', 'm in y=mx+b'
  FxAddPar, SlopeRawHeader, 'FRAME2', 'Intercept', 'b in y=mx+b'
  FxAddPar, SlopeRawHeader, 'FRAME3', 'Error', $
	'Error in fit sqrt(<(data - y=mx+b)^2>)'
  FxAddPar, SlopeRawHeader, 'FRAME4', 'Cosmic Ray Deposits'
  FxAddPar, SlopeRawHeader, 'MINTHRESH', KeyStr.LowerLinLim, $
	'Minimum limit for linear slope calculation'
  FxAddPar, SlopeRawHeader, 'MAXTHRESH', KeyStr.UpperLinLim, $
	'Maximum limit for linear slope calculation'
  FxAddPar, SlopeRawHeader, 'NOISEREM', KeyStr.Rem60HzStr, $
	'Mode of noise removal for raw image'
  FxAddPar, SlopeRawHeader, 'MEDDARK',  KeyStr.DarkKey, 'Name of Dark used'
  FxAddPar, SlopeRawHeader, 'NOISEREM', KeyStr.Rem60HzStr, $
	'Mode of fixed noise removal using output 0 (H4RG)'
  FxAddPar, SlopeRawHeader, 'REFPIX', KeyStr.UseRef, $
	'Reference pixels were averaged, filtered and subtracted'
  FxAddPar, SlopeRawHeader, 'USEDARK', KeyStr.DarkSub, $
        '1/0 Dark was/was not subtracted'
  FxAddPar, SlopeRawHeader, 'CRTHRESH', KeyStr.SlopeSigThresh, $
	'Threshold (# sigma from line) for cosmic ray rejection' 
  FxAddPar, SlopeRawHeader, 'PROFILE', 'slopefit_xrg.pro', $
	'IDL File used to create slope'
  FxADDPar, SlopeRawHeader, 'TIME', KeyStr.Time, $
	'Time at beginning of exposure'
  ;Form the filename depending on whether is was a dark slope or a lit slope
  ;UseRefPix should already be included in string
  If stregex(KeyStr.RawObjectKey, 'Dark', /boolean) then begin
     SlopeFileName = KeyStr.RedObjectDir+KeyStr.RawObjectKey+$
                     KeyStr.Rem60HzStr+'_Slope.fits'
  EndIf Else If stregex(KeyStr.RawObjectKey, 'Flat', /boolean) then Begin
     SlopeFileName = KeyStr.RedObjectDir+KeyStr.RawObjectKey+$
                     '_'+KeyStr.ThisFilter+KeyStr.Rem60HzStr+'_Slope.fits'
  EndIf Else Begin
     SlopeFileName = KeyStr.RedObjectDir+KeyStr.RawObjectKey+$
                     '_'+KeyStr.ThisFilter+'_'+KeyStr.RefPixStr+$
                     KeyStr.Rem60HzStr+'_Slope.fits'
  EndElse
  SlopeFileName    = clean_filename(SlopeFileName)
  Fits_Write, SlopeFileName, SlopeArray, SlopeRawHeader
  print, 'Slopes written to : ' & print, string(13B) 
  print,  SlopeFileName

  ;***********************************************FLAT FIELD SLOPE
  ;xRG Files use the slopefitted flats with a certain amount of reads
  ;Divide by the flat if requested
  ;Extension 1 = Saturation Mask
  If Not Stregex(KeyStr.ObjectName, 'Flat', /boolean) and $
     Not Stregex(KeyStr.ObjectName, 'Dark', /boolean) and $
     Not SkipFlat and KeyStr.FlatName ne '' then begin

       ;A specific flat name might be specified in keyword
       If SpecifyFlat ne '' then begin
         KeyStr.FlatName = SpecifyFlat
         KeyStr.FlatKey  = File_BaseName(KeyStr.FlatName)
       endif
       Fits_Read, KeyStr.FlatName, FlatIm, FlatHeader

       ;Normalize the Flat
       FlatIm = Double(FlatIm(KeyStr.Ref/2:KeyStr.NAxis1-KeyStr.Ref/2-1,$
                           KeyStr.Ref/2:KeyStr.NAxis2-KeyStr.Ref/2-1,0))/$
                Max(FlatIm(KeyStr.Ref/2:KeyStr.NAxis1-KeyStr.Ref/2-1,$
                           KeyStr.Ref/2:KeyStr.NAxis2-KeyStr.Ref/2-1,0))
       FlatFieldSlope = Fltarr(KeyStr.NAxis1, KeyStr.NAxis2)
       FlatFieldSlope(KeyStr.Ref/2:KeyStr.NAxis1-KeyStr.Ref/2-1,$
                      KeyStr.Ref/2:KeyStr.NAxis2-KeyStr.Ref/2-1) = $
                      Double(SlopeArray(KeyStr.Ref/2:KeyStr.NAxis1-KeyStr.Ref/2-1,$
                      KeyStr.Ref/2:KeyStr.NAxis2-KeyStr.Ref/2-1,0))/Double(FlatIm)

       ;Write the file and add a few keywords
       FxAddPar, SlopeRawHeader, 'FLATFILE', KeyStr.FlatKey, $
	'Flat field used for image'
       FxAddPar, SlopeRawHeader, 'EXT1', 'SATMASK', $
        'The 1st extension is a mask of saturated pixels'
       FlatSlopeFileName = KeyStr.RedObjectDir+KeyStr.RawObjectKey+$
			   '_'+KeyStr.ThisFilter+'_'+KeyStr.RefPixStr+$
		  	   KeyStr.Rem60HzStr+'_SlopeFlatFielded.fits'
       FlatSlopeFileName = clean_filename(FlatSlopeFileName)
       Fits_Write, FlatSlopeFileName, FlatFieldSlope, SlopeRawHeader
       Fits_Open,  FlatSlopeFileName, SlopeFCB, /append
       Fits_Write, SlopeFCB, SatMask, extname = 'SatMask'
       Fits_Close, SlopeFCB

       print, 'Flat-fielded Slopes written to : ' & print, string(13B)
       print,  FlatSlopeFileName
  Endif

  ;****************************************************************

EndFor

End
