##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Lance Simms, Stanford University 2009##Return_Persistence_DbQuantities.py
##
##PURPOSE: 
##To extract the persistence quanitities from the databases created with the
##Persistence_Create_Database.py script and return some quantities 
##
##INPUTS:
##
##          DetStr          - 'H1RG-022','H2RG-32-147', or 'H4RG-10-007' 
##          ElecSt          - 'ASIC' or 'LEACH'
##          Dates           - A string array containing the dates in the path 
##          NReads          - A list with the number of reads in the images
##          NDarkReads      - A listwith the number of 
##          DatabaseName    - Name of the database to use
##          SlopeTableNames - A string array containing the names of the
##                            databases with the saturation parameters 
##                            for each star
##          DarkTableNames  - A string array containing the names of the 
##                            database with the dark parameters for each star
##
##          SlopeFiles      - A string array containing the paths to the slope
##                            files reduced from the saturation exposures
##          FileLists       - A string array containing the paths to the dark
##                            exposures taken after saturation
##	    QueryString     - The identifier for the rows that are sought.
##                            Should be a string with the form:
##			         "WHERE " + Qualifiers + " "
##          PIXID           - The pixel ID key in the database.  This will be used
##                            in mode 1 to obtain one specific pixel
##          HxRG            - An instance of the HxRG class
##          TvFlag: int
##                            0 - Don't plot
##                            1 - Plot quantities as script runs
##          Verbosity: int
##                            0 - don't print much
##                            1 - print the values
##          UpdateMinMaxDb:int
##                            If we are in mode 2, 
##                            0 - Don't update the Min, Max database
##                            1 - Update the Min, Max database
##          NumFiles: int     
##                            If we are in mode 2, the total number of files to consider 
##                            in the decay fit
##          OverWrite: int 
##                            0 - Don't destroy the database
##                            1 - Overwrite the database if it exists
##	    Mode            - 0 - Get all of the values of the persistent 
##                                regions for a certain readnum and filenum
##                                after saturation
##                            1 - Return values for pixel given by PIXID based
##                                upon QueryString
##                            2 - Plot the decays for a series of pixels
##                                If UpdateMinMaxDb == 1, the decay time 
##                                constants will be written to a new database
##                                called [Object]_MinMax_[NREADS]Reads_[Filter]
##                            3 - Return Coefficients from fit to Min/Max 
##                                Decay     
##                            4 - Return all values for one pixel 
##                                from FILE=0 to FILE=9
##
###########################################################################
import MySQLdb
import pdb
from ReadCol import *
from numpy import *
from pylab import *
import scipy.optimize
import matplotlib.pylab as mplot
import time
from FitDecay import *
from Persistence_Get_Dark_Times import *
from HxRG_Class import *

