def calcEff(cName, scandate, vfatList, latBin, bkgSub=False):
    """
    Returns a tuple of (eff, sigma_eff)
    
    cName - chamber name, i.e. the value of a given key of the chamber_config dict
    scandate - scandate of the ultraLatency.py measurement
    vfatList - list of vfats to use for calculating the efficiency
    latBin - latency bin to determine the eff for
    bkgSub - Perform background subtraction
    """

    from anautilities import getDirByAnaType

    import os

    # Setup paths
    dirPath = "%s/%s" % (getDirByAnaType("latency", cName), scandate)
    filename_RAW = dirPath + "/LatencyScanData.root"
    filename_ANA = dirPath + "/LatencyScanData/latencyAna.root"

    # Load data - RAW
    import root_numpy as rp
    import numpy as np
    list_bNames = ["vfatN", "lat", "Nhits", "Nev"]
    try:
        array_VFATData = rp.root2array(filename_RAW, "latTree", list_bNames)
        pass
    except Exception as e:
        print '%s does not seem to exist' % filename_RAW
        print e
        exit(os.EX_NOINPUT)

    # Load data - ANA
    import ROOT as r
    try:
        anaFile = r.TFile(filename_ANA, "READ")
    except Exception as e:
        print '%s does not seem to exist' % filename_ANA
        print e
        exit(os.EX_NOINPUT)

    # Determine hits and triggers
    nTriggers = np.asscalar(np.unique(array_VFATData['Nev']))
    nHits = 0.0
    for vfat in vfatList:
        if bkgSub:
            try:
                gSignalNoBkg = anaFile.Get("grVFATNSignalNoBkg")
                vfatHits = r.Double()
                vfatPos = r.Double()
                gSignalNoBkg.GetPoint(vfat, vfatPos, vfatHits)
                nHits += vfatHits
            except Exception as e:
                print "grVFATNSignalNoBkg not present in TFile %s" % filename_ANA
                print "Maybe you forgot to analyze with the --fit, --latSigRange, and --latNoiseRange options?"
                print e
                exit(os.EX_DATAERR)
        else:
            vfatData = array_VFATData[array_VFATData['vfatN'] == vfat]
            latData = vfatData[vfatData['lat'] == latBin]
            nHits += np.asscalar(latData['Nhits'])

    # Calc Eff & Error
    return (nHits / nTriggers, calcEffErr(nHits / nTriggers, nTriggers))
        # Split the line
        line = line.strip('\n')
        chamberAndScanDatePair = line.rsplit('\t')  #chamber name, scandate
        if len(chamberAndScanDatePair) != 2:
            print "Input format incorrect"
            print "I was expecting a tab-delimited file with each line having 2 entries"
            print "But I received:"
            print "\t%s" % (line)
            print "Exiting"
            exit(os.EX_USAGE)
        tupleChamberAndScanDate = (chamberAndScanDatePair[0],
                                   chamberAndScanDatePair[1])

        # Setup the path
        dirPath = getDirByAnaType(options.anaType.strip("Ana"),
                                  chamberAndScanDatePair[0], options.ztrim)
        if not filePathExists(dirPath, chamberAndScanDatePair[1]):
            print 'Filepath %s/%s does not exist!' % (dirPath, scandate)
            print 'Please cross-check, exiting!'
            outF.Close()
            exit(os.EX_DATAERR)
        filename = "%s/%s/%s" % (dirPath, chamberAndScanDatePair[1],
                                 tree_names[options.anaType][0])

        # Get the Plot and Reset it's Name
        dictPlots[tupleChamberAndScanDate] = overlay_scurve(
            vfat=options.vfat,
            vfatCH=options.strip,
            fit_filename=filename,
            vfatChNotROBstr=options.channels)
