예제 #1
0
 def readExperiment(self, fnIn, show=True, fullRead=True):
     experiment = PKPDExperiment()
     experiment.load(fnIn, fullRead=fullRead)
     if show:
         self.printSection("Reading %s" % fnIn)
         experiment._printToStream(sys.stdout)
     return experiment
예제 #2
0
class ProtPKPDImportFromText(ProtPKPD):
    #--------------------------- DEFINE param functions --------------------------------------------

    def _defineParams(self, form, type):
        form.addSection('Input')
        inputFileHelp = "Specify a path to desired %s file.\n" % type
        inputFileHelp += "You may specify missing values with NA. You may also use LLOQ and ULOQ (Lower and Upper limit of quantification)\n"
        inputFileHelp += "to specify measurements that are below or above these limits"
        if type == "CSV":
            inputFileHelp += "The field separator must be a semicolon (;), decimal point must be a dot (.).\n"
            inputFileHelp += "The first row must contain the variable names and one of them must be SampleName which will serve as identifier."
        elif type == "ExcelTable":
            inputFileHelp += "The first column must be time, the rest of the columns must be measurements of each one of the individuals\n"
            inputFileHelp += "A column by each individual."
        form.addParam('inputFile',
                      params.PathParam,
                      label="File path",
                      allowsNull=False,
                      help=inputFileHelp)
        if type == "ExcelTable":
            form.addParam(
                'skipLines',
                params.IntParam,
                default=0,
                label='Skip lines',
                help=
                'Skip this amount of lines to reach the header line, the line with the variable names.'
            )
            form.addParam('format',params.EnumParam, choices=["Wide format", "Long format"], default=0,
                          label='Excel format',
                          help='Wide format: 1st column is time, all other columns are the measurements\n'\
                               'Long format: 1st column is the individualID, then all columns are as described by the variables')
            form.addParam(
                'header',
                params.StringParam,
                label='Header format',
                default='ID, t, Cp',
                condition='format==1',
                help=
                'The ID column is compulsory, but it does not need to be the first one. You can skip columns with the keyword SKIP.'
            )
        form.addParam('title',
                      params.StringParam,
                      label="Title",
                      default="My experiment")
        form.addParam('comment',
                      params.StringParam,
                      label="Comment",
                      default="")
        form.addParam('variables', params.TextParam, height=8, width=80, label="Variables", default="",
                      help="Structure: [Variable Name] ; [Units] ; [Type] ; [Role] ; [Comment]\n"\
                           "The variable name should have no space or special character\n"\
                           "Valid units are: h, mg, ug, ug/mL, ...\n"\
                           "Type is either numeric or text\n"\
                           "Role is either time, label or measurement\n"\
                           "The comment may be empty\n"\
                           "\nIt is important that there are three semicolons (none of them may be missing even if the comment is not present).\n"\
                           "Examples:\n"\
                           "t ; h ; numeric ; time ; \n"\
                           "Cp ; ug/mL ; numeric ; measurement ; plasma concentration\n"\
                           "weight ; g ; numeric; label ; weight of the animal\n"\
                           "sex ; none ; text ; label ; sex of the animal\n")
        form.addParam('vias', params.TextParam, height=8, width=80, label="Vias",
                      help="[ViaName]; [ViaType]; [tlag]; [bioavailability]"\
                       "Valid ViaTypes are: iv (intravenous), ev0 (extra-vascular order 0), ev1 (extra-vascular order 1), \n"\
                       "     ev01 (extra-vascular first order 0 and then order 1), evFractional (extra-vascular fractional order)\n"\
                       "     ev0tlag1 (extra-vascular first order 0 for a fraction F0, tlag1 and then order 1 for 1-F0)\n"\
                       "     ev1-ev1Saturable (extra-vascular first order absorption with fast and slow absorption fractions, both absorptions can be saturated\n)"\
                       "     doubleWeibull (double Weibull\n)"\
                       "     tripleWeibull (triple Weibull\n)"\
                       "     splineN (Spline with N nodes\n)"\
                       "     splineXYN (SplineXY with N nodes\n)"\
                       "Optional parameters are tlag (e.g. tlag=0)\n"\
                       "   and bioavailability (e.g. bioavailability=0.8)\n"\
                       "Examples:\n"\
                       "Intravenous; iv\n"\
                       "Oral; ev1; tlag; bioavailability=1\n")
        addDoseToForm(form)
        form.addParam('dosesToSamples', params.TextParam, height=5, width=70, label="Assign doses to samples", default="",
                      help="Structure: [Sample Name] ; [DoseName1,DoseName2,...] \n"\
                           "The sample name should have no space or special character\n"\
                           "\nIt is important that there is one semicolon.\n"\
                           "Examples:\n"\
                           "FemaleRat1 ; Bolus0,Bolus1,Infusion0\n"\
                           "If left empty, all individuals are assigned to the first dose")

    #--------------------------- INSERT steps functions --------------------------------------------

    def _insertAllSteps(self):
        self._insertFunctionStep('createOutputStep', self.inputFile.get())

    #--------------------------- STEPS functions --------------------------------------------
    def readTextFile(self):
        pass

    def addSample(self, samplename, tokens):
        if not samplename in self.experiment.samples.keys():
            self.experiment.samples[samplename] = PKPDSample()
        self.experiment.samples[samplename].parseTokens(
            tokens, self.experiment.variables, self.experiment.doses,
            self.experiment.groups)

    def createOutputStep(self, objId):
        fnFile = os.path.basename(self.inputFile.get())
        copyFile(self.inputFile.get(), self._getPath(fnFile))

        self.experiment = PKPDExperiment()
        self.experiment.general["title"] = self.title.get()
        self.experiment.general["comment"] = self.comment.get()

        ok = True

        # Read the variables
        self.listOfVariables = []
        for line in self.variables.get().replace('\n', ';;').split(';;'):
            tokens = line.split(';')
            if len(tokens) != 5:
                print("Skipping variable: ", line)
                ok = False
                continue
            varname = tokens[0].strip()
            self.listOfVariables.append(varname)
            self.experiment.variables[varname] = PKPDVariable()
            self.experiment.variables[varname].parseTokens(tokens)

        # Read vias
        if self.vias.get():
            for line in self.vias.get().replace('\n', ';;').split(';;'):
                if line != "":
                    tokens = line.split(';')
                    if len(tokens) < 2:
                        print("Skipping via: ", line)
                        ok = False
                        continue
                    vianame = tokens[0].strip()
                    self.experiment.vias[vianame] = PKPDVia(
                        ptrExperiment=self.experiment)
                    self.experiment.vias[vianame].parseTokens(tokens)

        # Read the doses
        if self.doses.get():
            for line in self.doses.get().replace('\n', ';;').split(';;'):
                if line != "":
                    tokens = line.split(';')
                    if len(tokens) < 5:
                        print("Skipping dose: ", line)
                        ok = False
                        continue
                    dosename = tokens[0].strip()
                    self.experiment.doses[dosename] = PKPDDose()
                    self.experiment.doses[dosename].parseTokens(
                        tokens, self.experiment.vias)

        # Read the sample doses
        if self.dosesToSamples.get():
            for line in self.dosesToSamples.get().replace('\n',
                                                          ';;').split(';;'):
                try:
                    tokens = line.split(';')
                    samplename = tokens[0].strip()
                    if len(tokens) > 1:
                        tokens[1] = "dose=" + tokens[1]
                    self.addSample(samplename, tokens)
                except Exception as e:
                    ok = False
                    print("Problem with line: ", line, str(e))

        if ok:
            # Read the measurements
            self.readTextFile()

            if self.dosesToSamples.get(
            ) == "" and self.experiment.doses:  # There are doses but they are not assigned
                dosename = list(self.experiment.doses.keys())[0]
                for samplename in self.experiment.samples:
                    self.experiment.samples[samplename].doseList.append(
                        dosename)

            self.experiment.write(self._getPath("experiment.pkpd"))
            self.experiment._printToStream(sys.stdout)
            self._defineOutputs(outputExperiment=self.experiment)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        return ["Input file: %s" % self.inputFile.get()]

    def _validate(self):
        retval = []
        if self.inputFile.get() == "" or self.inputFile.get is None:
            retval.append("There is no input file")
        else:
            if not os.path.exists(self.inputFile.get()):
                retval.append("The file %s does not exist" %
                              self.inputFile.get())
        return retval