def Return_Persistence_DbQuantities(DetStr, ElecStr, Dates, NReads, NDarkReads,\
                          DataBaseName, DarkTableNames, SlopeTableNames,\
                          FileLists, NTables, QueryString, Mode,\
                          PixID=1000, HxRG=0, TvFlag=0, Verbosity=0,\
                          UpdateMinMaxDb=0, OverWrite=0, NumFiles=9) : 

  ##OPEN THE DATABASE
  try:
    conn=MySQLdb.connect (host="localhost",
                         user="root",
                         passwd="mysql",
                         db=DataBaseName,
                         unix_socket="/tmp/mysql.sock")
  except MySQLdb.Error, e:
    print "Error $d: $s" % (e.args[0],e.args[1])
    sys.exit

  cursor=conn.cursor()

  ##############################################################################
  #MODE 0 - Return parameters from first exposure after saturation; last read
  ##############################################################################
  if Mode == 0:
    #Set up for the sequence used to fill the database
    FileNum = 0
    conn.query("SELECT * FROM "+ SlopeTableNames[0]+";")
    SatRes     = conn.store_result()
    SatRows    = SatRes.fetch_row(maxrows=0, how=1)
    NumSatRows = SatRes.num_rows() 
    PixIDs   = zeros(NumSatRows,dtype=int32)
    WellPcts = zeros(NumSatRows,dtype=float32)
    SatRads  = zeros(NumSatRows,dtype=float32)
    NumSats  = zeros(NumSatRows,dtype=float32)
    FWHMs    = zeros(NumSatRows,dtype=float32)
    SkyMeans = zeros(NumSatRows,dtype=float32)
    Maxs     = zeros(NumSatRows,dtype=float32) 
    Mins     = zeros(NumSatRows,dtype=float32)
    MinRads  = zeros(NumSatRows,dtype=float32)
    MaxRads  = zeros(NumSatRows,dtype=float32)
    FZeros   = zeros(NumSatRows,dtype=float32)
    SZeros   = zeros(NumSatRows,dtype=float32)
    SumCores = zeros(NumSatRows,dtype=float32)
    SumHalos = zeros(NumSatRows,dtype=float32)
    SumOuts  = zeros(NumSatRows,dtype=float32)

    #Get values from primary table and then access Dark table for each Pixel
    for RowNum in arange(NumSatRows):
      PixIDs[RowNum]   = SatRows[RowNum]['PIXID']
      WellPcts[RowNum] = SatRows[RowNum]['WELL_PERCENT']
      SatRads[RowNum]  = SatRows[RowNum]['SAT_RAD']
      NumSats[RowNum]  = SatRows[RowNum]['NUM_SAT']
      FWHMs[RowNum]    = SatRows[RowNum]['FWHM']
      SkyMeans[RowNum] = SatRows[RowNum]['SKY_MEAN']
      conn.query("SELECT * FROM " + DarkTableNames[0] + QueryString+\
                 " AND PIXID="+str(PixIDs[RowNum])+";")
      DarkRes  = conn.store_result()
      DarkRow  = DarkRes.fetch_row(maxrows=0,how=1)
      Maxs[RowNum] = DarkRow[0]['MAX']
      Mins[RowNum] = DarkRow[0]['MIN']
      MinRads[RowNum] = DarkRow[0]['MINRAD']
      MaxRads[RowNum] = DarkRow[0]['MAXRAD']
      FZeros[RowNum] = DarkRow[0]['FIRSTZ']
      SZeros[RowNum] = DarkRow[0]['SECONDZ']
      SumCores[RowNum] = DarkRow[0]['SUMCORE']
      SumHalos[RowNum] = DarkRow[0]['SUMHALO']
      SumOuts[RowNum]  = DarkRow[0]['SUMOUT']

    return WellPcts, SatRads, NumSats, FWHMs, SkyMeans, Maxs, Mins, \
           MinRads, MaxRads, FZeros, SZeros, SumCores, SumHalos, SumOuts
  
  ##############################################################################
  ##MODE=1 - Plot the exponential decay for one pixel
  elif Mode==1:

    conn.query("SELECT * FROM "+ DarkTableNames[0]+\
               " where "+QueryString+" and PixID="+str(PixID)+";")
    DarkRes      = conn.store_result() 
    DarkRows     = DarkRes.fetch_row(maxrows=0, how=1)
    NumDarkRows  = DarkRes.num_rows()
    Maxs     = zeros(NumDarkRows,dtype=float32)
    Mins     = zeros(NumDarkRows,dtype=float32)
    MinRads  = zeros(NumDarkRows,dtype=float32)
    MaxRads  = zeros(NumDarkRows,dtype=float32)
    FZeros   = zeros(NumDarkRows,dtype=float32)
    SZeros   = zeros(NumDarkRows,dtype=float32)
    MinRadsFit = zeros(NumDarkRows,dtype=float32)
    FZerosFit = zeros(NumDarkRows,dtype=float32)
    SZerosFit = zeros(NumDarkRows,dtype=float32)
    SumCores = zeros(NumDarkRows,dtype=float32)
    SumHalos = zeros(NumDarkRows,dtype=float32)
    SumOuts  = zeros(NumDarkRows,dtype=float32)

    for RowNum in arange(NumDarkRows):
      Maxs[RowNum] = DarkRows[RowNum]['MAX']
      Mins[RowNum] = DarkRows[RowNum]['MIN']
      MinRads[RowNum] = DarkRows[RowNum]['MINRAD']
      MaxRads[RowNum] = DarkRows[RowNum]['MAXRAD']
      FZeros[RowNum] = DarkRows[RowNum]['FIRSTZ']
      SZeros[RowNum] = DarkRows[RowNum]['SECONDZ']
      FZerosFit[RowNum] = DarkRows[RowNum]['FIRSTZ_FIT']
      SZerosFit[RowNum] = DarkRows[RowNum]['SECONDZ_FIT']
      MinRadsFit[RowNum] = DarkRows[RowNum]['MINRAD_FIT']
      SumCores[RowNum]  = DarkRows[RowNum]['SUMCORE']
      SumHalos[RowNum]  = DarkRows[RowNum]['SUMHALO']
      SumOuts[RowNum]   = DarkRows[RowNum]['SUMOUT']

    return Maxs, Mins, MinRads, MaxRads, FZeros, SZeros, SumCores,\
           SumHalos, SumOuts, MinRadsFit, FZerosFit, SZerosFit

  ##############################################################################
  ##MODE=2 - Plot the exponential decay for a series of pixel and optionally
  ##         Create a database with the fit coefficients
  elif Mode==2:

    ###NOTE: THE TIME IS SET 
    Times = Persistence_Get_Dark_Times(FileLists[0])+24.
    StartTimes = Persistence_Get_Dark_Times(FileLists[0])

    #Get the values from the slope image
    ##READ THE FILES IN FROM FILELIST
    FitsFiles=ReadFileList(FileLists[0])
    NumFitsFiles = len(FitsFiles)
    SHxRG=HxRG_C(FitsFileName=FitsFiles[1])
    SHxRG.Get_Raw_Header(FitsFiles[1])

    print Times

    if UpdateMinMaxDb == 1:
      DarkTableNameTemp = DarkTableNames[0]
      MinMaxTableName = DarkTableNameTemp.replace('DarksAfter','MinMaxDecay_RevII')
      print MinMaxTableName
      #Create the first table with the PRIMARY KEYS
      if OverWrite == 1:
        cursor.execute('DROP TABLE ' +MinMaxTableName+ ';')
      try:
        cursor.execute('CREATE TABLE '+ MinMaxTableName +\
                    '(PIXID MEDIUMINT NOT NULL PRIMARY KEY,'+\
                     'MAX_A1_1 FLOAT,'+\
                     'MAX_TAU1_1 FLOAT,'+\
                     'MAX_OFF_1 FLOAT,'+\
                     'MAX_ERR_1 FLOAT,'+\
                     'MAX_A1_2 FLOAT,'+\
                     'MAX_TAU1_2 FLOAT,'+\
                     'MAX_A2_2  FLOAT,'+\
                     'MAX_TAU2_2 FLOAT,'+\
                     'MAX_OFF_2 FLOAT,'+\
                     'MAX_ERR_2 FLOAT,'+\
                     'MIN_A1_1 FLOAT,'+\
                     'MIN_TAU1_1 FLOAT,'+\
                     'MIN_OFF_1 FLOAT,'+\
                     'MIN_ERR_1 FLOAT,'+\
                     'MIN_A1_2 FLOAT,'+\
                     'MIN_TAU1_2 FLOAT,'+\
                     'MIN_A2_2  FLOAT,'+\
                     'MIN_TAU2_2 FLOAT,'+\
                     'MIN_OFF_2 FLOAT,'+\
                     'MIN_ERR_2 FLOAT'+\
                     ');')
      except MySQLdb.Error, e:
        print "Error $d: $s" % (e.args[0],e.args[1])
        sys.exit


    #Fitting Function for decay - one time constant
    BadFitFunc = lambda p, x: p[0]*exp(-x/p[1])+p[2]
    BadErrFunc = lambda p, x, y: BadFitFunc(p,x)-y

    #Fitting Function for decay - two time constants
    FitFunc = lambda p, x: p[0]*exp(-x/p[1])+p[2]*exp(-x/p[3])+p[4]
    ErrFunc = lambda p, x, y: FitFunc(p,x)-y

    #Set up for the sequence used to fill the database
    FileNum = 0
    conn.query("SELECT * FROM "+ SlopeTableNames[0]+" where WELL_PERCENT > 0.5;")
    SatRes     = conn.store_result()
    SatRows    = SatRes.fetch_row(maxrows=0, how=1)
    NumSatRows = SatRes.num_rows() 
    PixIDs   = zeros(NumSatRows,dtype=int32)
    WellPcts = zeros(NumSatRows,dtype=float32)
    SatRads  = zeros(NumSatRows,dtype=float32)

    #Hold containers for fit coefficients
    Maxp1s = zeros([NumSatRows,5], dtype=float32)
    Minp1s = zeros([NumSatRows,5], dtype=float32)

    #Get values from primary table and then access Dark table for each Pixel
    for SRowNum in arange(NumSatRows):

      PixIDs[SRowNum]   = SatRows[SRowNum]['PIXID']
      WellPcts[SRowNum] = SatRows[SRowNum]['WELL_PERCENT']
      SatRads[SRowNum]  = SatRows[SRowNum]['SAT_RAD']

      NewMode = 1
      if NewMode == 0:
        #The old mode only looked at the integrated signal at READNUM=9
        Query = "SELECT * FROM "+ DarkTableNames[0]+\
               " where READNUM=9 and "\
              +" PixID="+str(PixIDs[SRowNum])+";"
      else:
        #The new mode looks at the dark current rate
        Query = "SELECT * FROM "+ DarkTableNames[0]+\
               " where PixID="+str(PixIDs[SRowNum])+";"

      conn.query(Query)
      DarkRes      = conn.store_result()
      DarkRows     = DarkRes.fetch_row(maxrows=0, how=1)
      NumDarkRows  = DarkRes.num_rows()
      Maxs     = zeros(NumDarkRows,dtype=float32)
      Mins     = zeros(NumDarkRows,dtype=float32)
      MinRads  = zeros(NumDarkRows,dtype=float32)
      MaxRads  = zeros(NumDarkRows,dtype=float32)
      FZeros   = zeros(NumDarkRows,dtype=float32)
      SZeros   = zeros(NumDarkRows,dtype=float32)
      SumCores = zeros(NumDarkRows,dtype=float32)
      SumHalos = zeros(NumDarkRows,dtype=float32)
      SumOuts  = zeros(NumDarkRows,dtype=float32)

      for DRowNum in arange(NumDarkRows):
        Maxs[DRowNum] = DarkRows[DRowNum]['MAX']
        Mins[DRowNum] = DarkRows[DRowNum]['MIN']
        MinRads[DRowNum] = DarkRows[DRowNum]['MINRAD']
        MaxRads[DRowNum] = DarkRows[DRowNum]['MAXRAD']
        FZeros[DRowNum] = DarkRows[DRowNum]['FIRSTZ']
        SZeros[DRowNum] = DarkRows[DRowNum]['SECONDZ']
        SumCores[DRowNum] = DarkRows[DRowNum]['SUMCORE']
        SumHalos[DRowNum] = DarkRows[DRowNum]['SUMHALO']
        SumOuts[DRowNum]  = DarkRows[DRowNum]['SUMOUT']

      #Start by assuming good fit, if failure , BadFit = 1
      BadFit = 0
     
      if NewMode == 0:
        #Do 2 Time Constant Fit
        Maxp0=[float(Maxs[0]), 18., float(Maxs[0])/10, 70., 10]
        Maxp1, Success = scipy.optimize.leastsq(ErrFunc, Maxp0[:], \
              args = (Times, Maxs), full_output=0,\
              maxfev=1000000.)

      else:
        ##CALCULATE RATE OF CHANGE -- Dark current
        NReads    = SHxRG.NReads-1
        DarkRates = []
        Times     = []
        for File in arange(NumFiles):
          for ReadNum in arange(NReads):
            if ReadNum == 0:
              DarkRate   = Maxs[File*NReads+ReadNum]/SHxRG.FrameTime
              Time       = StartTimes[File]+SHxRG.FrameTime*(1+SHxRG.NResets)
            else:
              DarkRate   = (Maxs[File*NReads+ReadNum] - Maxs[File*NReads+ReadNum-1])/ \
                   SHxRG.FrameTime
              Time       = StartTimes[File]+(ReadNum+SHxRG.NResets+1)*HxRG.FrameTime
            DarkRates.append(DarkRate)
            Times.append(Time)

        #Turn them into arrays
        DarkRates = array(DarkRates, dtype=double)
        Times     = array(Times,     dtype=double)

        #Now fit the dark current
        N1, Tau1, N2, Tau2, Off, Success = FitDecay(Times, DarkRates, \
            TvFlag=TvFlag, AttFit=2, Off=0, ReturnSuccess=1)
        Maxp1 = [N1, Tau1, N2, Tau2, Off]
      if Success !=1 : BadFit = 1
      #Determine the min and max time constants
      if Maxp1[1] > Maxp1[3]:
         MaxTau1_2 = Maxp1[1]
         MaxA1_2   = Maxp1[0]
         MaxTau2_2 = Maxp1[3]
         MaxA2_2   = Maxp1[2]
      else:
         MaxTau1_2 = Maxp1[3]
         MaxA1_2   = Maxp1[2]
         MaxTau2_2 = Maxp1[1]
         MaxA2_2   = Maxp1[0]
      MaxOff_2 = Maxp1[4]

      #Fit with one time constant
      BMaxp0=[float(Maxs[0]),24.,10]
      BMaxp1, Success = scipy.optimize.leastsq(BadErrFunc, BMaxp0[:], \
              args = (Times, DarkRates), full_output=0,\
              maxfev=1000000.)
      if Success !=1 : BadFit = 1
      MaxA1_1   = BMaxp1[0]
      MaxTau1_1 = BMaxp1[1]
      MaxOff_1  = BMaxp1[2]

      #Compute Erros
      MaxFit=Maxp1[0]*exp(-Times/Maxp1[1])+Maxp1[2]*exp(-Times/Maxp1[3])+\
             Maxp1[4]
      MaxErr_2=std(MaxFit-DarkRates)
      BMaxFit=BMaxp1[0]*exp(-Times/BMaxp1[1])+BMaxp1[2]
      MaxErr_1=std(BMaxFit-DarkRates)
 
      if TvFlag == 1:
        mplot.clf()
        mplot.plot(Times,DarkRates,'ro')
        mplot.plot(Times,MaxFit)
        mplot.hold(True)
      if Verbosity == 1:
        print '\n'
        print 'PIXID = ' + str(PixIDs[SRowNum])
        print 'Max Vals:'
        print 'Max1: ' + str(Maxp1[0])+ ' , T1 : '+str(Maxp1[1])
        print 'Max2: ' + str(Maxp1[2])+ ' , T1 : '+str(Maxp1[3])
        print 'Max Off: ' + str(Maxp1[4])
        print 'Ratio: '+ str(Maxp1[2]/Maxp1[0])

      #Do 2 Time Constant Fit
      if NewMode == 0: 
        Minp0=[float(Mins[0]),20.,float(Mins[0])/10, 80.,-5]
        Minp1, Success = scipy.optimize.leastsq(ErrFunc, Minp0[:], \
              args = (Times, Mins), full_output=0,\
              maxfev=1000000.)
      else: 
        ##CALCULATE RATE OF CHANGE -- Dark current
        NReads    = SHxRG.NReads-1
        DarkRates = []
        Times     = []
        for File in arange(NumFiles):
          for ReadNum in arange(NReads):
            if ReadNum == 0:
              DarkRate   = Mins[File*NReads+ReadNum]/SHxRG.FrameTime
              Time       = StartTimes[File]+SHxRG.FrameTime*(1+SHxRG.NResets)
            else:
              DarkRate   = (Mins[File*NReads+ReadNum] - Mins[File*NReads+ReadNum-1])/ \
                   SHxRG.FrameTime
              Time       = StartTimes[File]+(ReadNum+SHxRG.NResets+1)*HxRG.FrameTime
            DarkRates.append(DarkRate)
            Times.append(Time)

        #Turn them into arrays
        DarkRates = array(DarkRates, dtype=double)
        Times     = array(Times,     dtype=double)

        #Now fit the dark current
        N1, Tau1, N2, Tau2, Off, Success = FitDecay(Times, DarkRates, \
          TvFlag=TvFlag, AttFit=2, Off=0, ReturnSuccess=1)
        Minp1 = [N1, Tau1, N2, Tau2, Off]

      if Success !=1 : BadFit = 1
      
      if Minp1[1] > Minp1[3]:
         MinTau1_2 = Minp1[1]
         MinA1_2   = Minp1[0]
         MinTau2_2 = Minp1[3]
         MinA2_2   = Minp1[2]
      else:
         MinTau1_2 = Minp1[3]
         MinA1_2   = Minp1[2]
         MinTau2_2 = Minp1[1]
         MinA2_2   = Minp1[0]
      MinOff_2 = Minp1[4]

      #Do 1 Time Constant Fit 
      BMinp0=[float(Mins[0]),20.,-5]
      BMinp1, Success = scipy.optimize.leastsq(BadErrFunc, BMinp0[:], \
              args = (Times, DarkRates), full_output=0,\
              maxfev=1000000.)
      if Success !=1: BadFit = 1
      MinA1_1   = BMinp1[0]
      MinTau1_1 = BMinp1[1]
      MinOff_1  = BMinp1[2]

      #Compute Erros 
      MinFit=Minp1[0]*exp(-Times/Minp1[1])+Minp1[2]*exp(-Times/Minp1[3])+\
             Minp1[4] 
      MinErr_2=std(MinFit-DarkRates)
      BMinFit=BMinp1[0]*exp(-Times/BMinp1[1])+BMinp1[2]
      MinErr_1=std(BMinFit-DarkRates)

      if TvFlag == 1:
        mplot.plot(Times,DarkRates,'bo') 
        mplot.plot(Times,MinFit)
      if Verbosity == 1:
        print 'Min Vals:'
        print 'Min1: ' + str(Minp1[0])+ ' , T1 : '+str(Minp1[1])
        print 'Min2: ' + str(Minp1[2])+ ' , T1 : '+str(Minp1[3])
        print 'Min Off: ' +str(Minp1[4])
        print 'Ratio: '+ str(Minp1[2]/Minp1[0])
      Maxp1s[SRowNum,:]=Maxp1
      Minp1s[SRowNum,:]=Minp1
      if UpdateMinMaxDb == 1 and BadFit == 0:

         cursor.execute("INSERT INTO "+MinMaxTableName+" VALUES("+\
                   str(PixIDs[SRowNum])+","+\
                   str(MaxA1_1)+","+\
                   str(MaxTau1_1)+","+\
                   str(MaxOff_1)+","+\
                   str(MaxErr_1)+","+\
                   str(MaxA1_2)+","+\
                   str(MaxTau1_2)+","+\
                   str(MaxA2_2)+","+\
                   str(MaxTau2_2)+","+\
                   str(MaxOff_2)+","+\
                   str(MaxErr_2)+","+\
                   str(MinA1_1)+","+\
                   str(MinTau1_1)+","+\
                   str(MinOff_1)+","+\
                   str(MinErr_1)+","+\
                   str(MinA1_2)+","+\
                   str(MinTau1_2)+","+\
                   str(MinA2_2)+","+\
                   str(MinTau2_2)+","+\
                   str(MinOff_2)+","+\
                   str(MinErr_2)+")")

      if TvFlag == 1:
        time.sleep(4)
    return Minp1s, Maxp1s

  ##############################################################################
  #MODE 3 - Return Coefficients from fit to Min/Max Decay
  ##############################################################################
  if Mode == 3:
    #Set up for the sequence used to fill the database
    FileNum = 0
    #Get the table names
    DarkTableNameTemp = DarkTableNames[0]
    SlopeTableName  = SlopeTableNames[0]
    MinMaxTableName = DarkTableNameTemp.replace('DarksAfter','MinMaxDecay_RevII')

    conn.query("SELECT * FROM "+ SlopeTableName+" , " +MinMaxTableName+\
               " WHERE MAX_TAU1_2 > 2 and MAX_TAU2_2 > 2 and "+\
               " MIN_TAU1_2 > 2 and MIN_TAU2_2 > 2 and "+\
                SlopeTableName+'.PIXID='+\
                MinMaxTableName+'.PIXID;')
    SatRes     = conn.store_result()
    SatRows    = SatRes.fetch_row(maxrows=0, how=1)
    NumSatRows = SatRes.num_rows()
    PixIDs     = zeros(NumSatRows,dtype=int32)
    WellPcts   = zeros(NumSatRows,dtype=float32)
    SatRads    = zeros(NumSatRows,dtype=float32)
    MaxA1_1s   = zeros(NumSatRows,dtype=float32)
    MaxTau1_1s = zeros(NumSatRows,dtype=float32)
    MaxErr_1s  = zeros(NumSatRows,dtype=float32)
    MaxA1_2s   = zeros(NumSatRows,dtype=float32)
    MaxTau1_2s = zeros(NumSatRows,dtype=float32)
    MaxA1_2s   = zeros(NumSatRows,dtype=float32)
    MaxTau1_2s = zeros(NumSatRows,dtype=float32)
    MaxA2_2s   = zeros(NumSatRows,dtype=float32)
    MaxTau2_2s = zeros(NumSatRows,dtype=float32)
    MaxErr_2s  = zeros(NumSatRows,dtype=float32)
    MinA1_1s   = zeros(NumSatRows,dtype=float32)
    MinTau1_1s = zeros(NumSatRows,dtype=float32)
    MinA1_2s   = zeros(NumSatRows,dtype=float32)
    MinErr_1s  = zeros(NumSatRows,dtype=float32)
    MinTau1_2s = zeros(NumSatRows,dtype=float32)
    MinA1_2s   = zeros(NumSatRows,dtype=float32)
    MinTau1_2s = zeros(NumSatRows,dtype=float32)
    MinA2_2s   = zeros(NumSatRows,dtype=float32)
    MinTau2_2s = zeros(NumSatRows,dtype=float32)
    MinErr_2s  = zeros(NumSatRows,dtype=float32)
    
    #Get values from primary table and then access Dark table for each Pixel
    for RowNum in arange(NumSatRows):
      PixIDs[RowNum]     = SatRows[RowNum]['PIXID']
      WellPcts[RowNum]   = SatRows[RowNum]['WELL_PERCENT']
      SatRads[RowNum]    = SatRows[RowNum]['SAT_RAD']
      MaxA1_1s[RowNum]   = SatRows[RowNum]['MAX_A1_1']
      MaxTau1_1s[RowNum] = SatRows[RowNum]['MAX_TAU1_1']
      MaxErr_1s[RowNum]  = SatRows[RowNum]['MAX_ERR_1']
      MaxA1_2s[RowNum]   = SatRows[RowNum]['MAX_A1_2']
      MaxTau1_2s[RowNum] = SatRows[RowNum]['MAX_TAU1_2']
      MaxA2_2s[RowNum]   = SatRows[RowNum]['MAX_A2_2']
      MaxTau2_2s[RowNum] = SatRows[RowNum]['MAX_TAU2_2']
      MaxErr_2s[RowNum]  = SatRows[RowNum]['MAX_ERR_2']
      MinA1_1s[RowNum]   = SatRows[RowNum]['MIN_A1_1']
      MinTau1_1s[RowNum] = SatRows[RowNum]['MIN_TAU1_1']
      MinErr_1s[RowNum]  = SatRows[RowNum]['MIN_ERR_1']
      MinA1_2s[RowNum]   = SatRows[RowNum]['MIN_A1_2']
      MinTau1_2s[RowNum] = SatRows[RowNum]['MIN_TAU1_2']
      MinA2_2s[RowNum]   = SatRows[RowNum]['MIN_A2_2']
      MinTau2_2s[RowNum] = SatRows[RowNum]['MIN_TAU2_2']
      MinErr_2s[RowNum]  = SatRows[RowNum]['MIN_ERR_2']

    return PixIDs, WellPcts, SatRads, MaxA1_1s, MaxTau1_1s, MaxErr_1s,\
           MaxA1_2s, MaxTau1_2s, MaxA2_2s, MaxTau2_2s, MaxErr_2s,\
           MinA1_1s, MinTau1_1s, MinErr_1s,\
           MinA1_2s, MinTau1_2s, MinA2_2s, MinTau2_2s, MinErr_2s


  ##############################################################################
  ##MODE=4 - Return all values for one pixel from FILE=0 to FILE=9
  ##############################################################################
  elif Mode==4:

    conn.query("SELECT * FROM "+ DarkTableNames[0]+\
               " where FILENUM < 12 and PixID="+str(PixID)+";")
    DarkRes      = conn.store_result()
    DarkRows     = DarkRes.fetch_row(maxrows=0, how=1)
    NumDarkRows  = DarkRes.num_rows()
    Maxs      = zeros(NumDarkRows,dtype=float32)
    Mins      = zeros(NumDarkRows,dtype=float32)
    MinRads   = zeros(NumDarkRows,dtype=float32)
    MaxRads   = zeros(NumDarkRows,dtype=float32)
    FZeros    = zeros(NumDarkRows,dtype=float32)
    SZeros    = zeros(NumDarkRows,dtype=float32)
    FZerosFit = zeros(NumDarkRows,dtype=float32)
    SZerosFit = zeros(NumDarkRows,dtype=float32)
    SumCores  = zeros(NumDarkRows,dtype=float32)
    SumHalos  = zeros(NumDarkRows,dtype=float32)
    SumOuts   = zeros(NumDarkRows,dtype=float32)

    for RowNum in arange(NumDarkRows):
      Maxs[RowNum] = DarkRows[RowNum]['MAX']
      Mins[RowNum] = DarkRows[RowNum]['MIN']
      MinRads[RowNum]   = DarkRows[RowNum]['MINRAD']
      MaxRads[RowNum]   = DarkRows[RowNum]['MAXRAD']
      FZeros[RowNum]    = DarkRows[RowNum]['FIRSTZ']
      SZeros[RowNum]    = DarkRows[RowNum]['SECONDZ']
      FZerosFit[RowNum] = DarkRows[RowNum]['FIRSTZ_FIT']
      SZerosFit[RowNum] = DarkRows[RowNum]['SECONDZ_FIT']
      SumCores[RowNum]  = DarkRows[RowNum]['SUMCORE']
      SumHalos[RowNum]  = DarkRows[RowNum]['SUMHALO']
      SumOuts[RowNum]   = DarkRows[RowNum]['SUMOUT']

    return Maxs, Mins, MinRads, MaxRads, FZeros, SZeros, SumCores,\
           SumHalos, SumOuts, FZerosFit, SZerosFit