def arbitraryPlotter(anaType,
                     listDataPtTuples,
                     rootFileName,
                     treeName,
                     branchName,
                     vfat,
                     vfatCH=None,
                     strip=None,
                     ztrim=4):
    """
    Provides a list of tuples for 1D data where each element is of the form: (indepVarVal, depVarVal, depVarValErr)

    anaType - type of analysis to perform, helps build the file path to the input file(s), from set ana_config.keys()
    listDataPtTuples - list of tuples where each element is of the form: (cName, scandate, indepVar), note indepVar is expected to be numeric
    rootFileName - name of the TFile that will be found in the data path corresponding to anaType
    treeName - name of the TTree inside rootFileName
    branchName - name of a branch inside treeName that the dependent variable will be extracted from
    vfat - vfat number that plots should be made for
    vfatCH - channel of the vfat that should be used, if None an average is performed w/stdev for error bar, mutually exclusive w/strip
    strip - strip of the detector that should be used, if None an average is performed w/stdev for error bar, mutually exclusive w/vfatCH
    """

    from anautilities import filePathExists, getDirByAnaType

    import numpy as np
    import os
    import root_numpy as rp

    # Make branches to load
    listNames = ["vfatN"]
    if vfatCH is not None and strip is None:
        listNames.append("vfatCH")
    elif strip is not None and vfatCH is None:
        listNames.append("ROBstr")
    listNames.append(branchName)

    # Load data
    listData = []
    for dataPt in listDataPtTuples:
        # Get human readable info
        cName = dataPt[0]
        scandate = dataPt[1]
        indepVarVal = dataPt[2]

        # Setup Paths
        dirPath = getDirByAnaType(anaType.strip("Ana"), cName, ztrim)
        if not filePathExists(dirPath, scandate):
            print 'Filepath %s/%s does not exist!' % (dirPath, scandate)
            print 'Please cross-check, exiting!'
            exit(os.EX_DATAERR)
        filename = "%s/%s/%s" % (dirPath, scandate, rootFileName)

        # Get TTree
        try:
            dataFile = r.TFile(filename, "READ")
            dataTree = dataFile.Get(treeName)
            knownBranches = dataTree.GetListOfBranches()
        except Exception as e:
            print '%s may not exist in %s, please cross check' % (treeName,
                                                                  filename)
            print e
            #exit(os.EX_NOTFOUND) #Weird, not found but described in: https://docs.python.org/2/library/os.html#process-management
            exit(os.EX_DATAERR)
            pass

        # Check to make sure listNames are present in dataTree
        for testBranch in listNames:
            if testBranch not in knownBranches:
                print "Branch %s not in TTree %s of file %s" % (
                    branchName, treeName, filename)
                print "Existing Branches are:"
                for realBranch in knownBranches:
                    print realBranch
                print "Please try again using one of the existing branches"
                #exit(os.EX_NOTFOUND) #Weird, not found but described in: https://docs.python.org/2/library/os.html#process-management
                exit(os.EX_DATAERR)

        # Get dependent variable value
        arrayVFATData = rp.tree2array(dataTree, listNames)
        dataThisVFAT = arrayVFATData[arrayVFATData['vfatN'] ==
                                     vfat]  #VFAT Level

        # Close the TFile
        dataFile.Close()

        if vfatCH is not None and strip is None:
            dataThisVFAT = dataThisVFAT[dataThisVFAT['vfatCH'] ==
                                        vfatCH]  #VFAT Channel Level
        elif strip is not None and vfatCH is None:
            dataThisVFAT = dataThisVFAT[dataThisVFAT['ROBstr'] ==
                                        strip]  #Readout Board Strip Level

        depVarVal = np.asscalar(
            np.mean(dataThisVFAT[branchName])
        )  #If a vfatCH/ROBstr obs & chan/strip not give will be avg over all, else a number
        depVarValErr = np.asscalar(
            np.std(dataThisVFAT[branchName])
        )  #If a vfatCH/ROBstr obs & chan/strip not given will be stdev over all, or zero

        #Record this dataPt
        listData.append((indepVarVal, depVarVal, depVarValErr))

    # Return Data
    return listData