예제 #3
0
class ProtPKPDImportFromTable(ProtPKPD):
    #--------------------------- DEFINE param functions --------------------------------------------

    def _defineParams(self, form):
        form.addSection('Input')
        inputFileHelp = "Specify a path to desired %s file.\n" % type
        inputFileHelp += "You may specify missing values with NA. You may also use LLOQ and ULOQ (Lower and Upper limit of quantification)\n"
        inputFileHelp += "to specify measurements that are below or above these limits"
        inputFileHelp += "If you use a CSV: the field separator must be a semicolon (;), decimal point must be a dot (.).\n"
        inputFileHelp += "If you use an Excel: you may have several sheets\n"
        inputFileHelp += "The first row must contain the name of the time variable and the name of the sample names\n"
        form.addParam('inputFile',
                      params.PathParam,
                      label="File path",
                      allowsNull=False,
                      help=inputFileHelp)
        form.addParam(
            'sheetName',
            params.StringParam,
            label="Sheet",
            default="",
            help="Only valid for Excel files. Leave empty for all sheets")
        form.addParam('title',
                      params.StringParam,
                      label="Title",
                      default="My experiment")
        form.addParam('comment',
                      params.StringParam,
                      label="Comment",
                      default="")
        form.addParam('tVar',
                      params.TextParam,
                      height=8,
                      width=80,
                      label="Time variable",
                      default="t; h; numeric; time; Time variable")
        form.addParam(
            'xVar',
            params.TextParam,
            height=8,
            width=80,
            label="Measurement variable",
            default="C; none; numeric; measurement; Measurement variable")

    #--------------------------- INSERT steps functions --------------------------------------------

    def _insertAllSteps(self):
        self._insertFunctionStep('createOutputStep', self.inputFile.get())

    #--------------------------- STEPS functions --------------------------------------------
    def addVar(self, experiment, line):
        tokens = line.split(';')
        if len(tokens) != 5:
            print("Skipping variable: ", line)
            return False
        varname = tokens[0].strip()
        experiment.variables[varname] = PKPDVariable()
        experiment.variables[varname].parseTokens(tokens)
        return True

    def readTables(self, fnTable):
        retval = []
        if fnTable.endswith(".csv") or fnTable.endswith(".txt"):
            tableName = ""
            # csv
            fh = open(fnTable, "r")
            lineNo = 0
            allT = []
            allSamples = []
            for line in fh.readlines():
                tokens = line.split(";")
                if lineNo == 0:
                    sampleNames = []
                    tokenNo = 0
                    for token in tokens:
                        if tokenNo > 0:
                            strippedToken = token.strip()
                            if strippedToken != "":
                                sampleNames.append(strippedToken)
                        tokenNo += 1
                else:
                    allMeasurements = []
                    tokenNo = 0
                    for token in tokens:
                        if tokenNo == 0:
                            allT.append(token.strip())
                        else:
                            strippedToken = token.strip()
                            if strippedToken != "":
                                allMeasurements.append(strippedToken)
                        tokenNo += 1
                    allSamples.append(allMeasurements)
                lineNo += 1
            fh.close()
            retval.append((tableName, sampleNames, allT, allSamples))
        else:
            # excel
            import openpyxl
            wb = openpyxl.load_workbook(fnTable)
            sheetNames = wb.get_sheet_names()
            for sheetName in sheetNames:
                if (self.sheetName.get() != "" and sheetName
                        == self.sheetName.get()) or self.sheetName.get() == "":
                    tableName = "" if len(sheetNames) == 0 else "_" + sheetName
                    sampleNames = []
                    allT = []
                    allSamples = []
                    sheet = wb.get_sheet_by_name(sheetName)
                    for i in range(sheet.max_row):
                        if i > 0:
                            allMeasurements = []
                        for j in range(sheet.max_column):
                            cellValue = str(
                                sheet.cell(row=i + 1,
                                           column=j + 1).value).strip()
                            if cellValue == "":
                                continue
                            if i == 0 and j >= 1:
                                sampleNames.append(cellValue)
                            elif i > 0:
                                if j == 0:
                                    allT.append(cellValue)
                                else:
                                    allMeasurements.append(cellValue)
                        if i > 0:
                            allSamples.append(allMeasurements)
                    retval.append((tableName, sampleNames, allT, allSamples))
        return retval

    def createOutputStep(self, objId):
        fnFile = os.path.basename(self.inputFile.get())
        copyFile(self.inputFile.get(), self._getPath(fnFile))

        tables = self.readTables(self._getPath(fnFile))

        for tableName, sampleNames, allT, allMeasurements in tables:
            self.experiment = PKPDExperiment()
            self.experiment.general["title"] = self.title.get()
            self.experiment.general["comment"] = self.comment.get()

            # Add variables
            if not self.addVar(self.experiment, self.tVar.get()):
                raise Exception("Cannot process time variable")
            if not self.addVar(self.experiment, self.xVar.get()):
                raise Exception("Cannot process measurement variable")
            tvarName = self.tVar.get().split(';')[0].replace(';', '')
            xvarName = self.xVar.get().split(';')[0].replace(';', '')

            # Create the samples
            for sampleName in sampleNames:
                self.experiment.samples[sampleName] = PKPDSample()
                self.experiment.samples[sampleName].parseTokens(
                    [sampleName], self.experiment.variables,
                    self.experiment.doses, self.experiment.groups)
                self.experiment.samples[sampleName].addMeasurementPattern(
                    [sampleName, tvarName, xvarName])
                samplePtr = self.experiment.samples[sampleName]
                exec("samplePtr.measurement_%s=%s" % (tvarName, allT))

            # Fill the samples
            for i in range(len(allT)):
                for j in range(len(sampleNames)):
                    samplePtr = self.experiment.samples[sampleNames[j]]
                    exec('samplePtr.measurement_%s.append("%s")' %
                         (xvarName, allMeasurements[i][j]))

            self.experiment.write(
                self._getPath("experiment%s.pkpd" % tableName))
            self.experiment._printToStream(sys.stdout)
            self._defineOutputs(
                **{"outputExperiment%s" % tableName: self.experiment})

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        return ["Input file: %s" % self.inputFile.get()]