#####################################################################################
##Return_PersistenceFit_DbQuantities
##
##PURPOSE: 
##To extract the persistence quanitities from the PersistenceFitting 
##databases created with the Persistence_Create_Database.py script and 
##return some quantities.  This database contains additional fitting constants
##to the orginal PersistenceExpI database. 
##
##INPUTS:
##
##          DetStr          - 'H1RG-022','H2RG-32-147', or 'H4RG-10-007' 
##          ElecSt          - 'ASIC' or 'LEACH'
##          Dates           - A string array containing the dates in the path 
##          NReads          - A list with the number of reads in the images
##          NDarkReads      - A listwith the number of 
##          DatabaseName    - Name of the database to use
##          SlopeTableNames - A string array containing the names of the
##                            databases with the saturation parameters 
##                            for each star
##          DarkTableNames  - A string array containing the names of the 
##                            database with the dark parameters for each star
##
##          SlopeFiles      - A string array containing the paths to the slope
##                            files reduced from the saturation exposures
##          FileLists       - A string array containing the paths to the dark
##                            exposures taken after saturation
##          QueryString     - The identifier for the rows that are sought.
##                            Should be a string with the form:
##                               "WHERE " + Qualifiers + " "
##                            if MODE == 1, QueryString == FILE_PIXID
##          PIXID           - The pixel ID key in the database.  This will be used
##                            in mode 1 to obtain one specific pixel
##          HxRG            - An instance of the HxRG class
##          TvFlag: int
##                            0 - Don't plot
##                            1 - Plot quantities as script runs
##          ExpFun1: int
##            Choice of the function to fit the radial profile for a given read
##            1 - A*Cos(B*r^C)*Exp(-r^2/D)
##            2 - A*Cos(B*r^C)*Exp(-r^2/D)+E
##            3 - A*Cos(r^C/(2*pi))*Exp(-r^2/D)+E
##            4 - A*Cos(B*r^C)*r**D
##            NOTE: For all database entries ExpFunc=1 was used.
##          ExpFun3: int
##            Function to fit the overall rise for each exposure and decay with 
##            mutliple resets.  B and D are time constants, to is the time 
##            since the array was shuttered and t is the time since reset.
##          Verbosity: int
##                            0 - don't print much
##                            1 - print the values
##          UpdateMinMaxDb:int
##                            If we are in mode 2, 
##                            0 - Don't update the Min, Max database
##                            1 - Update the Min, Max database
##          OverWrite: int 
##                            0 - Don't destroy the database
##                            1 - Overwrite the database if it exists
##          Mode            - 0 - Get all of the values of the persistent 
##                                regions for a certain readnum and filenum
##                                after saturation
##                            1 - Return values for pixel given by PIXID based
##                                upon QueryString
##                            2 - Plot the decays for a series of pixels
##                                If UpdateMinMaxDb == 1, the decay time 
##                                constants will be written to a new database
##                                called [Object]_MinMax_[NREADS]Reads_[Filter]
##                            
##EXAMPLES:
##FilePixIDs, ReadNums, FileNums, Fit_C0s, Fit_C1s, Fit_C2s, Fit_C3s, Fit_C4s=Return_PersistenceFit_DbQuantities('H2RG-32-147', 'ASIC', 'M77', '', 0)