def launchAnaArgs(anaType,
                  cName,
                  cType,
                  scandate,
                  scandatetrim=None,
                  ztrim=4.0,
                  chConfigKnown=False,
                  channels=False,
                  panasonic=False,
                  latFit=False,
                  latSigRange=None,
                  latSigMaskRange=None):
    import os
    import subprocess
    from subprocess import CalledProcessError
    from anaInfo import ana_config
    from anautilities import getDirByAnaType
    from gempython.utils.wrappers import runCommand

    #dataPath  = os.getenv('DATA_PATH')
    dirPath = getDirByAnaType(anaType, cName, ztrim)
    elogPath = "%s/%s" % (os.getenv('ELOG_PATH'), scandate)

    print "Analysis Requested: %s" % (anaType)

    #Build Commands
    cmd = [ana_config[anaType]]
    postCmds = []
    postCmds.append(["mkdir", "-p", "%s" % (elogPath)])
    if anaType == "latency":
        dirPath = "%s/%s/" % (dirPath, scandate)
        filename = dirPath + "LatencyScanData.root"
        if not os.path.isfile(filename):
            print "No file to analyze. %s does not exist" % (filename)
            return os.EX_NOINPUT

        cmd.append("--infilename=%s" % (filename))
        cmd.append("--outfilename=%s" % ("latencyAna.root"))

        if latFit:
            cmd.append("--fit")
            cmd.append("--latSigMaskRange=%s" % (latSigMaskRange))
            cmd.append("--latSigRange=%s" % (latSigRange))

        postCmds.append([
            "cp",
            "%s/LatencyScanData/Summary.png" % (dirPath),
            "%s/LatencySumary_%s.png" % (elogPath, cName)
        ])
        postCmds.append([
            "cp",
            "%s/LatencyScanData/MaxHitsPerLatByVFAT.png" % (dirPath),
            "%s/MaxHitsPerLatByVFAT_%s.png" % (elogPath, cName)
        ])
        if latFit:
            postCmds.append([
                "cp",
                "%s/LatencyScanData/SignalOverBkg.png" % (dirPath),
                "%s/SignalOverBkg_%s.png" % (elogPath, cName)
            ])
            postCmds.append([
                "cp",
                "%s/LatencyScanData/SignalNoBkg.png" % (dirPath),
                "%s/SignalNoBkg_%s.png" % (elogPath, cName)
            ])

        pass
    elif anaType == "scurve":
        dirPath = "%s/%s/" % (dirPath, scandate)
        filename = dirPath + "SCurveData.root"
        if not os.path.isfile(filename):
            print "No file to analyze. %s does not exist" % (filename)
            return os.EX_NOINPUT

        cmd.append("--infilename=%s" % (filename))
        cmd.append("--outfilename=%s" % ("SCurveFitData.root"))
        cmd.append("--fit")
        cmd.append("--type=%s" % (cType))
        if channels:
            cmd.append("--channels")
            pass
        if panasonic:
            cmd.append("--panasonic")
            pass

        postCmds.append([
            "cp",
            "%s/SCurveData/Summary.png" % (dirPath),
            "%s/SCurveSummary_%s_ztrim%2.2f.png" % (elogPath, cName, ztrim)
        ])
        postCmds.append([
            "cp",
            "%s/SCurveData/chConfig.txt" % (dirPath),
            "%s/chConfig_%s_ztrim%2.2f.txt" % (elogPath, cName, ztrim)
        ])
        pass
    elif "threshold" in anaType:
        dirPath = "%s/%s/" % (dirPath, scandate)
        filename = dirPath + "ThresholdScanData.root"
        if not os.path.isfile(filename):
            print "No threshold file to analyze. %s does not exist" % (
                filename)
            return os.EX_NOINPUT

        cmd.append("--infilename=%s" % (filename))
        cmd.append("--outfilename=%s" % ("ThresholdPlots.root"))
        if "thresholdvf" in anaType:
            cmd.append("--pervfat")

        if chConfigKnown:
            cmd.append("--chConfigKnown")
            # dirPath_Trim = "%s/%s/trim/z%f/%s/SCurveData_Trimmed/"%(dataPath,cName,ztrim,scandatetrim)
            dirPath_Trim = "%s/%s/SCurveData_Trimmed/" % (getDirByAnaType(
                "trim", cName, ztrim), scandatetrim)
            filename_Trim = dirPath_Trim + "SCurveFitData.root"
            if not os.path.isfile(filename_Trim):
                print "No scurve fit data file to analyze. %s does not exist" % (
                    filename_Trim)
                return os.EX_NOINPUT

            cmd.append("--fileScurveFitTree=%s" % (filename_Trim))
            pass

        postCmds.append([
            "cp",
            "%s/ThresholdScanData/ThreshSummary.png" % (dirPath),
            "%s/ThreshSummary_%s.png" % (elogPath, cName)
        ])
        postCmds.append([
            "cp",
            "%s/ThresholdScanData/ThreshPrunedSummary.png" % (dirPath),
            "%s/ThreshPrunedSummary_%s.png" % (elogPath, cName)
        ])
        postCmds.append([
            "cp",
            "%s/ThresholdScanData/vfatConfig.txt" % (dirPath),
            "%s/vfatConfig_%s.txt" % (elogPath, cName)
        ])
        if chConfigKnown:
            postCmds.append([
                "cp",
                "%s/ThresholdScanData/chConfig_MasksUpdated.txt" % (dirPath),
                "%s/chConfig_MasksUpdated_%s.txt" % (elogPath, cName)
            ])
            pass
        pass
    elif anaType == "trim":
        dirPath = "%s/%s/" % (dirPath, scandate)
        filename = dirPath + "SCurveData_Trimmed.root"
        if not os.path.isfile(filename):
            print "No file to analyze. %s does not exist" % (filename)
            return os.EX_NOINPUT

        cmd.append("--infilename=%s" % (filename))
        cmd.append("--outfilename=%s" % ("SCurveFitData.root"))
        cmd.append("--fit")
        cmd.append("--type=%s" % (cType))
        if channels:
            cmd.append("--channels")
            pass
        if panasonic:
            cmd.append("--panasonic")
            pass

        postCmds.append([
            "cp",
            "%s/SCurveData_Trimmed/Summary.png" % (dirPath),
            "%s/SCurveSummaryTrimmed_%s_ztrim%2.2f.png" %
            (elogPath, cName, ztrim)
        ])
        postCmds.append([
            "cp",
            "%s/SCurveData_Trimmed/chConfig.txt" % (dirPath),
            "%s/chConfigTrimmed_%s_ztrim%2.2f.txt" % (elogPath, cName, ztrim)
        ])
        pass

    #Execute Commands
    try:
        log = file("%s/anaLog.log" % (dirPath), "w")

        returncode = runCommand(cmd, log)
        if returncode != 0:
            print "Error: command exited with non-zero code %d" % returncode
            return returncode
        for item in postCmds:
            returncode = runCommand(item)
            if returncode != 0:
                print "Error: command exited with non-zero code %d" % returncode
                return returncode
            pass
    except CalledProcessError as e:
        print "Caught exception", e
        return -1
        pass
    return 0
