def addDataSession(self,
                       slacNum,
                       container,
                       refGradVal=None,
                       calibSession=None):
        # type: (int, Cavity, float, CalibDataSession) -> Q0DataSession

        indices = self.idxMap[slacNum]

        fileReader, rows = self.getRowsAndFileReader(slacNum)

        # Unclear if this is actually necessary, but the idea is to have the
        # output of json.dumps be ordered by index number
        options = OrderedDict()

        for row in fileReader:

            # We could theoretically have hundreds of results, and that seems
            # like a seriously unnecessary number of options to show. This
            # asks the user if they want to keep searching for more every 10
            # hits
            if (len(options) + 1) % 10 == 0:
                printOptions(options)
                showMore = isYes("Search for more options? ")
                if not showMore:
                    break

            grad = float(row[indices["gradIdx"]])
            cavNum = int(row[indices["cavNumIdx"]])

            # The files are per cryomodule, so there's a lot of different
            # cavities in the file. We check to make sure that we're only
            # presenting the options for the requested cavity at the requested
            # gradient (by just skipping the irrelevant ones)
            if (grad != refGradVal) or (cavNum != container.cavNum):
                continue

            addOption(csvRow=row,
                      lineNum=fileReader.line_num,
                      indices=indices,
                      options=options)

        selection = getSelection(duration=2,
                                 suffix="Q0 Measurement",
                                 options=options)

        # If using an existing data session
        if selection != max(options):
            selectedRow = compatibleNext(reader([rows[selection - 1]]))
            refHeatLoad = float(selectedRow[indices["refHeatIdx"]])
            refHeatLoadAct = float(selectedRow[indices["refHeatActIdx"]])
            return container.addDataSessionFromRow(selectedRow, indices,
                                                   refHeatLoad, refHeatLoadAct,
                                                   calibSession, refGradVal)

        else:
            (Q0Sess, self.parent.valveParams) = container.runQ0Meas(
                refGradVal, calibSession, self.valveParams)
            return Q0Sess
    def addDataSession(self,
                       slacNum,
                       container,
                       refGradVal=None,
                       calibSession=None):
        # type: (int, Cryomodule, float, CalibDataSession) -> CalibDataSession

        indices = self.idxMap[slacNum]

        fileReader, rows = self.getRowsAndFileReader(slacNum)

        # Unclear if this is actually necessary, but the idea is to have the
        # output of json.dumps be ordered by index number
        options = OrderedDict()

        for row in fileReader:

            if (len(options) + 1) % 10 == 0:
                printOptions(options)
                showMore = isYes("Search for more options? ")
                if not showMore:
                    break

            addOption(csvRow=row,
                      lineNum=fileReader.line_num,
                      indices=indices,
                      options=options)

        selection = getSelection(duration=5,
                                 suffix="calibration",
                                 options=options)

        if selection != max(options):

            calibRow = compatibleNext(reader([rows[selection - 1]]))

            if not container:
                container = Cryomodule(slacNum,
                                       calibRow[indices["jlabNumIdx"]])

            refHeatLoad = float(calibRow[indices["refHeatIdx"]])
            refHeatLoadAct = float(calibRow[indices["refHeatActIdx"]])

            return container.addDataSessionFromRow(calibRow, indices,
                                                   refHeatLoad, refHeatLoadAct)

        else:
            if not container:
                container = Cryomodule(
                    slacNum,
                    getNumInputFromLst("JLab cryomodule"
                                       " number: ", [2, 3], int))

            (calibSession, self.parent.valveParams) = container.runCalibration(
                self.parent.valveParams)

            return calibSession
    def getCalibAndDesGrads(self, row, slacNum):
        desiredGradients = {}
        options = {
            1: "Full module calibration",
            2: "Single cavity calibration (to be used for each cavity in row)"
        }
        printOptions(options)
        prompt = "Please select a calibration option (hit enter for option 1): "
        selection = getNumInputFromLst(prompt, options.keys(), int, True)
        if selection == 1:
            if ((slacNum not in self.cryoModules)
                    or (not self.cryoModules[slacNum].calibDataSessions)):
                calibSess = self.cryModManager.addNewCalibration(
                    slacNum=slacNum)

            else:
                options = {}
                idx = 1
                idx2session = {}

                # Multiple rows in the input file may have the same SLAC
                # cryomodule number. However, the user might want to use
                # different calibrations. This is where we give the user the
                # option to reuse a calibration we've already loaded up and
                # processed.
                calibDataSessions = self.cryoModules[slacNum].calibDataSessions
                for _, calibDataSession in calibDataSessions.items():
                    options[idx] = str(calibDataSession)
                    idx2session[idx] = calibDataSession
                    idx += 1

                options[idx] = "Use a different calibration"
                printOptions(options)

                prompt = ("Please select a calibration option"
                          " (hit enter for option 1): ")
                reuseSelection = getNumInputFromLst(prompt, options.keys(),
                                                    int, True)

                reuseCalibration = (reuseSelection != max(options))

                if not reuseCalibration:
                    cryMod = self.cryoModules[slacNum]
                    calibSess = self.cryModManager.addToCryMod(slacNum=slacNum,
                                                               cryMod=cryMod)

                else:
                    calibSess = idx2session[reuseSelection]

        else:
            if slacNum not in self.cryoModules:
                prompt = "LERF cryomodule number for CM{CM}: ".format(
                    CM=slacNum)
                cryoModule = Cryomodule(
                    slacNum, getNumInputFromLst(prompt, [2, 3], int))
                self.cryoModules[slacNum] = cryoModule

        for _, cavity in self.cryoModules[slacNum].cavities.items():
            cavGradIdx = self.header.index(
                "Cavity {NUM} Gradient".format(NUM=cavity.cavNum))
            try:
                gradDes = float(row[cavGradIdx])
            except ValueError:
                continue

            desiredGradients[cavity.cavNum] = gradDes

        if selection == 2:
            cavNum = getNumInputFromLst(
                "Single cavity calibration to be used (cavity number): ",
                self.cryoModules[slacNum].cavities.keys(), int, True)
            # for cavNum in desiredGradients.keys():
            cavity = self.cryoModules[slacNum].cavities[cavNum]
            if not cavity.calibDataSessions:
                calibSess = self.cavManager.addNewCalibration(slacNum=slacNum,
                                                              cavity=cavity)

            else:
                options = {}
                idx = 1
                idx2session = {}

                # Multiple rows in the input file may have the same SLAC
                # cryomodule number. However, the user might want to use
                # different calibrations. This is where we give the user the
                # option to reuse a calibration we've already loaded up and
                # processed.
                calibDataSessions = cavity.calibDataSessions
                for _, calibDataSession in calibDataSessions.items():
                    options[idx] = str(calibDataSession)
                    idx2session[idx] = calibDataSession
                    idx += 1

                options[idx] = "Use a different calibration"
                printOptions(options)

                prompt = ("Please select a calibration option"
                          " (hit enter for option 1): ")
                selection = getNumInputFromLst(prompt, options.keys(), int,
                                               True)

                reuseCalibration = (selection != max(options))

                if not reuseCalibration:
                    calibSess = self.cavManager.addDataSession(
                        slacNum=slacNum, container=cavity, kind="calib")

                else:
                    calibSess = idx2session[selection]
        return calibSess, desiredGradients
    def parse(self):
        for row in self.csvReader:
            slacNum = int(row[self.slacNumIdx])

            calibSess, desiredGradients = self.getCalibAndDesGrads(
                row, slacNum)

            cryoModule = self.cryoModules[slacNum]

            calibSess.printSessionReport()

            calibCutoffs = [
                str(run.diagnostics["Cutoff"]) for run in calibSess.dataRuns
            ]

            if desiredGradients:

                options = {
                    1: "multi-cavity Q0 measurement",
                    2: "single-cavity Q0 measurements"
                }

                prompt = "Please select a type of measurement for row: {ROW}".format(
                    ROW=row)
                printOptions(options)

                selectedType = getNumInputFromLst(prompt, options.keys(), int,
                                                  True)

                if selectedType == 2:
                    for cavNum, gradDes in desiredGradients.items():
                        if not gradDes:
                            continue

                        fname = (
                            "results/cm{CM}/cav{CAV}/resultsCM{CM}CAV{CAV}.csv"
                            .format(CM=slacNum, CAV=cavNum))

                        if not isfile(fname):
                            compatibleMkdirs(fname)
                            with open(fname, "w+") as f:
                                csvWriter = writer(f, delimiter=',')
                                csvWriter.writerow([
                                    "Cavity", "Gradient", "Q0", "Calibration",
                                    "Q0 Measurement", "Calibration Cutoffs",
                                    "Q0 Cutoffs"
                                ])

                        print("\n---- Cavity {CAV} @ {GRAD} MV/m ----".format(
                            CM=slacNum, CAV=cavNum, GRAD=gradDes))

                        cavity = self.cryoModules[slacNum].cavities[cavNum]

                        q0Sess = self.genQ0Session(desiredGradient=gradDes,
                                                   slacNum=slacNum,
                                                   cavity=cavity,
                                                   calibSession=calibSess)

                        q0s = [
                            q0Sess.dataRuns[runIdx].q0
                            for runIdx in q0Sess.rfRunIdxs
                        ]
                        q0Cutoffs = [
                            str(run.diagnostics["Cutoff"])
                            for run in q0Sess.dataRuns
                        ]

                        with open(fname, "a") as f:
                            csvWriter = writer(f, delimiter=',')
                            csvWriter.writerow([
                                cavity.cavNum, gradDes,
                                '{:.2e}'.format(Decimal(mean(q0s))),
                                str(calibSess),
                                str(q0Sess), " | ".join(calibCutoffs),
                                " | ".join(q0Cutoffs)
                            ])
                else:
                    # desiredGradients = {}
                    # for _, cavity in cryoModule.cavities.items():
                    #     cavGradIdx = self.header.index("Cavity {NUM} Gradient"
                    #                                    .format(NUM=cavity.cavNum))
                    #     try:
                    #         gradDes = float(row[cavGradIdx])
                    #     except ValueError:
                    #         continue
                    #
                    #     desiredGradients[cavity.cavNum] = gradDes

                    fname = "results/cm{CM}/resultsCM{CM}.csv".format(
                        CM=slacNum)

                    if not isfile(fname):
                        compatibleMkdirs(fname)
                        with open(fname, "w+") as f:
                            csvWriter = writer(f, delimiter=',')
                            csvWriter.writerow([
                                "Cavity 1 Gradient", "Cavity 2 Gradient",
                                "Cavity 3 Gradient", "Cavity 4 Gradient",
                                "Cavity 5 Gradient", "Cavity 6 Gradient",
                                "Cavity 7 Gradient", "Cavity 8 Gradient",
                                "Cumulative Gradient", "Q0", "Calibration",
                                "Q0 Measurement", "Calibration Cutoffs",
                                "Q0 Cutoffs"
                            ])

                    q0Sess = self.genMultiQ0Session(
                        desiredGradients=desiredGradients,
                        slacNum=slacNum,
                        cryomodule=cryoModule,
                        calibSession=calibSess)

                    q0s = [
                        q0Sess.dataRuns[runIdx].q0
                        for runIdx in q0Sess.rfRunIdxs
                    ]
                    q0Cutoffs = [
                        str(run.diagnostics["Cutoff"])
                        for run in q0Sess.dataRuns
                    ]

                    with open(fname, "a") as f:
                        csvWriter = writer(f, delimiter=',')

                        # TODO fix this...
                        csvWriter.writerow([
                            slacNum, desiredGradients,
                            '{:.2e}'.format(Decimal(mean(q0s))),
                            str(calibSess),
                            str(q0Sess), " | ".join(calibCutoffs),
                            " | ".join(q0Cutoffs)
                        ])
            self.saveFigs(cryoModule)

        drawAndShow()
    def parse(self):
        for row in self.csvReader:
            slacNum = int(row[self.slacNumIdx])

            if slacNum not in self.cryoModules:
                calibSess = self.cryModManager.addNewCryMod(slacNum=slacNum)

            else:
                options = {}
                idx = 1
                idx2session = {}

                # Multiple rows in the input file may have the same SLAC
                # cryomodule number. However, the user might want to use
                # different calibrations. This is where we give the user the
                # option to reuse a calibration we've already loaded up and
                # processed.
                dataSessions = self.cryoModules[slacNum].dataSessions
                for _, dataSession in dataSessions.items():
                    options[idx] = str(dataSession)
                    idx2session[idx] = dataSession
                    idx += 1

                options[idx] = "Use a different calibration"
                printOptions(options)

                prompt = ("Please select a calibration option"
                          " (hit enter for option 1): ")
                selection = getNumInputFromLst(prompt, options.keys(), int,
                                               True)

                reuseCalibration = (selection != max(options))

                if not reuseCalibration:
                    cryMod = self.cryoModules[slacNum]
                    calibSess = self.cryModManager.addToCryMod(slacNum=slacNum,
                                                               cryMod=cryMod)

                else:
                    calibSess = idx2session[selection]

            cryoModule = self.cryoModules[slacNum]

            calibSess.printSessionReport()

            calibCutoffs = [
                str(run.diagnostics["Cutoff"]) for run in calibSess.dataRuns
            ]

            fname = "results/cm{CM}.csv".format(CM=slacNum)

            if not isfile(fname):
                compatibleMkdirs(fname)
                with open(fname, "w+") as f:
                    csvWriter = writer(f, delimiter=',')
                    csvWriter.writerow([
                        "Cavity", "Gradient", "Q0", "Calibration",
                        "Q0 Measurement", "Calibration Cutoffs", "Q0 Cutoffs"
                    ])

            for _, cavity in cryoModule.cavities.items():
                cavGradIdx = self.header.index(
                    "Cavity {NUM} Gradient".format(NUM=cavity.cavNum))

                try:
                    gradDes = float(row[cavGradIdx])
                except ValueError:
                    continue

                print("\n---- Cavity {CAV} @ {GRAD} MV/m ----".format(
                    CM=slacNum, CAV=cavity.cavNum, GRAD=gradDes))

                q0Sess = self.genQ0Session(refGradVal=gradDes,
                                           slacNum=slacNum,
                                           cavity=cavity,
                                           calibSession=calibSess)

                q0s = [
                    q0Sess.dataRuns[runIdx].q0 for runIdx in q0Sess.rfRunIdxs
                ]
                q0Cutoffs = [
                    str(run.diagnostics["Cutoff"]) for run in q0Sess.dataRuns
                ]

                with open(fname, "a") as f:
                    csvWriter = writer(f, delimiter=',')
                    csvWriter.writerow([
                        cavity.cavNum, gradDes,
                        '{:.2e}'.format(Decimal(mean(q0s))),
                        str(calibSess),
                        str(q0Sess), " | ".join(calibCutoffs),
                        " | ".join(q0Cutoffs)
                    ])

            self.saveFigs(cryoModule)

        drawAndShow()