###########################################################################

def Return_PersistenceFit_DbQuantities(DetStr, ElecStr, ObjectName,\
                          QueryString, Mode,\
                          PixID=1000, HxRG=0, TvFlag=0, Verbosity=0,\
                          UpdateMinMaxDb=0, OverWrite=0, ThisFilter='I',\
                          ExpFunc1 = 3) :


  #Get the HxRG instance
  SHxRG = HxRG_C(DetStr=DetStr, ElecStr=ElecStr, ObjectName = ObjectName)
  #Determine Database + Table Names
  if ExpFunc1 == 2:
    DataBaseName       = 'PersistenceFitting'
  elif ExpFunc1 == 3:
    DataBaseName       = 'PersistenceFitting4'

  #If dark files occur after, call it dark
  if ObjectName.find('Dark') == -1 :
    TemporalTableName  = SHxRG.DetStrMySQL+'_'+SHxRG.ElecStr+'_TemporalFits_Illum'
    SpatialTableName   = SHxRG.DetStrMySQL+'_'+SHxRG.ElecStr+'_SpatialFits_Illum'
    SlopeTableName     = SHxRG.DetStrMySQL+'_'+SHxRG.ElecStr+'_Slopes_Illum'
  else:
    TemporalTableName  = SHxRG.DetStrMySQL+'_'+SHxRG.ElecStr+'_TemporalFits_Dark'
    SpatialTableName   = SHxRG.DetStrMySQL+'_'+SHxRG.ElecStr+'_SpatialFits_Dark'
    SlopeTableName     = SHxRG.DetStrMySQL+'_'+SHxRG.ElecStr+'_Slopes_Dark'

  ##OPEN THE DATABASE
  try:
    conn=MySQLdb.connect (host="localhost",
                         user="root",
                         passwd="mysql",
                         db=DataBaseName,
                         unix_socket="/tmp/mysql.sock")
  except MySQLdb.Error, e:
    print "Error $d: $s" % (e.args[0],e.args[1])
    sys.exit

  cursor=conn.cursor()

  if Mode == 0:
    Query = "SELECT "+SpatialTableName+".FILE_PIXID, READNUM, FILENUM, "+\
             "FIT_C0, FIT_C1, FIT_C2, FIT_C3, FIT_C4, "+\
             "FILTER,"+SlopeTableName+".FWHM FROM " + \
             SpatialTableName + "," + TemporalTableName + "," + SlopeTableName + \
             " WHERE " + \
             SpatialTableName+".FILE_PIXID = "+TemporalTableName+".FILE_PIXID AND "+\
             SpatialTableName+".FILE_PIXID = "+SlopeTableName+".FILE_PIXID"+\
             " AND NUMFILES = 6 AND FILTER = '"+ThisFilter+"'"+QueryString+";"
    print 'Your query string is :'
    print '----------------------'
    print Query
    print '----------------------'

    conn.query(Query)
    SatRes       = conn.store_result()
    SatRows      = SatRes.fetch_row(maxrows=0, how=1)
    NumSatRows   = SatRes.num_rows() 
    FilePixIDs   = zeros(NumSatRows,dtype=chararray)
    FileNums     = zeros(NumSatRows,dtype=int16)
    ReadNums     = zeros(NumSatRows,dtype=int16)
    Fit_C0s      = zeros(NumSatRows,dtype=float32)
    Fit_C1s      = zeros(NumSatRows,dtype=float32)
    Fit_C2s      = zeros(NumSatRows,dtype=float32)
    Fit_C3s      = zeros(NumSatRows,dtype=float32)
    Fit_C4s      = zeros(NumSatRows,dtype=float32)
    Filters      = zeros(NumSatRows,dtype=chararray) 
   
    #Get values from primary table and then access Dark table for each Pixel
    for RowNum in arange(NumSatRows):
      FilePixIDs[RowNum]   = SatRows[RowNum]['FILE_PIXID']
      ReadNums[RowNum]     = SatRows[RowNum]['READNUM']
      FileNums[RowNum]     = SatRows[RowNum]['FILENUM']
      Fit_C0s[RowNum]      = SatRows[RowNum]['FIT_C0']
      Fit_C1s[RowNum]      = SatRows[RowNum]['FIT_C1']
      Fit_C2s[RowNum]      = SatRows[RowNum]['FIT_C2']
      Fit_C3s[RowNum]      = SatRows[RowNum]['FIT_C3']
      Fit_C4s[RowNum]      = SatRows[RowNum]['FIT_C4']
      Filters[RowNum]      = SatRows[RowNum]['FILTER']

    return FilePixIDs, ReadNums, FileNums, Fit_C0s, Fit_C1s, Fit_C2s, Fit_C3s, Fit_C4s, Filters

  elif Mode == 1:
    Query = "SELECT "+SpatialTableName+".FILE_PIXID, READNUM, FILENUM, "+\
             "FIT_C0, FIT_C1, FIT_C2, FIT_C3, FIT_C4, "+\
             "FILTER FROM " + \
             SpatialTableName + "," + TemporalTableName + "," +SlopeTableName + \
             " WHERE " + \
             SpatialTableName+".FILE_PIXID = " + "'"+ QueryString +"';"

    print 'Your query string is :'
    print '----------------------'
    print Query
    print '----------------------'

    conn.query(Query)
    SatRes       = conn.store_result()
    SatRows      = SatRes.fetch_row(maxrows=0, how=1)
    NumSatRows   = SatRes.num_rows() 
    FilePixIDs   = zeros(NumSatRows,dtype=chararray)
    FileNums     = zeros(NumSatRows,dtype=int16)
    ReadNums     = zeros(NumSatRows,dtype=int16)
    Fit_C0s      = zeros(NumSatRows,dtype=float32)
    Fit_C1s      = zeros(NumSatRows,dtype=float32)
    Fit_C2s      = zeros(NumSatRows,dtype=float32)
    Fit_C3s      = zeros(NumSatRows,dtype=float32)
    Fit_C4s      = zeros(NumSatRows,dtype=float32)
    Filters      = zeros(NumSatRows,dtype=chararray) 
   
    #Get values from primary table and then access Dark table for each Pixel
    for RowNum in arange(NumSatRows):
      FilePixIDs[RowNum]   = SatRows[RowNum]['FILE_PIXID']
      ReadNums[RowNum]     = SatRows[RowNum]['READNUM']
      FileNums[RowNum]     = SatRows[RowNum]['FILENUM']
      Fit_C0s[RowNum]      = SatRows[RowNum]['FIT_C0']
      Fit_C1s[RowNum]      = SatRows[RowNum]['FIT_C1']
      Fit_C2s[RowNum]      = SatRows[RowNum]['FIT_C2']
      Fit_C3s[RowNum]      = SatRows[RowNum]['FIT_C3']
      Fit_C4s[RowNum]      = SatRows[RowNum]['FIT_C4']
      Filters[RowNum]      = SatRows[RowNum]['FILTER']

    return FilePixIDs, ReadNums, FileNums, Fit_C0s, Fit_C1s, Fit_C2s, Fit_C3s, Fit_C4s, Filters