def arbitraryPlotter2D(anaType,
                       listDataPtTuples,
                       rootFileName,
                       treeName,
                       branchName,
                       vfat,
                       ROBstr=True,
                       ztrim=4):
    """
    Provides a list of tuples for 2D data where each element is of the (x,y,z) form: (indepVarVal, vfatCHOrROBstr, depVarVal)

    anaType - type of analysis to perform, helps build the file path to the input file(s), from set ana_config.keys()
    listDataPtTuples - list of tuples where each element is of the form: (cName, scandate, indepVar), note indepVar is expected to be numeric
    rootFileName - name of the TFile that will be found in the data path corresponding to anaType
    treeName - name of the TTree inside rootFileName
    branchName - name of a branch inside treeName that the dependent variable will be extracted from
    vfat - vfat number that plots should be made for
    """

    from anautilities import filePathExists, getDirByAnaType

    import numpy as np
    import os
    import root_numpy as rp

    # Make branches to load
    listNames = ["vfatN"]
    strChanName = ""  #Name of channel TBranch, either 'ROBstr' or 'vfatCH'
    if ROBstr:
        listNames.append("ROBstr")
        strChanName = "ROBstr"
    else:
        listNames.append("vfatCH")
        strChanName = "vfatCH"
    listNames.append(branchName)

    # Load data
    listData = []
    for dataPt in listDataPtTuples:
        # Get human readable info
        cName = dataPt[0]
        scandate = dataPt[1]
        indepVarVal = dataPt[2]

        # Setup Paths
        dirPath = getDirByAnaType(anaType.strip("Ana"), cName, ztrim)
        if not filePathExists(dirPath, scandate):
            print 'Filepath %s/%s does not exist!' % (dirPath, scandate)
            print 'Please cross-check, exiting!'
            exit(os.EX_DATAERR)
        filename = "%s/%s/%s" % (dirPath, scandate, rootFileName)

        # Get TTree
        try:
            dataFile = r.TFile(filename, "READ")
            dataTree = dataFile.Get(treeName)
            knownBranches = dataTree.GetListOfBranches()
        except Exception as e:
            print '%s may not exist in %s, please cross check' % (treeName,
                                                                  filename)
            print e
            #exit(os.EX_NOTFOUND) #Weird, not found but described in: https://docs.python.org/2/library/os.html#process-management
            exit(os.EX_DATAERR)
            pass

        # Check to make sure listNames are present in dataTree
        for testBranch in listNames:
            if testBranch not in knownBranches:
                print "Branch %s not in TTree %s of file %s" % (
                    branchName, treeName, filename)
                print "Existing Branches are:"
                for realBranch in knownBranches:
                    print realBranch
                print "Please try again using one of the existing branches"
                #exit(os.EX_NOTFOUND) #Weird, not found but described in: https://docs.python.org/2/library/os.html#process-management
                exit(os.EX_DATAERR)

        # Get dependent variable value - VFAT Level
        arrayVFATData = rp.tree2array(dataTree, listNames)
        dataThisVFAT = arrayVFATData[arrayVFATData['vfatN'] ==
                                     vfat]  #VFAT Level

        # Close the TFile
        dataFile.Close()

        # Get the data for each strip and store it as a tuple in the list to be returned
        for chan in range(0, 128):
            dataThisChan = dataThisVFAT[dataThisVFAT[strChanName] ==
                                        chan]  #Channel Level
            depVarVal = np.asscalar(np.mean(dataThisChan[branchName]))
            listData.append((indepVarVal, chan, depVarVal))
            pass

    # Return Data
    return listData