Exemplo n.º 1
0
    def visualize(self, obj, **kwargs):
        if hasattr(obj, "outputPopulation"):
            population = PKPDFitting("PKPDSampleFitBootstrap")
            population.load(obj.outputPopulation.fnFitting)

            self.populationWindow = self.tkWindow(PopulationWindow,
                                                  title='Population Viewer',
                                                  population=population)
            self.populationWindow.show()
Exemplo n.º 2
0
    def runMerge(self, objId1, objId2):
        self.population1 = self.readFitting(
            self.inputPopulation1.get().fnFitting,
            cls="PKPDSampleFitBootstrap")
        self.population2 = self.readFitting(
            self.inputPopulation2.get().fnFitting,
            cls="PKPDSampleFitBootstrap")
        self.printSection("Merging populations")

        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.population1.fnExperiment)
        self.fitting.predictor = self.population1.predictor
        self.fitting.predicted = self.population1.predicted
        self.fitting.modelParameterUnits = self.population1.modelParameterUnits
        self.fitting.modelParameters = self.population1.modelParameters
        self.fitting.modelDescription = self.population1.modelDescription

        newSampleFit = PKPDSampleFitBootstrap()
        newSampleFit.sampleName = "Merged population"
        newSampleFit.parameters = None
        for sampleFit in self.population1.sampleFits:
            if newSampleFit.parameters == None:
                newSampleFit.parameters = np.copy(sampleFit.parameters)
                newSampleFit.xB = copy.copy(sampleFit.xB)
                newSampleFit.yB = copy.copy(sampleFit.yB)
                newSampleFit.R2 = copy.copy(sampleFit.R2)
                newSampleFit.R2adj = copy.copy(sampleFit.R2adj)
                newSampleFit.AIC = copy.copy(sampleFit.AIC)
                newSampleFit.AICc = copy.copy(sampleFit.AICc)
                newSampleFit.BIC = copy.copy(sampleFit.BIC)
            else:
                newSampleFit.parameters = np.vstack(
                    [newSampleFit.parameters, sampleFit.parameters])
                newSampleFit.xB += sampleFit.xB
                newSampleFit.yB += sampleFit.yB
                newSampleFit.R2 += sampleFit.R2
                newSampleFit.R2adj += sampleFit.R2adj
                newSampleFit.AIC += sampleFit.AIC
                newSampleFit.AICc += sampleFit.AICc
                newSampleFit.BIC += sampleFit.BIC
        for sampleFit in self.population2.sampleFits:
            newSampleFit.parameters = np.vstack(
                [newSampleFit.parameters, sampleFit.parameters])
            print(type(newSampleFit.xB))
            print(type(sampleFit.xB))
            newSampleFit.xB += sampleFit.xB
            newSampleFit.yB += sampleFit.yB
            newSampleFit.R2 += sampleFit.R2
            newSampleFit.R2adj += sampleFit.R2adj
            newSampleFit.AIC += sampleFit.AIC
            newSampleFit.AICc += sampleFit.AICc
            newSampleFit.BIC += sampleFit.BIC
        self.fitting.sampleFits.append(newSampleFit)

        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))
Exemplo n.º 3
0
 def createOutputStep(self):
     newFitting = PKPDFitting()
     newFitting.fnExperiment.set(self.inputExperiment.get().fnPKPD)
     experiment = PKPDExperiment()
     experiment.load(self.inputExperiment.get().fnPKPD)
     for ptrFitting in self.inputFittings:
         newFitting.gather(self.readFitting(ptrFitting.get().fnFitting), experiment)
     self.writeExperiment(newFitting, self._getPath("fitting.pkpd"))
     self._defineOutputs(outputFitting=newFitting)
     for ptrFitting in self.inputFittings:
         self._defineSourceRelation(ptrFitting, newFitting)
Exemplo n.º 4
0
    def getInVitroModels(self):
        fnFitting = self.inputInVitro.get().fnFitting
        cls = "PKPDSampleFitBootstrap" if fnFitting.get().find(
            "bootstrap") != -1 else ""
        self.fittingInVitro = PKPDFitting(cls)
        self.fittingInVitro.load(fnFitting)
        self.invitroClsName = self.fittingInVitro.modelDescription.split(
            '(')[1].split(')')[0]

        klass = globals()[self.invitroClsName]
        self.dissolutionModel = klass()
        self.dissolutionModel.allowTlag = "tlag" in self.fittingInVitro.modelParameters
        self.dissolutionPopulation = cls != ""
Exemplo n.º 5
0
    def getPKModels(self):
        fnFitting = self.inputPK.get().fnFitting
        cls = "PKPDSampleFitBootstrap" if fnFitting.get().find(
            "bootstrap") != -1 else ""
        self.fittingPK = PKPDFitting(cls)
        self.fittingPK.load(fnFitting)
        modelDescription = self.fittingPK.modelDescription.split(';')[
            1]  # Before ; there is the drug source description
        self.pkClsName = modelDescription.split('(')[1].split(')')[0]

        klass = globals()[self.pkClsName]
        self.pkModel = klass()
        self.pkModel.t0 = self.t0.get()
        self.pkModel.tF = self.tF.get()
        self.timeUnits = self.fittingPK.getTimeUnits().unit
        if self.timeUnits == PKPDUnit.UNIT_TIME_MIN:
            self.pkModel.t0 *= 60
            self.pkModel.tF *= 60
        self.pkModel.drugSource = DrugSource()
        dose = createDeltaDose(self.inputDose.get(),
                               via=createVia("Oral; numerical"))
        self.pkModel.drugSource.setDoses([dose], self.pkModel.t0,
                                         self.pkModel.tF)
        self.pkPopulation = cls != ""
        self.pkNParams = self.pkModel.getNumberOfParameters()

        self.tlagIdx = None
        if self.includeTlag.get():
            i = 0
            for prmName in self.fittingPK.modelParameters:
                if prmName.endswith('_tlag'):
                    self.tlagIdx = i
                    print("Found tlag in %s at position %d" % (prmName, i))
                    break
                i += 1
        self.bioavailabilityIdx = None
        if not self.ignorePKbioavailability.get():
            i = 0
            for prmName in self.fittingPK.modelParameters:
                if prmName.endswith('_bioavailability'):
                    self.bioavailabilityIdx = i
                    print("Found bioavailabilityIdx in %s at position %d" %
                          (prmName, i))
                    break
                i += 1
Exemplo n.º 6
0
 def readFitting(self, fnIn, show=True, cls=""):
     fitting = PKPDFitting(cls)
     fitting.load(fnIn)
     if show:
         self.printSection("Reading %s" % fnIn)
         fitting._printToStream(sys.stdout)
     return fitting
Exemplo n.º 7
0
 def createFitting(self, prot, experiment, suffix):
     # Create output object
     fitting = PKPDFitting()
     fitting.fnExperiment.set(self._getPath("experiment%d.pkpd" % suffix))
     fitting.predictor = experiment.variables[prot.varNameX]
     if type(prot.varNameY) == list:
         fitting.predicted = []
         for y in prot.varNameY:
             fitting.predicted.append(experiment.variables[y])
     else:
         fitting.predicted = experiment.variables[prot.varNameY]
     fitting.modelParameterUnits = None
     return fitting
Exemplo n.º 8
0
class ProtPKPDDissolutionSimulate(ProtPKPD):
    """ Simulate a dissolution profile\n
        Protocol created by http://www.kinestatpharma.com\n"""
    _label = 'simulate dissolution'

    # --------------------------- DEFINE param functions --------------------------------------------
    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam(
            'allowTlag',
            params.BooleanParam,
            label="Allow lag",
            default=False,
            help='Allow lag time before starting dissolution (t-tlag)')
        form.addParam('modelType', params.EnumParam, choices=["Zero order", "First order", "Fractional", "Weibull",
                                                              "Double Weibull", "Triple Weibull", "Higuchi",
                                                              "Korsmeyer-Peppas", "Hixson-Crowell", "Hopfenberg",
                                                              "Hill",
                                                              "Makoid-Banakar",
                                                              "Splines2", "Splines3", "Splines4", "Spline5", "Splines6",
                                                              "Splines7", "Splines8", "Splines9", "Splines10"],
                      label="Dissolution model", default=3,
                      help='Zero order: Y=K*(t-[tlag])\n' \
                           'First order: Y=Ymax*(1-exp(-beta*(t-[tlag])))\n' \
                           'Fractional order: Y=Ymax-pow(Ymax^alpha-alpha*beta*t,1/alpha))\n' \
                           'Weibull: Y=Ymax*(1-exp(-lambda*t^b))\n' \
                           'Double Weibull: Y=Ymax*(F1*(1-exp(-lambda1*t^b1))+(1-F1)*(1-exp(-lambda2*(t-tlag2)^b2)))\n' \
                           'Triple Weibull: Y=Ymax*(F1*(1-exp(-lambda1*t^b1))+F2*(1-exp(-lambda2*(t-tlag2)^b2))+(1-F1-F2)*(1-exp(-lambda3*(t-tlag3)^b3)))\n' \
                           'Higuchi: Y=Ymax*t^0.5\n' \
                           'Korsmeyer-Peppas: Y=Ymax*t^m\n' \
                           'Hixson-Crowell: Y=Ymax*(1-(1-K*t)^3)\n'
                           'Hopfenberg: Y=Ymax*(1-(1-K*t)^m)\n'
                           'Hill: Y = Ymax*t^d/(g^d+t^d)\n'
                           'Makoid-Banakar: Ymax*(t/tmax)^b*exp(b*(1-t/tmax))\n'
                           'SplinesN: Y= Ymax*Bspline(t;N,tmax)\n')
        form.addParam(
            'parameters',
            params.StringParam,
            label="Parameters",
            default="",
            help=
            'Parameter values for the simulation.\nExample: 2;5 is 2 for the first parameter, 5 for the second parameter\n'
            'Zero order: [tlag];K\n'
            'First order: [tlag];Ymax;beta\n'
            'Fractional order: [tlag]; Ymax;beta;alpha\n'
            'Weibull: [tlag]; Ymax;lambda;b\n'
            'Double Weibull: [tlag]; Ymax; lambda1; b1; F1; tlag2; lambda2; b2\n'
            'Triple Weibull: [tlag]; Ymax; lambda1; b1; F1; tlag2; lambda2; b2; F2; tlag3; lambda3; b3\n'
            'Higuchi: [tlag]; Ymax\n'
            'Korsmeyer-Peppas: [tlag]; Ymax; m\n'
            'Hixson-Crowell: [tlag]; Ymax; K\n'
            'Hopfenberg: [tlag]; Ymax; K; m\n'
            'Hill: [tlag]; Ymax; g; d\n'
            'Makoid-Banakar: [tlag]; Ymax; Tmax; b\n'
            'SplinesN: [tlag]; Ymax; tmax; c1; c2; ...; cN\n')
        form.addParam('timeUnits',
                      params.EnumParam,
                      choices=["min", "h"],
                      label="Time units",
                      default=0)
        form.addParam('resampleT',
                      params.FloatParam,
                      label='Simulation model time step=',
                      default=1)
        form.addParam('resampleT0',
                      params.FloatParam,
                      label='Initial time for simulation',
                      default=0)
        form.addParam('resampleTF',
                      params.FloatParam,
                      label='Final time for simulation',
                      default=100)
        form.addParam('AUnits',
                      params.StringParam,
                      label="Dissolution units",
                      default="%",
                      help="%, mg/dL, ...")

        form.addParam('noiseType', params.EnumParam, label="Type of noise to add",
                      choices=["None", "Additive", "Multiplicative"],
                      default=0, expertLevel=LEVEL_ADVANCED,
                      help='Additive: noise is normally distributed (mean=0 and standard deviation=sigma)\n' \
                           'Multiplicative: noise is normally distributed (mean=0 and standard deviation=sigma*X)\n')
        form.addParam('noiseSigma',
                      params.FloatParam,
                      label="Noise sigma",
                      default=0.0,
                      expertLevel=LEVEL_ADVANCED,
                      condition="noiseType>0",
                      help='See help of Type of noise to add\n')

    # --------------------------- STEPS functions --------------------------------------------
    def _insertAllSteps(self):
        self._insertFunctionStep('runSimulate')
        self._insertFunctionStep('createOutputStep')

    def addNoise(self, y):
        if self.noiseType.get() == 0:
            return y
        elif self.noiseType.get() == 1:
            return y + np.random.normal(0.0, self.noiseSigma.get(), y.shape)
        elif self.noiseType.get() == 2:
            return y * (1 +
                        np.random.normal(0.0, self.noiseSigma.get(), y.shape))

    def runSimulate(self):
        tvar = PKPDVariable()
        tvar.varName = "t"
        tvar.varType = PKPDVariable.TYPE_NUMERIC
        tvar.role = PKPDVariable.ROLE_TIME
        if self.timeUnits.get() == 0:
            tvar.units = createUnit("min")
        elif self.timeUnits.get() == 1:
            tvar.units = createUnit("h")

        Avar = PKPDVariable()
        Avar.varName = "A"
        Avar.varType = PKPDVariable.TYPE_NUMERIC
        Avar.role = PKPDVariable.ROLE_MEASUREMENT
        if self.AUnits.get() != "%":
            Avar.units = createUnit(self.AUnits.get())
        else:
            Avar.units = createUnit("none")

        self.experimentSimulated = PKPDExperiment()
        self.experimentSimulated.variables["t"] = tvar
        self.experimentSimulated.variables["A"] = Avar
        self.experimentSimulated.general[
            "title"] = "Simulated dissolution profile"
        self.experimentSimulated.general["comment"] = ""

        if self.modelType.get() == 0:
            self.model = Dissolution0()
        elif self.modelType.get() == 1:
            self.model = Dissolution1()
        elif self.modelType.get() == 2:
            self.model = DissolutionAlpha()
        elif self.modelType.get() == 3:
            self.model = DissolutionWeibull()
        elif self.modelType.get() == 4:
            self.model = DissolutionDoubleWeibull()
        elif self.modelType.get() == 5:
            self.model = DissolutionTripleWeibull()
        elif self.modelType.get() == 6:
            self.model = DissolutionHiguchi()
        elif self.modelType.get() == 7:
            self.model = DissolutionKorsmeyer()
        elif self.modelType.get() == 8:
            self.model = DissolutionHixson()
        elif self.modelType.get() == 9:
            self.model = DissolutionHopfenberg()
        elif self.modelType.get() == 10:
            self.model = DissolutionHill()
        elif self.modelType.get() == 11:
            self.model = DissolutionMakoidBanakar()
        elif self.modelType.get() == 12:
            self.model = DissolutionSplines2()
        elif self.modelType.get() == 13:
            self.model = DissolutionSplines3()
        elif self.modelType.get() == 14:
            self.model = DissolutionSplines4()
        elif self.modelType.get() == 15:
            self.model = DissolutionSplines5()
        elif self.modelType.get() == 16:
            self.model = DissolutionSplines6()
        elif self.modelType.get() == 17:
            self.model = DissolutionSplines7()
        elif self.modelType.get() == 18:
            self.model = DissolutionSplines8()
        elif self.modelType.get() == 19:
            self.model = DissolutionSplines9()
        elif self.modelType.get() == 20:
            self.model = DissolutionSplines10()
        self.model.allowTlag = self.allowTlag.get()
        self.model.parameters = [
            float(x) for x in self.parameters.get().split(';')
        ]

        newSample = PKPDSample()
        newSample.sampleName = "simulatedProfile"
        newSample.variableDictPtr = self.experimentSimulated.variables
        newSample.descriptors = {}
        newSample.addMeasurementPattern(["A"])

        t0 = self.resampleT0.get()
        tF = self.resampleTF.get()
        deltaT = self.resampleT.get()
        t = np.arange(t0, tF + deltaT, deltaT)
        self.model.setExperiment(self.experimentSimulated)
        self.model.setXVar("t")
        self.model.setYVar("A")
        self.model.calculateParameterUnits(newSample)
        y = self.model.forwardModel(self.model.parameters, t)
        newSample.addMeasurementColumn("t", t)
        newSample.addMeasurementColumn("A", y[0])

        self.experimentSimulated.samples[newSample.sampleName] = newSample
        fnExperiment = self._getPath("experimentSimulated.pkpd")
        self.experimentSimulated.write(fnExperiment)

        self.fittingSimulated = PKPDFitting()
        self.fittingSimulated.fnExperiment.set(fnExperiment)
        self.fittingSimulated.predictor = self.experimentSimulated.variables[
            "t"]
        self.fittingSimulated.predicted = self.experimentSimulated.variables[
            "A"]
        self.fittingSimulated.modelDescription = self.model.getDescription()
        self.fittingSimulated.modelParameters = self.model.getParameterNames()
        self.fittingSimulated.modelParameterUnits = self.model.parameterUnits

        sampleFit = PKPDSampleFit()
        sampleFit.sampleName = newSample.sampleName
        sampleFit.x = [t]
        sampleFit.y = y
        sampleFit.yp = y
        sampleFit.yl = y
        sampleFit.yu = y
        sampleFit.parameters = self.model.parameters
        sampleFit.modelEquation = self.model.getEquation()

        sampleFit.R2 = -1
        sampleFit.R2adj = -1
        sampleFit.AIC = -1
        sampleFit.AICc = -1
        sampleFit.BIC = -1
        sampleFit.significance = ["NA" for prm in sampleFit.parameters]
        sampleFit.lowerBound = ["NA" for prm in sampleFit.parameters]
        sampleFit.upperBound = ["NA" for prm in sampleFit.parameters]

        self.fittingSimulated.sampleFits.append(sampleFit)

        fnFitting = self._getPath("fittingSimulated.pkpd")
        self.fittingSimulated.write(fnFitting)

    def createOutputStep(self):
        self._defineOutputs(outputExperiment=self.experimentSimulated)
        self._defineOutputs(outputFitting=self.fittingSimulated)
Exemplo n.º 9
0
    def runSimulate(self):
        tvar = PKPDVariable()
        tvar.varName = "t"
        tvar.varType = PKPDVariable.TYPE_NUMERIC
        tvar.role = PKPDVariable.ROLE_TIME
        if self.timeUnits.get() == 0:
            tvar.units = createUnit("min")
        elif self.timeUnits.get() == 1:
            tvar.units = createUnit("h")

        Avar = PKPDVariable()
        Avar.varName = "A"
        Avar.varType = PKPDVariable.TYPE_NUMERIC
        Avar.role = PKPDVariable.ROLE_MEASUREMENT
        if self.AUnits.get() != "%":
            Avar.units = createUnit(self.AUnits.get())
        else:
            Avar.units = createUnit("none")

        self.experimentSimulated = PKPDExperiment()
        self.experimentSimulated.variables["t"] = tvar
        self.experimentSimulated.variables["A"] = Avar
        self.experimentSimulated.general[
            "title"] = "Simulated dissolution profile"
        self.experimentSimulated.general["comment"] = ""

        if self.modelType.get() == 0:
            self.model = Dissolution0()
        elif self.modelType.get() == 1:
            self.model = Dissolution1()
        elif self.modelType.get() == 2:
            self.model = DissolutionAlpha()
        elif self.modelType.get() == 3:
            self.model = DissolutionWeibull()
        elif self.modelType.get() == 4:
            self.model = DissolutionDoubleWeibull()
        elif self.modelType.get() == 5:
            self.model = DissolutionTripleWeibull()
        elif self.modelType.get() == 6:
            self.model = DissolutionHiguchi()
        elif self.modelType.get() == 7:
            self.model = DissolutionKorsmeyer()
        elif self.modelType.get() == 8:
            self.model = DissolutionHixson()
        elif self.modelType.get() == 9:
            self.model = DissolutionHopfenberg()
        elif self.modelType.get() == 10:
            self.model = DissolutionHill()
        elif self.modelType.get() == 11:
            self.model = DissolutionMakoidBanakar()
        elif self.modelType.get() == 12:
            self.model = DissolutionSplines2()
        elif self.modelType.get() == 13:
            self.model = DissolutionSplines3()
        elif self.modelType.get() == 14:
            self.model = DissolutionSplines4()
        elif self.modelType.get() == 15:
            self.model = DissolutionSplines5()
        elif self.modelType.get() == 16:
            self.model = DissolutionSplines6()
        elif self.modelType.get() == 17:
            self.model = DissolutionSplines7()
        elif self.modelType.get() == 18:
            self.model = DissolutionSplines8()
        elif self.modelType.get() == 19:
            self.model = DissolutionSplines9()
        elif self.modelType.get() == 20:
            self.model = DissolutionSplines10()
        self.model.allowTlag = self.allowTlag.get()
        self.model.parameters = [
            float(x) for x in self.parameters.get().split(';')
        ]

        newSample = PKPDSample()
        newSample.sampleName = "simulatedProfile"
        newSample.variableDictPtr = self.experimentSimulated.variables
        newSample.descriptors = {}
        newSample.addMeasurementPattern(["A"])

        t0 = self.resampleT0.get()
        tF = self.resampleTF.get()
        deltaT = self.resampleT.get()
        t = np.arange(t0, tF + deltaT, deltaT)
        self.model.setExperiment(self.experimentSimulated)
        self.model.setXVar("t")
        self.model.setYVar("A")
        self.model.calculateParameterUnits(newSample)
        y = self.model.forwardModel(self.model.parameters, t)
        newSample.addMeasurementColumn("t", t)
        newSample.addMeasurementColumn("A", y[0])

        self.experimentSimulated.samples[newSample.sampleName] = newSample
        fnExperiment = self._getPath("experimentSimulated.pkpd")
        self.experimentSimulated.write(fnExperiment)

        self.fittingSimulated = PKPDFitting()
        self.fittingSimulated.fnExperiment.set(fnExperiment)
        self.fittingSimulated.predictor = self.experimentSimulated.variables[
            "t"]
        self.fittingSimulated.predicted = self.experimentSimulated.variables[
            "A"]
        self.fittingSimulated.modelDescription = self.model.getDescription()
        self.fittingSimulated.modelParameters = self.model.getParameterNames()
        self.fittingSimulated.modelParameterUnits = self.model.parameterUnits

        sampleFit = PKPDSampleFit()
        sampleFit.sampleName = newSample.sampleName
        sampleFit.x = [t]
        sampleFit.y = y
        sampleFit.yp = y
        sampleFit.yl = y
        sampleFit.yu = y
        sampleFit.parameters = self.model.parameters
        sampleFit.modelEquation = self.model.getEquation()

        sampleFit.R2 = -1
        sampleFit.R2adj = -1
        sampleFit.AIC = -1
        sampleFit.AICc = -1
        sampleFit.BIC = -1
        sampleFit.significance = ["NA" for prm in sampleFit.parameters]
        sampleFit.lowerBound = ["NA" for prm in sampleFit.parameters]
        sampleFit.upperBound = ["NA" for prm in sampleFit.parameters]

        self.fittingSimulated.sampleFits.append(sampleFit)

        fnFitting = self._getPath("fittingSimulated.pkpd")
        self.fittingSimulated.write(fnFitting)
Exemplo n.º 10
0
class ProtPKPDODEBase(ProtPKPD, PKPDModelBase2):
    """ Base ODE protocol"""
    def __init__(self, **kwargs):
        ProtPKPD.__init__(self, **kwargs)
        self.boundsList = None

    #--------------------------- DEFINE param functions --------------------------------------------
    def _defineParams1(self,
                       form,
                       addXY=False,
                       defaultPredictor="",
                       defaultPredicted=""):
        form.addSection('Input')
        form.addParam('inputExperiment',
                      params.PointerParam,
                      label="Input experiment",
                      pointerClass='PKPDExperiment',
                      help='Select an experiment with samples')
        if addXY:
            form.addParam(
                'predictor',
                params.StringParam,
                label="Predictor variable (X)",
                default=defaultPredictor,
                help='Y is predicted as an exponential function of X, Y=f(X)')
            form.addParam(
                'predicted',
                params.StringParam,
                label="Predicted variable (Y)",
                default=defaultPredicted,
                help='Y is predicted as an exponential function of X, Y=f(X)')
        form.addParam(
            'deltaT',
            params.FloatParam,
            default=0.5,
            label='Step (t)',
            expertLevel=LEVEL_ADVANCED,
            help=
            "Time step for the numerical solution of the differential equation. Same units as time in the "
            "input experiment. "
            "For very long simulations you may want to increase this value, beware that this results in "
            "less accurate solutions.")

        fromTo = form.addLine(
            'Simulation length',
            expertLevel=LEVEL_ADVANCED,
            help='Minimum and maximum time (in hours). '
            'If minimum and maximum are not given (set to -1), they are estimated from the sample'
        )
        fromTo.addParam('t0', params.StringParam, default="", label='Min (h)')
        fromTo.addParam('tF', params.StringParam, default="", label='Max (h)')

        form.addParam('fitType', params.EnumParam, choices=["Linear","Logarithmic","Relative"], label="Fit mode", default=1,
                      expertLevel=LEVEL_ADVANCED,
                      help='Linear: sum (Cobserved-Cpredicted)^2\nLogarithmic: sum(log10(Cobserved)-log10(Cpredicted))^2\n'\
                           "Relative: sum ((Cobserved-Cpredicted)/Cobserved)^2")
        form.addParam('confidenceInterval',
                      params.FloatParam,
                      label="Confidence interval",
                      default=95,
                      expertLevel=LEVEL_ADVANCED,
                      help='Confidence interval for the fitted parameters')
        form.addParam(
            'reportX',
            params.StringParam,
            label="Evaluate at X",
            default="",
            expertLevel=LEVEL_ADVANCED,
            help=
            'Evaluate the model at these X values\nExample 1: [0,5,10,20,40,100]\nExample 2: 0:0.55:10, from 0 to 10 in steps of 0.5'
        )
        form.addParam(
            'globalSearch',
            params.BooleanParam,
            label="Global search",
            default=True,
            expertLevel=LEVEL_ADVANCED,
            help=
            'Global search looks for the best parameters within bounds. If it is not performed, the '
            'middle of the bounding box is used as initial parameter for a local optimization'
        )

    #--------------------------- INSERT steps functions --------------------------------------------
    def getListOfFormDependencies(self):
        retval = [
            self.fitType.get(),
            self.confidenceInterval.get(),
            self.reportX.get()
        ]
        if hasattr(self, "predictor"):
            retval.append(self.predictor.get())
            retval.append(self.predicted.get())
        if hasattr(self, "bounds"):
            retval.append(self.bounds.get())
        return retval

    def _insertAllSteps(self):
        self._insertFunctionStep('runFit',
                                 self.getInputExperiment().getObjId(),
                                 self.getListOfFormDependencies())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def getInputExperiment(self):
        if hasattr(self, "inputExperiment"):
            return self.inputExperiment.get()
        else:
            return None

    def getConfidenceInterval(self):
        return self.confidenceInterval.get()

    def getXYvars(self):
        if hasattr(self, "predictor"):
            self.varNameX = self.predictor.get()
        else:
            self.varNameX = None

        if hasattr(self, "predicted"):
            self.varNameY = self.predicted.get()
        else:
            self.varNameY = None

    def configureSource(self, drugSource):
        pass

    def createModel(self):
        pass

    def setupModel(self):
        # Setup model
        self.model = self.createModel()
        self.model.setExperiment(self.experiment)
        self.model.setXVar(self.varNameX)
        self.model.setYVar(self.varNameY)
        self.modelList.append(self.model)

    def getResponseDimension(self):
        return self.model.getResponseDimension()

    def getStateDimension(self):
        return self.model.getStateDimension()

    def setBounds(self, sample):
        if hasattr(self, "bounds"):
            self.model.setBounds(self.bounds.get())

    def prepareForSampleAnalysis(self, sampleName):
        pass

    def postSampleAnalysis(self, sampleName):
        pass

    def setTimeRange(self, sample):
        if self.t0.get() == "" or self.tF.get() == "":
            tmin, tmax = sample.getRange(self.varNameX)
        else:
            tmin = self.t0.get()
            tmax = self.tF.get()
        if self.tmin == None:
            self.tmin = tmin
        else:
            self.tmin = min(tmin, self.tmin)
        if self.tmax == None:
            self.tmax = tmax
        else:
            self.tmax = max(tmax, self.tmax)

        if self.t0.get() == "":
            self.model.t0 = min(-10, self.tmin - 10)  # 10 minutes before
        else:
            self.model.t0 = min(-10, float(self.t0.get()) * 60)

        if self.tF.get() == "":
            self.model.tF = self.tmax + 10  # 10 minutes later
        else:
            self.model.tF = float(self.tF.get()) * 60

        if hasattr(self, "deltaT"):
            self.model.deltaT = self.deltaT.get()

    def setVarNames(self, varNameX, varNameY):
        self.varNameX = varNameX
        self.varNameY = varNameY

    def setModel(self, model):
        self.model = model

    # As model --------------------------------------------
    def clearGroupParameters(self):
        self.tmin = None
        self.tmax = None
        self.sampleList = []
        self.modelList = []
        self.drugSourceList = []
        self.clearXYLists()

    def clearXYLists(self):
        self.XList = []
        self.YList = []

    def parseBounds(self, boundsString):
        self.boundsList = []

        if boundsString != "" and boundsString != None:
            tokens = boundsString.split(';')
            if len(tokens) != self.getNumberOfParameters():
                raise Exception("The number of bound intervals (%d) does not match the number of parameters (%d)"%\
                                (len(tokens),self.getNumberOfParameters()))

            for token in tokens:
                values = token.strip().split(',')
                self.boundsList.append(
                    (float(values[0][1:]), float(values[1][:-1])))

    def setBounds(self, sample):
        self.parseBounds(self.bounds.get())
        self.setBoundsFromBoundsList()

    def setBoundsFromBoundsList(self):
        Nbounds = len(self.boundsList)
        Nsource = self.drugSource.getNumberOfParameters()
        Nmodel = self.model.getNumberOfParameters()
        if Nbounds != Nsource + Nmodel:
            raise Exception(
                "The number of parameters (%d) and bounds (%d) are different" %
                (Nsource + Nmodel, Nbounds))
        self.boundsSource = self.boundsList[0:Nsource]
        self.boundsPK = self.boundsList[Nsource:]
        self.model.bounds = self.boundsPK

    def getBounds(self):
        return self.boundsList

    def getParameterBounds(self):
        """ Return a dictionary where the parameter name is the key
        and the bounds are its values. """
        boundsDict = OrderedDict()
        self.parseBounds(self.bounds.get())  # after this we have boundsList
        parameterNames = self.getParameterNames()

        for paramName, bound in izip(parameterNames, self.getBounds()):
            boundsDict[paramName] = bound

        # Set None as bound for parameters not matched
        for paramName in parameterNames:
            if paramName not in boundsDict:
                boundsDict[paramName] = None

        return boundsDict

    def setParameters(self, parameters):
        self.parameters = parameters
        self.parametersPK = self.parameters[-self.NparametersModel:]

        for n in range(len(self.modelList)):
            if self.NparametersSource > 0:
                self.drugSourceList[n].setParameters(
                    self.parameters[0:self.NparametersSource])
            self.modelList[n].setParameters(self.parametersPK)

    def setXYValues(self, x, y):
        PKPDModelBase.setXYValues(self, x, y)
        self.model.setXYValues(x, y)
        self.XList.append(x)
        self.YList.append(y)

    def mergeLists(self, iny):
        if len(self.XList) > 1:
            outy = []
            for m in range(len(iny[0])):
                outy.append(np.empty(shape=[0]))
            for m in range(len(outy)):
                for n in range(len(iny)):
                    outy[m] = np.concatenate((outy[m], iny[n][m]))
            return outy
        else:
            return iny[0]

    def separateLists(self, iny):
        outy = []
        Nsamples = len(self.YList)
        if Nsamples == 0:
            return
        Nmeasurements = self.model.getResponseDimension()
        idx = [0] * Nmeasurements
        for n in range(Nsamples):
            yn = self.YList[n]
            perSampleIn = []
            for j in range(Nmeasurements):
                ynDim = yn[j].size
                ysample = iny[j][idx[j]:(idx[j] + ynDim)]
                perSampleIn.append(ysample)
                idx[j] += ynDim
            outy.append(perSampleIn)
        return outy

    def addSample(self, sample):
        self.sampleList.append(sample)
        self.model.setSample(sample)

    def forwardModel(self, parameters, x=None):
        self.setParameters(parameters)

        yPredictedList = []
        for n in range(len(self.modelList)):
            self.modelList[n].forwardModel(self.parametersPK, x)
            yPredictedList.append(self.modelList[n].yPredicted)
        self.yPredicted = self.mergeLists(yPredictedList)
        return copy.copy(self.yPredicted)

    def forwardModelByConvolution(self, parameters, x=None):
        self.setParameters(parameters)
        tFImpulse = None
        if hasattr(self, "tFImpulse"):
            if self.tFImpulse.get() != "":
                tFImpulse = float(self.tFImpulse.get())

        yPredictedList = []
        for n in range(len(self.modelList)):
            self.modelList[n].tFImpulse = tFImpulse
            self.modelList[n].forwardModelByConvolution(self.parametersPK, x)
            yPredictedList.append(self.modelList[n].yPredicted)
        self.yPredicted = self.mergeLists(yPredictedList)
        return copy.copy(self.yPredicted)

    def imposeConstraints(self, yt):
        self.model.imposeConstraints(yt)

    def getEquation(self):
        return self.drugSource.getEquation(
        ) + " and " + self.model.getEquation()

    def getModelEquation(self):
        return self.drugSource.getModelEquation(
        ) + " and " + self.model.getModelEquation()

    def getDescription(self):
        return self.drugSource.getDescription(
        ) + "; " + self.model.getDescription()

    def getParameterNames(self):
        retval = []
        parametersSource = self.drugSource.getParameterNames()
        self.NparametersSource = len(parametersSource)
        retval += parametersSource
        parametersModel = self.model.getParameterNames()
        self.NparametersModel = len(parametersModel)
        retval += parametersModel
        return retval

    def calculateParameterUnits(self, sample):
        retval = []
        retval += self.drugSource.calculateParameterUnits(sample)
        retval += self.model.calculateParameterUnits(sample)
        self.parameterUnits = retval

    def areParametersSignificant(self, lowerBound, upperBound):
        retval = []
        idx = 0
        if len(self.boundsSource) > 0:
            retval += self.drugSource.areParametersSignificant(
                lowerBound[idx:len(self.boundsSource)],
                upperBound[idx:len(self.boundsSource)])
        retval += self.model.areParametersSignificant(
            lowerBound[len(self.boundsSource):],
            upperBound[len(self.boundsSource):])
        return retval

    def areParametersValid(self, p):
        return self.drugSource.areParametersValid(p[0:len(self.boundsSource)]) and \
               self.model.areParametersValid(p[len(self.boundsSource):])

    def createDrugSource(self):
        self.drugSource = DrugSource()
        self.drugSourceList.append(self.drugSource)

        return self.drugSource

    # Really fit ---------------------------------------------------------
    def runFit(self, objId, otherDependencies):
        reportX = parseRange(self.reportX.get())
        self.setInputExperiment()

        # Setup model
        self.getXYvars()

        # Create output object
        self.fitting = PKPDFitting()
        self.fitting.fnExperiment.set(self._getPath("experiment.pkpd"))
        self.fitting.predictor = self.experiment.variables[self.varNameX]
        if type(self.varNameY) == list:
            self.fitting.predicted = []
            for y in self.varNameY:
                self.fitting.predicted.append(self.experiment.variables[y])
        else:
            self.fitting.predicted = self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        if self.fitType.get() == 0:
            fitType = "linear"
        elif self.fitType.get() == 1:
            fitType = "log"
        elif self.fitType.get() == 2:
            fitType = "relative"

        for groupName, group in self.experiment.groups.items():
            self.printSection("Fitting " + groupName)
            self.clearGroupParameters()

            for sampleName in group.sampleList:
                print("   Sample " + sampleName)
                sample = self.experiment.samples[sampleName]

                self.createDrugSource()
                self.setupModel()

                # Get the values to fit
                x, y = sample.getXYValues(self.varNameX, self.varNameY)
                print("X= " + str(x))
                print("Y= " + str(y))
                print(" ")

                # Interpret the dose
                self.setTimeRange(sample)
                sample.interpretDose()

                self.drugSource.setDoses(sample.parsedDoseList, self.model.t0,
                                         self.model.tF)
                self.configureSource(self.drugSource)
                self.model.drugSource = self.drugSource

                # Prepare the model
                self.setBounds(sample)
                self.setXYValues(x, y)
                self.addSample(sample)
                self.prepareForSampleAnalysis(sampleName)
                self.calculateParameterUnits(sample)
                if self.fitting.modelParameterUnits == None:
                    self.fitting.modelParameterUnits = self.parameterUnits

            self.printSetup()
            self.x = self.mergeLists(self.XList)
            self.y = self.mergeLists(self.YList)

            if self.globalSearch:
                optimizer1 = PKPDDEOptimizer(self, fitType)
                optimizer1.optimize()
            else:
                self.parameters = np.zeros(len(self.boundsList), np.double)
                n = 0
                for bound in self.boundsList:
                    self.parameters[n] = 0.5 * (bound[0] + bound[1])
                    n += 1
            try:
                optimizer2 = PKPDLSOptimizer(self, fitType)
                optimizer2.optimize()
            except Exception as e:
                msg = "Error: " + str(e)
                msg += "\nErrors in the local optimizer may be caused by starting from a bad initial guess\n"
                msg += "Try performing a global search first or changing the bounding box"
                raise Exception("Error in the local optimizer\n" + msg)
            optimizer2.setConfidenceInterval(self.getConfidenceInterval())
            self.setParameters(optimizer2.optimum)
            optimizer2.evaluateQuality()
            self.model.printOtherParameterization()

            self.yPredictedList = self.separateLists(self.yPredicted)
            self.yPredictedLowerList = self.separateLists(self.yPredictedLower)
            self.yPredictedUpperList = self.separateLists(self.yPredictedUpper)

            n = 0
            for sampleName in group.sampleList:
                sample = self.experiment.samples[sampleName]

                # Keep this result
                sampleFit = PKPDSampleFit()
                sampleFit.sampleName = sample.sampleName
                sampleFit.x = self.XList[n]
                sampleFit.y = self.YList[n]
                sampleFit.yp = self.yPredictedList[n]
                sampleFit.yl = self.yPredictedLowerList[n]
                sampleFit.yu = self.yPredictedUpperList[n]
                sampleFit.parameters = self.parameters
                sampleFit.modelEquation = self.getEquation()
                sampleFit.copyFromOptimizer(optimizer2)
                self.fitting.sampleFits.append(sampleFit)

                # Add the parameters to the sample and experiment
                for varName, varUnits, description, varValue in izip(
                        self.getParameterNames(), self.parameterUnits,
                        self.getParameterDescriptions(), self.parameters):
                    self.experiment.addParameterToSample(sampleName,
                                                         varName,
                                                         varUnits,
                                                         description,
                                                         varValue,
                                                         rewrite=True)
                self.experiment.addParameterToSample(sampleName,
                                                     "R2",
                                                     PKPDUnit.UNIT_NONE,
                                                     "Fitting R2",
                                                     sampleFit.R2,
                                                     rewrite=True)

                self.postSampleAnalysis(sampleName)

                if reportX != None:
                    print("Evaluation of the model at specified time points")
                    self.model.tF = np.max(reportX)
                    yreportX = self.model.forwardModel(self.model.parameters,
                                                       reportX)
                    print("==========================================")
                    print("X     Ypredicted     log10(Ypredicted)")
                    print("==========================================")
                    for n in range(0, reportX.shape[0]):
                        aux = 0
                        if yreportX[n] > 0:
                            aux = math.log10(yreportX[n])
                        print("%f %f %f" % (reportX[n], yreportX[n], aux))
                    print(' ')

                n += 1

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.getDescription()
        self.fitting.write(self._getPath("fitting.pkpd"))
        self.experiment.general['Model'] = self.getDescription()
        self.experiment.write(self._getPath("experiment.pkpd"))

    def createOutputStep(self):
        self._defineOutputs(outputFitting=self.fitting)
        self._defineOutputs(outputExperiment=self.experiment)
        self._defineSourceRelation(self.getInputExperiment(), self.fitting)
        self._defineSourceRelation(self.getInputExperiment(), self.experiment)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        msg = []
        self.getXYvars()
        if self.varNameX != None:
            msg.append('Predicting %s from %s' %
                       (self.varNameX, self.varNameY))
        return msg

    def _validate(self):
        self.getXYvars()
        errors = []
        if self.varNameX != None:
            experiment = self.readExperiment(self.getInputExperiment().fnPKPD,
                                             False)
            if not self.varNameX in experiment.variables:
                errors.append("Cannot find %s as variable" % self.varNameX)
            if type(self.varNameY) == list:
                for y in self.varNameY:
                    if not y in experiment.variables:
                        errors.append("Cannot find %s as variable" % y)
            else:
                if not self.varNameY in experiment.variables:
                    errors.append("Cannot find %s as variable" % self.varNameY)
        if self.bounds.get() == "":
            errors.append("Bounds are required")
        return errors

    def _citations(self):
        return ['Spiess2010']

    def filterVarForWizard(self, v):
        """ Define the type of variables required (used in wizard). """
        return v.isNumeric() and (v.isTime() or v.isMeasurement())
Exemplo n.º 11
0
    def runFit(self, objId, otherDependencies):
        reportX = parseRange(self.reportX.get())
        self.setInputExperiment()

        # Setup model
        self.getXYvars()

        # Create output object
        self.fitting = PKPDFitting()
        self.fitting.fnExperiment.set(self._getPath("experiment.pkpd"))
        self.fitting.predictor = self.experiment.variables[self.varNameX]
        if type(self.varNameY) == list:
            self.fitting.predicted = []
            for y in self.varNameY:
                self.fitting.predicted.append(self.experiment.variables[y])
        else:
            self.fitting.predicted = self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        if self.fitType.get() == 0:
            fitType = "linear"
        elif self.fitType.get() == 1:
            fitType = "log"
        elif self.fitType.get() == 2:
            fitType = "relative"

        for groupName, group in self.experiment.groups.items():
            self.printSection("Fitting " + groupName)
            self.clearGroupParameters()

            for sampleName in group.sampleList:
                print("   Sample " + sampleName)
                sample = self.experiment.samples[sampleName]

                self.createDrugSource()
                self.setupModel()

                # Get the values to fit
                x, y = sample.getXYValues(self.varNameX, self.varNameY)
                print("X= " + str(x))
                print("Y= " + str(y))
                print(" ")

                # Interpret the dose
                self.setTimeRange(sample)
                sample.interpretDose()

                self.drugSource.setDoses(sample.parsedDoseList, self.model.t0,
                                         self.model.tF)
                self.configureSource(self.drugSource)
                self.model.drugSource = self.drugSource

                # Prepare the model
                self.setBounds(sample)
                self.setXYValues(x, y)
                self.addSample(sample)
                self.prepareForSampleAnalysis(sampleName)
                self.calculateParameterUnits(sample)
                if self.fitting.modelParameterUnits == None:
                    self.fitting.modelParameterUnits = self.parameterUnits

            self.printSetup()
            self.x = self.mergeLists(self.XList)
            self.y = self.mergeLists(self.YList)

            if self.globalSearch:
                optimizer1 = PKPDDEOptimizer(self, fitType)
                optimizer1.optimize()
            else:
                self.parameters = np.zeros(len(self.boundsList), np.double)
                n = 0
                for bound in self.boundsList:
                    self.parameters[n] = 0.5 * (bound[0] + bound[1])
                    n += 1
            try:
                optimizer2 = PKPDLSOptimizer(self, fitType)
                optimizer2.optimize()
            except Exception as e:
                msg = "Error: " + str(e)
                msg += "\nErrors in the local optimizer may be caused by starting from a bad initial guess\n"
                msg += "Try performing a global search first or changing the bounding box"
                raise Exception("Error in the local optimizer\n" + msg)
            optimizer2.setConfidenceInterval(self.getConfidenceInterval())
            self.setParameters(optimizer2.optimum)
            optimizer2.evaluateQuality()
            self.model.printOtherParameterization()

            self.yPredictedList = self.separateLists(self.yPredicted)
            self.yPredictedLowerList = self.separateLists(self.yPredictedLower)
            self.yPredictedUpperList = self.separateLists(self.yPredictedUpper)

            n = 0
            for sampleName in group.sampleList:
                sample = self.experiment.samples[sampleName]

                # Keep this result
                sampleFit = PKPDSampleFit()
                sampleFit.sampleName = sample.sampleName
                sampleFit.x = self.XList[n]
                sampleFit.y = self.YList[n]
                sampleFit.yp = self.yPredictedList[n]
                sampleFit.yl = self.yPredictedLowerList[n]
                sampleFit.yu = self.yPredictedUpperList[n]
                sampleFit.parameters = self.parameters
                sampleFit.modelEquation = self.getEquation()
                sampleFit.copyFromOptimizer(optimizer2)
                self.fitting.sampleFits.append(sampleFit)

                # Add the parameters to the sample and experiment
                for varName, varUnits, description, varValue in izip(
                        self.getParameterNames(), self.parameterUnits,
                        self.getParameterDescriptions(), self.parameters):
                    self.experiment.addParameterToSample(sampleName,
                                                         varName,
                                                         varUnits,
                                                         description,
                                                         varValue,
                                                         rewrite=True)
                self.experiment.addParameterToSample(sampleName,
                                                     "R2",
                                                     PKPDUnit.UNIT_NONE,
                                                     "Fitting R2",
                                                     sampleFit.R2,
                                                     rewrite=True)

                self.postSampleAnalysis(sampleName)

                if reportX != None:
                    print("Evaluation of the model at specified time points")
                    self.model.tF = np.max(reportX)
                    yreportX = self.model.forwardModel(self.model.parameters,
                                                       reportX)
                    print("==========================================")
                    print("X     Ypredicted     log10(Ypredicted)")
                    print("==========================================")
                    for n in range(0, reportX.shape[0]):
                        aux = 0
                        if yreportX[n] > 0:
                            aux = math.log10(yreportX[n])
                        print("%f %f %f" % (reportX[n], yreportX[n], aux))
                    print(' ')

                n += 1

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.getDescription()
        self.fitting.write(self._getPath("fitting.pkpd"))
        self.experiment.general['Model'] = self.getDescription()
        self.experiment.write(self._getPath("experiment.pkpd"))
Exemplo n.º 12
0
class ProtPKPDDissolutionPKSimulation(ProtPKPD):
    """ This protocol simulates the pharmacokinetic response of an ODE model when it is given a single dose of
        an drug whose release is modelled by an in vitro fitting and an in vitro-in vivo correlation."""

    _label = 'simulate PK response'

    #--------------------------- DEFINE param functions --------------------------------------------
    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam(
            'inputInVitro',
            params.PointerParam,
            label="Dissolution profiles in vitro",
            pointerClass='PKPDFitting',
            help='Select a fitting with dissolution profiles. '
            'It is assumed that the input dissolution profile is a percentage, between 0 and 100'
        )
        form.addParam(
            'inputPK',
            params.PointerParam,
            label="Pharmacokinetic model",
            pointerClass='PKPDFitting',
            help='Select the PK model to be simulated with this input')
        form.addParam(
            'usePKExperiment',
            params.BooleanParam,
            label="Use experiment from PK fitting",
            default=True,
            help='If True, the PK parameters are taken from the same fitting. '
            'If False, they are taken from another experiment')
        form.addParam(
            'inputPKOtherExperiment',
            params.PointerParam,
            label="Experiment with PK parameters",
            pointerClass='PKPDExperiment',
            condition='not usePKExperiment',
            help=
            'The experiment must have all the PK parameters specified by the PK model'
        )
        form.addParam(
            'ignorePKbioavailability',
            params.BooleanParam,
            default=False,
            label='Ignore PK bioavailability',
            help=
            'Ignore the bioavailability from the PK if it has been considered in the IVIVC'
        )
        form.addParam(
            'conversionType',
            params.EnumParam,
            label='Time/Response scaling',
            choices=['IVIVC', 'Levy plot', 'None'],
            default=0,
            help=
            'To convert the dissolution profile into an absorption profile you may use an IVIVC (Fabs output) or a Levy plot. '
            'The Levy plot can better represent what is happening in reality with patients.'
        )
        form.addParam(
            'inputIvIvC',
            params.PointerParam,
            label="In vitro-In vivo correlation",
            condition='conversionType==0',
            pointerClass='PKPDExperiment',
            help='Select the Fabs output of an in vitro-in vivo correlation')
        form.addParam('inputLevy',
                      params.PointerParam,
                      label="Levy plot",
                      condition='conversionType==1',
                      pointerClass='PKPDExperiment',
                      help='Select the output of a Levy plot protocol')
        form.addParam('inputDose', params.FloatParam, label="Dose", default=1,
                      help='Make sure that it is in the same units as the ones at which the PK was estimated. '\
                           'This dose will be given simpy once (single dose).')
        form.addParam(
            'includeTlag',
            params.BooleanParam,
            label="Include PK tlag",
            default=True,
            help=
            'If you include the tlag (if available), the simulations will be done with the same PK tlag as '
            'the input PK population. If not, tlag will be set to 0.')
        form.addParam(
            'allCombinations',
            params.BooleanParam,
            label="All combinations of dissolutions/PK",
            default=False,
            help=
            'If set to True, then all combinations of dissolutions and PK profiles are tested. '
            'Otherwise, only a random subset is chosen')
        form.addParam('inputN',
                      params.IntParam,
                      label="Number of simulations",
                      default=100,
                      condition='not allCombinations')
        form.addParam('t0',
                      params.FloatParam,
                      label="Initial time (h)",
                      default=0)
        form.addParam('tF',
                      params.FloatParam,
                      label="Final time (h)",
                      default=48)
        form.addParam('addIndividuals',
                      params.BooleanParam,
                      label="Add individual simulations",
                      default=True,
                      expertLevel=LEVEL_ADVANCED,
                      help="Individual simulations are added to the output")
        form.addParam(
            'NCAt0',
            params.StringParam,
            label="NCA Initial time (h)",
            default="",
            help=
            "The non-compartimental analysis is performed within NCA t0 and NCA tF. Leave empty for the whole period"
        )
        form.addParam(
            'NCAtF',
            params.StringParam,
            label="NCA Final time (h)",
            default="",
            help=
            "The non-compartimental analysis is performed within NCA t0 and NCA tF. Leave empty for the whole period"
        )

    #--------------------------- INSERT steps functions --------------------------------------------
    def _insertAllSteps(self):
        self._insertFunctionStep('simulate',
                                 self.inputInVitro.get().getObjId(),
                                 self.inputPK.get().getObjId(),
                                 self.inputDose.get(), self.inputN.get())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def getInVitroModels(self):
        fnFitting = self.inputInVitro.get().fnFitting
        cls = "PKPDSampleFitBootstrap" if fnFitting.get().find(
            "bootstrap") != -1 else ""
        self.fittingInVitro = PKPDFitting(cls)
        self.fittingInVitro.load(fnFitting)
        self.invitroClsName = self.fittingInVitro.modelDescription.split(
            '(')[1].split(')')[0]

        klass = globals()[self.invitroClsName]
        self.dissolutionModel = klass()
        self.dissolutionModel.allowTlag = "tlag" in self.fittingInVitro.modelParameters
        self.dissolutionPopulation = cls != ""

    def getScaling(self):
        self.allTimeScalings = {}
        self.allResponseScalings = {}
        if self.conversionType.get() == 0:
            experiment = self.readExperiment(self.inputIvIvC.get().fnPKPD,
                                             show=False)
        elif self.conversionType.get() == 1:
            experiment = self.readExperiment(self.inputLevy.get().fnPKPD,
                                             show=False)
        elif self.conversionType.get() == 2:
            experiment = self.readExperiment(
                self.inputInVitro.get().fnExperiment, show=False)
            tvar = experiment.getTimeVariable()
        for sampleName, sample in experiment.samples.items():
            if self.conversionType.get() == 0:
                vivo = sample.getValues("tvivo")
                vitro = sample.getValues("tvitroReinterpolated")
            elif self.conversionType.get() == 1:
                vivo = sample.getValues("tvivo")
                vitro = sample.getValues("tvitro")
            elif self.conversionType.get() == 2:
                vivo = sample.getValues(tvar)
                vitro = sample.getValues(tvar)
            if self.conversionType.get() != 2:
                fromSample = sample.getDescriptorValue("from")
                fromIndividual, _ = fromSample.split("---")
            else:
                fromSample = sample.sampleName
                fromIndividual = sample.sampleName
            if not fromIndividual in self.allTimeScalings.keys():
                self.allTimeScalings[fromIndividual] = []
            self.allTimeScalings[fromIndividual].append(
                (np.asarray(vitro, dtype=np.float64),
                 np.asarray(vivo, dtype=np.float64)))

            if self.conversionType.get() == 0:
                vivo = sample.getValues("FabsPredicted")
                vitro = sample.getValues("AdissolReinterpolated")
                if not fromIndividual in self.allResponseScalings.keys():
                    self.allResponseScalings[fromIndividual] = []
                self.allResponseScalings[fromIndividual].append(
                    (np.asarray(vitro, dtype=np.float64),
                     np.asarray(vivo, dtype=np.float64)))

    def getPKModels(self):
        fnFitting = self.inputPK.get().fnFitting
        cls = "PKPDSampleFitBootstrap" if fnFitting.get().find(
            "bootstrap") != -1 else ""
        self.fittingPK = PKPDFitting(cls)
        self.fittingPK.load(fnFitting)
        modelDescription = self.fittingPK.modelDescription.split(';')[
            1]  # Before ; there is the drug source description
        self.pkClsName = modelDescription.split('(')[1].split(')')[0]

        klass = globals()[self.pkClsName]
        self.pkModel = klass()
        self.pkModel.t0 = self.t0.get()
        self.pkModel.tF = self.tF.get()
        self.timeUnits = self.fittingPK.getTimeUnits().unit
        if self.timeUnits == PKPDUnit.UNIT_TIME_MIN:
            self.pkModel.t0 *= 60
            self.pkModel.tF *= 60
        self.pkModel.drugSource = DrugSource()
        dose = createDeltaDose(self.inputDose.get(),
                               via=createVia("Oral; numerical"))
        self.pkModel.drugSource.setDoses([dose], self.pkModel.t0,
                                         self.pkModel.tF)
        self.pkPopulation = cls != ""
        self.pkNParams = self.pkModel.getNumberOfParameters()

        self.tlagIdx = None
        if self.includeTlag.get():
            i = 0
            for prmName in self.fittingPK.modelParameters:
                if prmName.endswith('_tlag'):
                    self.tlagIdx = i
                    print("Found tlag in %s at position %d" % (prmName, i))
                    break
                i += 1
        self.bioavailabilityIdx = None
        if not self.ignorePKbioavailability.get():
            i = 0
            for prmName in self.fittingPK.modelParameters:
                if prmName.endswith('_bioavailability'):
                    self.bioavailabilityIdx = i
                    print("Found bioavailabilityIdx in %s at position %d" %
                          (prmName, i))
                    break
                i += 1

    def addSample(self, sampleName, t, y, fromSamples):
        newSample = PKPDSample()
        newSample.sampleName = sampleName
        newSample.variableDictPtr = self.outputExperiment.variables
        newSample.doseDictPtr = self.outputExperiment.doses
        newSample.descriptors = {}
        newSample.doseList = ["Bolus"]
        newSample.addMeasurementPattern([self.fittingPK.predicted.varName])
        newSample.addMeasurementColumn("t", t)
        newSample.addMeasurementColumn(self.fittingPK.predicted.varName, y)

        newSample.descriptors["AUC0t"] = self.AUC0t
        newSample.descriptors["AUMC0t"] = self.AUMC0t
        newSample.descriptors["MRT"] = self.MRT
        newSample.descriptors["Cmax"] = self.Cmax
        newSample.descriptors["Tmax"] = self.Tmax

        self.outputExperiment.samples[sampleName] = newSample
        self.outputExperiment.addLabelToSample(sampleName, "from",
                                               "individual---vesel",
                                               fromSamples)

    def NCA(self, t, C):
        self.AUC0t = 0
        self.AUMC0t = 0
        t0 = t[0]
        tperiod0 = 0  # Time at which the dose was given
        T0 = 0
        TF = np.max(t)
        if self.NCAt0.get() != "" and self.NCAtF.get() != "":
            T0 = float(self.NCAt0.get())
            TF = float(self.NCAtF.get())
            if self.timeUnits == PKPDUnit.UNIT_TIME_MIN:
                T0 *= 60
                TF *= 60

        for idx in range(0, t.shape[0] - 1):
            if t[idx] >= T0 and t[idx] <= TF:
                dt = (t[idx + 1] - t[idx])
                if C[idx + 1] >= C[idx]:  # Trapezoidal in the raise
                    self.AUC0t += 0.5 * dt * (C[idx] + C[idx + 1])
                    self.AUMC0t += 0.5 * dt * (C[idx] * t[idx] +
                                               C[idx + 1] * t[idx + 1])
                else:  # Log-trapezoidal in the decay
                    decrement = C[idx] / C[idx + 1]
                    K = math.log(decrement)
                    B = K / dt
                    self.AUC0t += dt * (C[idx] - C[idx + 1]) / K
                    self.AUMC0t += (C[idx] * (t[idx] - tperiod0) - C[idx + 1] *
                                    (t[idx + 1] - tperiod0)) / B - (
                                        C[idx + 1] - C[idx]) / (B * B)

                if idx == 0:
                    self.Cmax = C[idx]
                    self.Tmax = t[idx] - t0
                else:
                    if C[idx] > self.Cmax:
                        self.Cmax = C[idx]
                        self.Tmax = t[idx] - t0

        self.MRT = self.AUMC0t / self.AUC0t

        print("   Cmax=%f [%s]" % (self.Cmax, strUnit(self.Cunits.unit)))
        print("   Tmax=%f [%s]" % (self.Tmax, strUnit(self.timeUnits)))
        print("   AUC0t=%f [%s]" % (self.AUC0t, strUnit(self.AUCunits)))
        print("   AUMC0t=%f [%s]" % (self.AUMC0t, strUnit(self.AUMCunits)))
        print("   MRT=%f [%s]" % (self.MRT, strUnit(self.timeUnits)))

    def simulate(self, objId1, objId2, inputDose, inputN):
        import sys
        self.getInVitroModels()
        self.getScaling()
        self.getPKModels()

        if not self.usePKExperiment:
            otherPKExperiment = PKPDExperiment()
            otherPKExperiment.load(self.inputPKOtherExperiment.get().fnPKPD)

        self.outputExperiment = PKPDExperiment()
        tvar = PKPDVariable()
        tvar.varName = "t"
        tvar.varType = PKPDVariable.TYPE_NUMERIC
        tvar.role = PKPDVariable.ROLE_TIME
        tvar.units = createUnit(self.fittingPK.predictor.units.unit)

        self.Cunits = self.fittingPK.predicted.units
        self.AUCunits = multiplyUnits(tvar.units.unit, self.Cunits.unit)
        self.AUMCunits = multiplyUnits(tvar.units.unit, self.AUCunits)
        if self.addIndividuals.get():
            self.outputExperiment.variables["t"] = tvar
            self.outputExperiment.variables[
                self.fittingPK.predicted.varName] = self.fittingPK.predicted
            self.outputExperiment.general[
                "title"] = "Simulated ODE response from IVIVC dissolution profiles"
            self.outputExperiment.general[
                "comment"] = "Simulated ODE response from IVIVC dissolution profiles"
            for via, _ in self.pkModel.drugSource.vias:
                self.outputExperiment.vias[via.viaName] = via
            for dose in self.pkModel.drugSource.parsedDoseList:
                self.outputExperiment.doses[dose.doseName] = dose

            AUCvar = PKPDVariable()
            AUCvar.varName = "AUC0t"
            AUCvar.varType = PKPDVariable.TYPE_NUMERIC
            AUCvar.role = PKPDVariable.ROLE_LABEL
            AUCvar.units = createUnit(strUnit(self.AUCunits))

            AUMCvar = PKPDVariable()
            AUMCvar.varName = "AUMC0t"
            AUMCvar.varType = PKPDVariable.TYPE_NUMERIC
            AUMCvar.role = PKPDVariable.ROLE_LABEL
            AUMCvar.units = createUnit(strUnit(self.AUMCunits))

            MRTvar = PKPDVariable()
            MRTvar.varName = "MRT"
            MRTvar.varType = PKPDVariable.TYPE_NUMERIC
            MRTvar.role = PKPDVariable.ROLE_LABEL
            MRTvar.units = createUnit(
                self.outputExperiment.getTimeUnits().unit)

            Cmaxvar = PKPDVariable()
            Cmaxvar.varName = "Cmax"
            Cmaxvar.varType = PKPDVariable.TYPE_NUMERIC
            Cmaxvar.role = PKPDVariable.ROLE_LABEL
            Cmaxvar.units = createUnit(strUnit(self.Cunits.unit))

            Tmaxvar = PKPDVariable()
            Tmaxvar.varName = "Tmax"
            Tmaxvar.varType = PKPDVariable.TYPE_NUMERIC
            Tmaxvar.role = PKPDVariable.ROLE_LABEL
            Tmaxvar.units = createUnit(
                self.outputExperiment.getTimeUnits().unit)

            self.outputExperiment.variables["AUC0t"] = AUCvar
            self.outputExperiment.variables["AUMC0t"] = AUMCvar
            self.outputExperiment.variables["MRT"] = MRTvar
            self.outputExperiment.variables["Cmax"] = Cmaxvar
            self.outputExperiment.variables["Tmax"] = Tmaxvar

        t = np.arange(self.pkModel.t0, self.pkModel.tF, 1)

        if self.usePKExperiment:
            NPKFits = len(self.fittingPK.sampleFits)
            invivoFits = self.fittingPK.sampleFits
        else:
            NPKFits = len(otherPKExperiment.samples)
            invivoFits = [x for x in otherPKExperiment.samples.values()]
            for sample in invivoFits:
                sample.parameters = [
                    float(x) for x in sample.getDescriptorValues(
                        self.fittingPK.modelParameters)
                ]

        NDissolFits = len(self.fittingInVitro.sampleFits)

        if self.allCombinations:
            inputN = NPKFits * NDissolFits

        AUCarray = np.zeros(inputN)
        AUMCarray = np.zeros(inputN)
        MRTarray = np.zeros(inputN)
        CmaxArray = np.zeros(inputN)
        TmaxArray = np.zeros(inputN)

        for i in range(0, inputN):
            print("Simulation no. %d ----------------------" % i)

            # Get a random PK model
            if self.allCombinations:
                nfit = int(i / NDissolFits)
            else:
                nfit = int(random.uniform(0, NPKFits))
            sampleFitVivo = invivoFits[nfit]
            print("In vivo sample name=", sampleFitVivo.sampleName)
            if self.pkPopulation:
                nbootstrap = int(
                    random.uniform(0, sampleFitVivo.parameters.shape[0]))
                pkPrmAll = sampleFitVivo.parameters[nbootstrap, :]
            else:
                pkPrmAll = sampleFitVivo.parameters
            pkPrm = pkPrmAll[-self.pkNParams:]  # Get the last Nparams
            print("PK parameters: ", pkPrm)

            tlag = 0
            if self.includeTlag.get() and (not self.tlagIdx is None):
                tlag = pkPrmAll[self.tlagIdx]
                print("tlag: ", tlag)
            bioavailability = 1
            if not self.bioavailabilityIdx is None:
                bioavailability = pkPrmAll[self.bioavailabilityIdx]
                print("bioavailability: ", bioavailability)

            # Get a dissolution profile
            if self.allCombinations:
                nfit = i % NDissolFits
            else:
                nfit = int(random.uniform(0, NDissolFits))
            sampleFitVitro = self.fittingInVitro.sampleFits[nfit]
            if self.dissolutionPopulation:
                nbootstrap = int(
                    random.uniform(0, sampleFitVitro.parameters.shape[0]))
                dissolutionPrm = sampleFitVitro.parameters[nbootstrap, :]
            else:
                dissolutionPrm = sampleFitVitro.parameters
            print(
                "Dissolution parameters: ",
                np.array2string(np.asarray(dissolutionPrm, dtype=np.float64),
                                max_line_width=1000))
            sys.stdout.flush()

            if sampleFitVivo.sampleName in self.allTimeScalings:
                keyToUse = sampleFitVivo.sampleName
            elif len(self.allTimeScalings) == 1:
                keyToUse = list(self.allTimeScalings.keys())[0]
            else:
                raise Exception("Cannot find %s in the scaling keys" %
                                sampleFitVivo.sampleName)
            nfit = int(random.uniform(0, len(self.allTimeScalings[keyToUse])))

            tvitroLevy, tvivoLevy = self.allTimeScalings[keyToUse][nfit]
            tvivoLevyUnique, tvitroLevyUnique = uniqueFloatValues(
                tvivoLevy, tvitroLevy)
            BLevy = InterpolatedUnivariateSpline(tvivoLevyUnique,
                                                 tvitroLevyUnique,
                                                 k=1)

            tvitro = np.asarray(BLevy(t), dtype=np.float64)
            A = np.clip(
                self.dissolutionModel.forwardModel(dissolutionPrm, tvitro)[0],
                0, 100)

            if self.conversionType.get() == 0:
                # In vitro-in vivo correlation
                Adissol, Fabs = self.allResponseScalings[keyToUse][nfit]
                AdissolUnique, FabsUnique = uniqueFloatValues(Adissol, Fabs)
                B = InterpolatedUnivariateSpline(AdissolUnique,
                                                 FabsUnique,
                                                 k=1)
                A = np.asarray(B(A), dtype=np.float64)

            # Set the dissolution profile
            self.pkModel.drugSource.getVia().viaProfile.setXYValues(t, A)
            C = self.pkModel.forwardModel(
                pkPrm, [t])[0]  # forwardModel returns a list of arrays
            if tlag != 0.0:
                B = interp1d(t, C)
                C = B(np.clip(t - tlag, 0.0, None))
                C[0:int(tlag)] = 0.0
            C *= bioavailability

            self.NCA(t, C)
            AUCarray[i] = self.AUC0t
            AUMCarray[i] = self.AUMC0t
            MRTarray[i] = self.MRT
            CmaxArray[i] = self.Cmax
            TmaxArray[i] = self.Tmax

            if self.addIndividuals:
                self.addSample(
                    "Simulation_%d" % i, t, C, "%s---%s" %
                    (sampleFitVivo.sampleName, sampleFitVitro.sampleName))

        # Report NCA statistics
        alpha_2 = (100 - 95) / 2
        limits = np.percentile(AUCarray, [alpha_2, 100 - alpha_2])
        fhSummary = open(self._getPath("summary.txt"), "w")
        self.doublePrint(
            fhSummary, "AUC %f%% confidence interval=[%f,%f] [%s] mean=%f" %
            (95, limits[0], limits[1], strUnit(
                self.AUCunits), np.mean(AUCarray)))
        limits = np.percentile(AUMCarray, [alpha_2, 100 - alpha_2])
        self.doublePrint(
            fhSummary, "AUMC %f%% confidence interval=[%f,%f] [%s] mean=%f" %
            (95, limits[0], limits[1], strUnit(
                self.AUMCunits), np.mean(AUMCarray)))
        limits = np.percentile(MRTarray, [alpha_2, 100 - alpha_2])
        self.doublePrint(
            fhSummary, "MRT %f%% confidence interval=[%f,%f] [%s] mean=%f" %
            (95, limits[0], limits[1], strUnit(
                self.timeUnits), np.mean(MRTarray)))
        limits = np.percentile(CmaxArray, [alpha_2, 100 - alpha_2])
        self.doublePrint(
            fhSummary, "Cmax %f%% confidence interval=[%f,%f] [%s] mean=%f" %
            (95, limits[0], limits[1], strUnit(
                self.Cunits.unit), np.mean(CmaxArray)))
        limits = np.percentile(TmaxArray, [alpha_2, 100 - alpha_2])
        self.doublePrint(
            fhSummary, "Tmax %f%% confidence interval=[%f,%f] [%s] mean=%f" %
            (95, limits[0], limits[1], strUnit(
                self.timeUnits), np.mean(TmaxArray)))
        fhSummary.close()

        if self.addIndividuals:
            self.outputExperiment.write(self._getPath("experiment.pkpd"),
                                        writeToExcel=False)

    def createOutputStep(self):
        if self.addIndividuals:
            self._defineOutputs(outputExperiment=self.outputExperiment)
            self._defineSourceRelation(self.inputInVitro.get(),
                                       self.outputExperiment)
            self._defineSourceRelation(self.inputPK.get(),
                                       self.outputExperiment)
            if self.conversionType.get() == 0:
                self._defineSourceRelation(self.inputIvIvC.get(),
                                           self.outputExperiment)
            elif self.conversionType.get() == 1:
                self._defineSourceRelation(self.inputLevy.get(),
                                           self.outputExperiment)

    def _validate(self):
        retval = []
        if self.conversionType.get(
        ) == 0 and not "experimentFabs" in self.inputIvIvC.get().fnPKPD.get():
            retval.append(
                "If the conversion is done from IVIVC, then you must take the Fabs output"
            )
        return retval

    def _summary(self):
        retval = []
        retval.append('Dose=%f' % self.inputDose.get())
        retval.append('No. simulations=%d' % self.inputN.get())
        retval.append(' ')
        self.addFileContentToMessage(retval, self._getPath("summary.txt"))
        return retval
Exemplo n.º 13
0
    def runFit(self, objId, Nbootstrap, confidenceInterval):
        self.protFit = self.inputFit.get()
        self.experiment = self.readExperiment(
            self.protFit.outputExperiment.fnPKPD)
        self.fitting = self.readFitting(self.protFit.outputFitting.fnFitting)

        # Get the X and Y variable names
        self.varNameX = self.fitting.predictor.varName
        self.varNameY = self.fitting.predicted.varName
        self.protFit.experiment = self.experiment
        self.protFit.varNameX = self.varNameX
        self.protFit.varNameY = self.varNameY

        # Setup model
        self.printSection("Model setup")
        self.protFit.model = self.protFit.createModel()
        self.protFit.model.setExperiment(self.experiment)
        self.protFit.model.setXVar(self.varNameX)
        self.protFit.model.setYVar(self.varNameY)
        self.protFit.setupFromFormParameters()
        self.protFit.setupModel()
        self.protFit.model.setBounds(self.protFit.bounds.get())
        self.protFit.model.printSetup()
        self.model = self.protFit.model

        # Setup self as model
        self.boundsList = self.model.bounds

        # Create output object
        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.experiment.fnPKPD.get())
        self.fitting.predictor = self.experiment.variables[self.varNameX]
        self.fitting.predicted = self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        if self.protFit.fitType.get() == 0:
            fitType = "linear"
        elif self.protFit.fitType.get() == 1:
            fitType = "log"
        elif self.protFit.fitType.get() == 2:
            fitType = "relative"

        parameterNames = self.model.getParameterNames()
        for sampleName, sample in self.experiment.samples.items():
            self.printSection("Fitting " + sampleName)

            x, y = sample.getXYValues(self.varNameX, self.varNameY)
            print("X= " + str(x))
            print("Y= " + str(y))
            print(" ")

            self.model.setXYValues(x, y)
            self.prepareForSampleAnalysis(sampleName)
            self.model.calculateParameterUnits(sample)
            if self.fitting.modelParameterUnits == None:
                self.fitting.modelParameterUnits = self.model.parameterUnits
            self.model.prepare()
            if self.model.bounds == None:
                continue
            print(" ")

            # Get the initial parameters
            parameters0 = []
            for parameterName in parameterNames:
                parameters0.append(float(sample.descriptors[parameterName]))
            print("Initial solution: %s" % str(parameters0))
            print(" ")

            # Output object
            sampleFit = PKPDSampleFitBootstrap()
            sampleFit.sampleName = sample.sampleName
            sampleFit.parameters = np.zeros(
                (self.Nbootstrap.get(), len(parameters0)), np.double)
            sampleFit.xB = []
            sampleFit.yB = []

            # Bootstrap samples
            firstX = x[0]  # From [array(...)] to array(...)
            firstY = y[0]  # From [array(...)] to array(...)
            idx = [k for k in range(0, len(firstX))]
            for n in range(0, self.Nbootstrap.get()):
                ok = False
                while not ok:
                    lenToUse = len(idx)
                    idxB = sorted(np.random.choice(idx, lenToUse))
                    xB = [np.asarray([firstX[i] for i in idxB])]
                    yB = [np.asarray([firstY[i] for i in idxB])]

                    print("Bootstrap sample %d" % n)
                    print("X= " + str(xB))
                    print("Y= " + str(yB))
                    self.model.setXYValues(xB, yB)
                    self.model.parameters = parameters0

                    optimizer2 = PKPDLSOptimizer(self.model, fitType)
                    optimizer2.verbose = 0
                    try:
                        optimizer2.optimize()
                        ok = True
                    except Exception as e:
                        print(e)
                        raise (e)
                        ok = False

                # Evaluate the quality on the whole data set
                self.model.setXYValues(x, y)
                optimizer2.evaluateQuality()
                print(optimizer2.optimum)
                print("   R2 = %f R2Adj=%f AIC=%f AICc=%f BIC=%f"%(optimizer2.R2,optimizer2.R2adj,optimizer2.AIC,\
                                                                   optimizer2.AICc,optimizer2.BIC))

                # Keep this result
                sampleFit.parameters[n, :] = optimizer2.optimum
                sampleFit.xB.append(str(xB[0]))
                sampleFit.yB.append(str(yB[0]))
                sampleFit.copyFromOptimizer(optimizer2)

            self.fitting.sampleFits.append(sampleFit)

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.model.getDescription()
        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))
Exemplo n.º 14
0
    def runFit(self, objId, deltaT):
        self.protODE = self.inputODE.get()
        self.experiment = self.readExperiment(self.protODE.outputExperiment.fnPKPD)
        self.fitting = self.readFitting(self.protODE.outputFitting.fnFitting)

        # Get the X and Y variable names
        self.varNameX = self.fitting.predictor.varName
        if type(self.fitting.predicted)==list:
            self.varNameY = [v.varName for v in self.fitting.predicted]
        else:
            self.varNameY = self.fitting.predicted.varName
        self.protODE.experiment = self.experiment
        self.protODE.setVarNames(self.varNameX, self.varNameY)

        # Create output object
        self.fitting = PKPDFitting()
        self.fitting.fnExperiment.set(self.experiment.fnPKPD.get())
        self.fitting.predictor=self.experiment.variables[self.varNameX]
        self.fitting.predicted=self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        fitTypeN = self.protODE.fitType.get() if self.fitType.get()==3 else self.fitType.get()
        if fitTypeN==0:
            fitType = "linear"
        elif fitTypeN==1:
            fitType = "log"
        elif fitTypeN==2:
            fitType = "relative"

        parameterNames = None
        for groupName, group in self.experiment.groups.items():
            self.printSection("Fitting "+groupName)
            self.protODE.clearGroupParameters()
            self.clearGroupParameters()

            for sampleName in group.sampleList:
                print("   Sample "+sampleName)
                sample = self.experiment.samples[sampleName]

                self.protODE.createDrugSource()
                self.protODE.setupModel()

                # Setup self model
                self.drugSource = self.protODE.drugSource
                self.drugSourceList = self.protODE.drugSourceList
                self.model = self.protODE.model
                self.modelList = self.protODE.modelList
                self.model.deltaT = self.deltaT.get()
                self.model.setXVar(self.varNameX)
                self.model.setYVar(self.varNameY)

                # Get the values to fit
                x, y = sample.getXYValues(self.varNameX,self.varNameY)
                print("X= "+str(x))
                print("Y= "+str(y))

                # Interpret the dose
                self.protODE.varNameX = self.varNameX
                self.protODE.varNameY = self.varNameY
                self.protODE.model = self.model
                self.protODE.setTimeRange(sample)
                sample.interpretDose()

                self.drugSource.setDoses(sample.parsedDoseList, self.model.t0, self.model.tF)
                self.protODE.configureSource(self.drugSource)
                self.model.drugSource = self.drugSource

                # Prepare the model
                self.model.setSample(sample)
                self.calculateParameterUnits(sample)
                if self.fitting.modelParameterUnits==None:
                    self.fitting.modelParameterUnits = self.parameterUnits

                # Get the initial parameters
                if parameterNames==None:
                    parameterNames = self.getParameterNames()
                parameters0 = []
                for parameterName in parameterNames:
                    parameters0.append(float(sample.descriptors[parameterName]))
                print("Initial solution: %s"%str(parameters0))
                print(" ")

                # Set bounds
                self.setBounds(sample)
                self.setXYValues(x, y)
                self.parameters = parameters0

            self.printSetup()
            self.x = self.mergeLists(self.XList)
            self.y = self.mergeLists(self.YList)

            optimizer2 = PKPDLSOptimizer(self,fitType)
            optimizer2.optimize()
            optimizer2.setConfidenceInterval(self.protODE.getConfidenceInterval())
            self.setParameters(optimizer2.optimum)

            n=0
            for sampleName in group.sampleList:
                sample = self.experiment.samples[sampleName]

                # Keep this result
                sampleFit = PKPDSampleFit()
                sampleFit.sampleName = sample.sampleName
                sampleFit.x = x
                sampleFit.y = y
                sampleFit.yp = self.yPredicted
                sampleFit.yl = self.yPredictedLower
                sampleFit.yu = self.yPredictedUpper
                sampleFit.parameters = self.parameters
                sampleFit.modelEquation = self.getEquation()
                sampleFit.copyFromOptimizer(optimizer2)
                self.fitting.sampleFits.append(sampleFit)

                # Add the parameters to the sample and experiment
                for varName, varUnits, description, varValue in izip(self.getParameterNames(), self.parameterUnits, self.getParameterDescriptions(), self.parameters):
                    self.experiment.addParameterToSample(sampleName, varName, varUnits, description, varValue, rewrite=True)

                n+=1

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.getDescription()
        self.fitting.write(self._getPath("fitting.pkpd"))
        self.experiment.write(self._getPath("experiment.pkpd"))
Exemplo n.º 15
0
class ProtPKPDMergePopulations(ProtPKPD):
    """ Merge two populations. Both populations must have the same labels\n
        Protocol created by http://www.kinestatpharma.com\n """
    _label = 'merge populations'

    #--------------------------- DEFINE param functions --------------------------------------------

    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam(
            'inputPopulation1',
            params.PointerParam,
            label="Population 1",
            important=True,
            pointerClass='PKPDFitting',
            pointerCondition="isPopulation",
            help='It must be a fitting coming from a bootstrap sample')
        form.addParam(
            'inputPopulation2',
            params.PointerParam,
            label="Population 2",
            important=True,
            pointerClass='PKPDFitting',
            pointerCondition="isPopulation",
            help='It must be a fitting coming from a bootstrap sample')

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

    def _insertAllSteps(self):
        self._insertFunctionStep('runMerge',
                                 self.inputPopulation1.get().getObjId(),
                                 self.inputPopulation2.getObjId())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def runMerge(self, objId1, objId2):
        self.population1 = self.readFitting(
            self.inputPopulation1.get().fnFitting,
            cls="PKPDSampleFitBootstrap")
        self.population2 = self.readFitting(
            self.inputPopulation2.get().fnFitting,
            cls="PKPDSampleFitBootstrap")
        self.printSection("Merging populations")

        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.population1.fnExperiment)
        self.fitting.predictor = self.population1.predictor
        self.fitting.predicted = self.population1.predicted
        self.fitting.modelParameterUnits = self.population1.modelParameterUnits
        self.fitting.modelParameters = self.population1.modelParameters
        self.fitting.modelDescription = self.population1.modelDescription

        newSampleFit = PKPDSampleFitBootstrap()
        newSampleFit.sampleName = "Merged population"
        newSampleFit.parameters = None
        for sampleFit in self.population1.sampleFits:
            if newSampleFit.parameters == None:
                newSampleFit.parameters = np.copy(sampleFit.parameters)
                newSampleFit.xB = copy.copy(sampleFit.xB)
                newSampleFit.yB = copy.copy(sampleFit.yB)
                newSampleFit.R2 = copy.copy(sampleFit.R2)
                newSampleFit.R2adj = copy.copy(sampleFit.R2adj)
                newSampleFit.AIC = copy.copy(sampleFit.AIC)
                newSampleFit.AICc = copy.copy(sampleFit.AICc)
                newSampleFit.BIC = copy.copy(sampleFit.BIC)
            else:
                newSampleFit.parameters = np.vstack(
                    [newSampleFit.parameters, sampleFit.parameters])
                newSampleFit.xB += sampleFit.xB
                newSampleFit.yB += sampleFit.yB
                newSampleFit.R2 += sampleFit.R2
                newSampleFit.R2adj += sampleFit.R2adj
                newSampleFit.AIC += sampleFit.AIC
                newSampleFit.AICc += sampleFit.AICc
                newSampleFit.BIC += sampleFit.BIC
        for sampleFit in self.population2.sampleFits:
            newSampleFit.parameters = np.vstack(
                [newSampleFit.parameters, sampleFit.parameters])
            print(type(newSampleFit.xB))
            print(type(sampleFit.xB))
            newSampleFit.xB += sampleFit.xB
            newSampleFit.yB += sampleFit.yB
            newSampleFit.R2 += sampleFit.R2
            newSampleFit.R2adj += sampleFit.R2adj
            newSampleFit.AIC += sampleFit.AIC
            newSampleFit.AICc += sampleFit.AICc
            newSampleFit.BIC += sampleFit.BIC
        self.fitting.sampleFits.append(newSampleFit)

        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))

    def createOutputStep(self):
        self._defineOutputs(outputPopulation=self.fitting)
        self._defineSourceRelation(self.inputPopulation1, self.fitting)
        self._defineSourceRelation(self.inputPopulation2, self.fitting)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        msg = [
            "Populations %s and %s were merged" %
            (self.getObjectTag(self.inputPopulation1.get()),
             self.getObjectTag(self.inputPopulation2.get()))
        ]
        return msg

    def _validate(self):
        msg = []
        if not self.inputPopulation1.get().fnFitting.get().endswith(
                "bootstrapPopulation.pkpd"):
            msg.append("Population 1 must be a bootstrap sample")
        if not self.inputPopulation2.get().fnFitting.get().endswith(
                "bootstrapPopulation.pkpd"):
            msg.append("Population 2 must be a bootstrap sample")
        return msg
Exemplo n.º 16
0
class ProtPKPDODEBootstrap(ProtPKPDODEBase):
    """ Bootstrap of an ODE protocol"""

    _label = 'ODE bootstrap'

    PRM_PROTOCOL = 0
    PRM_FITTING = 1

    #--------------------------- DEFINE param functions --------------------------------------------
    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam('inputODE', params.PointerParam, label="Input ODE model",
                      pointerClass='ProtPKPDMonoCompartment, ProtPKPDMonoCompartmentUrine, ProtPKPDTwoCompartments, '\
                                   'ProtPKPDTwoCompartmentsAutoinduction, ProtPKPDTwoCompartmentsClint, '\
                                   'ProtPKPDTwoCompartmentsClintCl, '\
                                   'ProtPKPDTwoCompartmentsClintMetabolite, ProtPKPDTwoCompartmentsUrine, '\
                                   'ProtPKPDODERefine',
                      help='Select a run of an ODE model')
        form.addParam(
            'paramsSource',
            params.EnumParam,
            label="Source of parameters",
            choices=['ODE protocol', 'ODE Fitting'],
            default=0,
            help=
            "Choose a population of parameters, your own parameters or a previously fitted set of measurements"
        )
        form.addParam(
            'inputFitting',
            params.PointerParam,
            label="Input ODE fitting",
            condition="paramsSource==1",
            pointerClass='PKPDFitting',
            help='It must be a fitting coming from a compartmental PK fitting')
        form.addParam('Nbootstrap',
                      params.IntParam,
                      label="Bootstrap samples",
                      default=200,
                      expertLevel=LEVEL_ADVANCED,
                      help='Number of bootstrap realizations for each sample')
        form.addParam('sampleLength', params.IntParam, label="Sample length", default=-1, expertLevel=LEVEL_ADVANCED,
                      help='If the input experiment represents a population, the bootstrap sample is so overdetermined '\
                           'that the bootstrap parameter estimate seldom moves from the original values. In this case, '\
                           'you may use the sample length to generate bootstrap samples of the same length as the indiviudals '\
                           'taking part of the population. If this value is set to -1, then the length of the bootstrap sample '\
                           'will be the same as the one in the input experiment. If set to any other value, e.g. 8, then '\
                           'each bootstrap sample will have this length')
        form.addParam('confidenceInterval',
                      params.FloatParam,
                      label="Confidence interval",
                      default=95,
                      expertLevel=LEVEL_ADVANCED,
                      help='Confidence interval for the fitted parameters')
        form.addParam('deltaT',
                      params.FloatParam,
                      default=2,
                      label='Step (min)',
                      expertLevel=LEVEL_ADVANCED)

    #--------------------------- INSERT steps functions --------------------------------------------
    def _insertAllSteps(self):
        self._insertFunctionStep('runFit',
                                 self.inputODE.get().getObjId(),
                                 self.Nbootstrap.get(),
                                 self.confidenceInterval.get())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def parseBounds(self, boundsString):
        if boundsString != "" and boundsString != None:
            tokens = boundsString.split(';')
            if len(tokens) != self.getNumberOfParameters():
                raise Exception(
                    "The number of bound intervals does not match the number of parameters"
                )
            self.boundsList = []
            for token in tokens:
                values = token.strip().split(',')
                self.boundsList.append(
                    (float(values[0][1:]), float(values[1][:-1])))

    def setBounds(self, sample):
        self.parseBounds(self.protODE.bounds.get())
        self.setBoundsFromBoundsList()

    def setBoundsFromBoundsList(self):
        Nbounds = len(self.boundsList)
        Nsource = self.drugSource.getNumberOfParameters()
        Nmodel = self.model.getNumberOfParameters()
        if Nbounds != Nsource + Nmodel:
            raise "The number of parameters (%d) and bounds (%d) are different" % (
                Nsource + Nmodel, Nbounds)
        self.boundsSource = self.boundsList[0:Nsource]
        self.boundsPK = self.boundsList[Nsource:]
        self.model.bounds = self.boundsPK

    def getBounds(self):
        return self.boundsList

    def runFit(self, objId, Nbootstrap, confidenceInterval):
        self.protODE = self.inputODE.get()
        if self.paramsSource.get() == self.PRM_PROTOCOL:
            self.experiment = self.readExperiment(
                self.protODE.outputExperiment.fnPKPD)
            self.fitting = self.readFitting(
                self.protODE.outputFitting.fnFitting)
        else:
            self.fitting = self.readFitting(self.inputFitting.get().fnFitting)
            self.experiment = self.readExperiment(
                self.inputFitting.get().fnExperiment)

        # Get the X and Y variable names
        self.varNameX = self.fitting.predictor.varName
        if type(self.fitting.predicted) == list:
            self.varNameY = [v.varName for v in self.fitting.predicted]
        else:
            self.varNameY = self.fitting.predicted.varName
        self.protODE.experiment = self.experiment
        self.protODE.varNameX = self.varNameX
        self.protODE.varNameY = self.varNameY

        # Create output object
        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.experiment.fnPKPD.get())
        self.fitting.predictor = self.experiment.variables[self.varNameX]
        if type(self.varNameY) == list:
            self.fitting.predicted = [
                self.experiment.variables[v] for v in self.varNameY
            ]
        else:
            self.fitting.predicted = self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        if self.protODE.fitType.get() == 0:
            fitType = "linear"
        elif self.protODE.fitType.get() == 1:
            fitType = "log"
        elif self.protODE.fitType.get() == 2:
            fitType = "relative"

        parameterNames = None
        for groupName, group in self.experiment.groups.items():
            self.printSection("Fitting " + groupName)
            self.protODE.clearGroupParameters()
            self.clearGroupParameters()

            for sampleName in group.sampleList:
                print("   Sample " + sampleName)
                sample = self.experiment.samples[sampleName]

                self.protODE.createDrugSource()
                self.protODE.setupModel()

                # Setup self model
                self.drugSource = self.protODE.drugSource
                self.drugSourceList = self.protODE.drugSourceList
                self.model = self.protODE.model
                self.modelList = self.protODE.modelList
                self.model.deltaT = self.deltaT.get()
                self.model.setXVar(self.varNameX)
                self.model.setYVar(self.varNameY)

                # Get the values to fit
                x, y = sample.getXYValues(self.varNameX, self.varNameY)
                print("X= " + str(x))
                print("Y= " + str(y))
                firstX = x[0]  # From [array(...)] to array(...)
                firstY = y[0]  # From [array(...)] to array(...)

                # Interpret the dose
                self.protODE.setVarNames(self.varNameX, self.varNameY)
                self.protODE.setModel(self.model)
                self.protODE.setTimeRange(sample)
                sample.interpretDose()

                self.drugSource.setDoses(sample.parsedDoseList, self.model.t0,
                                         self.model.tF)
                self.protODE.configureSource(self.drugSource)
                self.model.drugSource = self.drugSource

                # Prepare the model
                self.model.setSample(sample)
                self.calculateParameterUnits(sample)
                if self.fitting.modelParameterUnits == None:
                    self.fitting.modelParameterUnits = self.parameterUnits

                # Get the initial parameters
                if parameterNames == None:
                    parameterNames = self.getParameterNames()
                parameters0 = []
                for parameterName in parameterNames:
                    parameters0.append(float(
                        sample.descriptors[parameterName]))
                print("Initial solution: %s" % str(parameters0))
                print(" ")

                # Set bounds
                self.setBounds(sample)

                # Output object
                sampleFit = PKPDSampleFitBootstrap()
                sampleFit.sampleName = sample.sampleName
                sampleFit.parameters = np.zeros(
                    (self.Nbootstrap.get(), len(parameters0)), np.double)
                sampleFit.xB = []
                sampleFit.yB = []

                # Bootstrap samples
                idx = [k for k in range(0, len(firstX))]
                for n in range(0, self.Nbootstrap.get()):
                    ok = False
                    while not ok:
                        if self.sampleLength.get() > 0:
                            lenToUse = self.sampleLength.get()
                        else:
                            lenToUse = len(idx)
                        idxB = sorted(np.random.choice(idx, lenToUse))
                        xB = [np.asarray([firstX[i] for i in idxB])]
                        yB = [np.asarray([firstY[i] for i in idxB])]

                        print("Bootstrap sample %d" % n)
                        print("X= " + str(xB))
                        print("Y= " + str(yB))
                        self.clearXYLists()
                        self.setXYValues(xB, yB)
                        self.parameters = parameters0

                        optimizer2 = PKPDLSOptimizer(self, fitType)
                        optimizer2.verbose = 0
                        try:
                            optimizer2.optimize(ftol=1e-4, xtol=1e-4)
                            ok = True
                        except Exception as e:
                            print(e)
                            raise (e)
                            ok = False

                    # Evaluate the quality on the whole data set
                    self.clearXYLists()
                    self.setXYValues(x, y)
                    optimizer2.evaluateQuality()
                    print(optimizer2.optimum)
                    print("   R2 = %f R2Adj=%f AIC=%f AICc=%f BIC=%f"%(optimizer2.R2,optimizer2.R2adj,optimizer2.AIC,\
                                                                       optimizer2.AICc,optimizer2.BIC))

                    # Keep this result
                    sampleFit.parameters[n, :] = optimizer2.optimum
                    sampleFit.xB.append(str(xB[0]))
                    sampleFit.yB.append(str(yB[0]))
                    sampleFit.copyFromOptimizer(optimizer2)

                self.fitting.sampleFits.append(sampleFit)

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.getDescription()
        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))

    def createOutputStep(self):
        self._defineOutputs(outputPopulation=self.fitting)
        self._defineSourceRelation(self.inputODE.get(), self.fitting)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        msg = []
        msg.append("Number of bootstrap realizations: %d" %
                   self.Nbootstrap.get())
        msg.append("Confidence interval: %f" % self.confidenceInterval.get())
        return msg

    def _validate(self):
        return []
Exemplo n.º 17
0
    def runFit(self, objId, Nbootstrap, confidenceInterval):
        self.protODE = self.inputODE.get()
        if self.paramsSource.get() == self.PRM_PROTOCOL:
            self.experiment = self.readExperiment(
                self.protODE.outputExperiment.fnPKPD)
            self.fitting = self.readFitting(
                self.protODE.outputFitting.fnFitting)
        else:
            self.fitting = self.readFitting(self.inputFitting.get().fnFitting)
            self.experiment = self.readExperiment(
                self.inputFitting.get().fnExperiment)

        # Get the X and Y variable names
        self.varNameX = self.fitting.predictor.varName
        if type(self.fitting.predicted) == list:
            self.varNameY = [v.varName for v in self.fitting.predicted]
        else:
            self.varNameY = self.fitting.predicted.varName
        self.protODE.experiment = self.experiment
        self.protODE.varNameX = self.varNameX
        self.protODE.varNameY = self.varNameY

        # Create output object
        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.experiment.fnPKPD.get())
        self.fitting.predictor = self.experiment.variables[self.varNameX]
        if type(self.varNameY) == list:
            self.fitting.predicted = [
                self.experiment.variables[v] for v in self.varNameY
            ]
        else:
            self.fitting.predicted = self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        if self.protODE.fitType.get() == 0:
            fitType = "linear"
        elif self.protODE.fitType.get() == 1:
            fitType = "log"
        elif self.protODE.fitType.get() == 2:
            fitType = "relative"

        parameterNames = None
        for groupName, group in self.experiment.groups.items():
            self.printSection("Fitting " + groupName)
            self.protODE.clearGroupParameters()
            self.clearGroupParameters()

            for sampleName in group.sampleList:
                print("   Sample " + sampleName)
                sample = self.experiment.samples[sampleName]

                self.protODE.createDrugSource()
                self.protODE.setupModel()

                # Setup self model
                self.drugSource = self.protODE.drugSource
                self.drugSourceList = self.protODE.drugSourceList
                self.model = self.protODE.model
                self.modelList = self.protODE.modelList
                self.model.deltaT = self.deltaT.get()
                self.model.setXVar(self.varNameX)
                self.model.setYVar(self.varNameY)

                # Get the values to fit
                x, y = sample.getXYValues(self.varNameX, self.varNameY)
                print("X= " + str(x))
                print("Y= " + str(y))
                firstX = x[0]  # From [array(...)] to array(...)
                firstY = y[0]  # From [array(...)] to array(...)

                # Interpret the dose
                self.protODE.setVarNames(self.varNameX, self.varNameY)
                self.protODE.setModel(self.model)
                self.protODE.setTimeRange(sample)
                sample.interpretDose()

                self.drugSource.setDoses(sample.parsedDoseList, self.model.t0,
                                         self.model.tF)
                self.protODE.configureSource(self.drugSource)
                self.model.drugSource = self.drugSource

                # Prepare the model
                self.model.setSample(sample)
                self.calculateParameterUnits(sample)
                if self.fitting.modelParameterUnits == None:
                    self.fitting.modelParameterUnits = self.parameterUnits

                # Get the initial parameters
                if parameterNames == None:
                    parameterNames = self.getParameterNames()
                parameters0 = []
                for parameterName in parameterNames:
                    parameters0.append(float(
                        sample.descriptors[parameterName]))
                print("Initial solution: %s" % str(parameters0))
                print(" ")

                # Set bounds
                self.setBounds(sample)

                # Output object
                sampleFit = PKPDSampleFitBootstrap()
                sampleFit.sampleName = sample.sampleName
                sampleFit.parameters = np.zeros(
                    (self.Nbootstrap.get(), len(parameters0)), np.double)
                sampleFit.xB = []
                sampleFit.yB = []

                # Bootstrap samples
                idx = [k for k in range(0, len(firstX))]
                for n in range(0, self.Nbootstrap.get()):
                    ok = False
                    while not ok:
                        if self.sampleLength.get() > 0:
                            lenToUse = self.sampleLength.get()
                        else:
                            lenToUse = len(idx)
                        idxB = sorted(np.random.choice(idx, lenToUse))
                        xB = [np.asarray([firstX[i] for i in idxB])]
                        yB = [np.asarray([firstY[i] for i in idxB])]

                        print("Bootstrap sample %d" % n)
                        print("X= " + str(xB))
                        print("Y= " + str(yB))
                        self.clearXYLists()
                        self.setXYValues(xB, yB)
                        self.parameters = parameters0

                        optimizer2 = PKPDLSOptimizer(self, fitType)
                        optimizer2.verbose = 0
                        try:
                            optimizer2.optimize(ftol=1e-4, xtol=1e-4)
                            ok = True
                        except Exception as e:
                            print(e)
                            raise (e)
                            ok = False

                    # Evaluate the quality on the whole data set
                    self.clearXYLists()
                    self.setXYValues(x, y)
                    optimizer2.evaluateQuality()
                    print(optimizer2.optimum)
                    print("   R2 = %f R2Adj=%f AIC=%f AICc=%f BIC=%f"%(optimizer2.R2,optimizer2.R2adj,optimizer2.AIC,\
                                                                       optimizer2.AICc,optimizer2.BIC))

                    # Keep this result
                    sampleFit.parameters[n, :] = optimizer2.optimum
                    sampleFit.xB.append(str(xB[0]))
                    sampleFit.yB.append(str(yB[0]))
                    sampleFit.copyFromOptimizer(optimizer2)

                self.fitting.sampleFits.append(sampleFit)

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.getDescription()
        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))
Exemplo n.º 18
0
    def runFilter(self, objId, filterType, condition):
        self.population = self.readFitting(
            self.inputPopulation.get().fnFitting, cls="PKPDSampleFitBootstrap")
        self.printSection("Filtering population")

        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.population.fnExperiment)
        self.fitting.predictor = self.population.predictor
        self.fitting.predicted = self.population.predicted
        self.fitting.modelParameterUnits = self.population.modelParameterUnits
        self.fitting.modelParameters = self.population.modelParameters
        self.fitting.modelDescription = self.population.modelDescription

        newSampleFit = PKPDSampleFitBootstrap()
        newSampleFit.parameters = None
        filterType = self.filterType.get()
        for sampleFit in self.population.sampleFits:
            newSampleFit.sampleName = sampleFit.sampleName
            if newSampleFit.parameters == None:
                newSampleFit.parameters = np.empty(
                    (0, sampleFit.parameters.shape[1]))
                newSampleFit.xB = []
                newSampleFit.yB = []
                newSampleFit.R2 = []
                newSampleFit.R2adj = []
                newSampleFit.AIC = []
                newSampleFit.AICc = []
                newSampleFit.BIC = []

            if filterType <= 1:
                conditionToEvaluate = self.condition.get()
            else:
                tokens = self.condition.get().strip().split(' ')
                variable = tokens[0][2:-1]
                confidenceLevel = float(tokens[1])
                columnIdx = -1
                for j in range(len(self.population.modelParameters)):
                    if self.population.modelParameters[j] == variable:
                        columnIdx = j
                        break
                if columnIdx == -1:
                    raise Exception(
                        "Cannot find %s amongst the model variables" %
                        variable)
                values = sampleFit.parameters[:, columnIdx]
                alpha_2 = (100 - confidenceLevel) / 2
                limits = np.percentile(values, [alpha_2, 100 - alpha_2])
                conditionToEvaluate = "%s>=%f and %s<=%f" % (
                    tokens[0], limits[0], tokens[0], limits[1])
                print("Condition to evaluate: %s" % conditionToEvaluate)

            for n in range(0, len(sampleFit.R2)):
                evaluatedCondition = copy.copy(conditionToEvaluate)
                evaluatedCondition = evaluatedCondition.replace(
                    '$(R2)', "(%f)" % sampleFit.R2[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(R2adj)', "(%f)" % sampleFit.R2adj[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(AIC)', "(%f)" % sampleFit.AIC[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(AICc)', "(%f)" % sampleFit.AICc[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(BIC)', "(%f)" % sampleFit.BIC[n])

                for j in range(len(self.population.modelParameters)):
                    evaluatedCondition = evaluatedCondition.replace(
                        '$(%s)' % self.population.modelParameters[j],
                        "(%f)" % sampleFit.parameters[n, j])
                evaluatedCondition = eval(evaluatedCondition)
                if (filterType == 0 and not evaluatedCondition) or (
                        filterType >= 1 and evaluatedCondition):
                    newSampleFit.parameters = np.vstack(
                        [newSampleFit.parameters, sampleFit.parameters[n, :]])
                    newSampleFit.xB += sampleFit.xB
                    newSampleFit.yB += sampleFit.yB
                    newSampleFit.R2.append(sampleFit.R2[n])
                    newSampleFit.R2adj.append(sampleFit.R2adj[n])
                    newSampleFit.AIC.append(sampleFit.AIC[n])
                    newSampleFit.AICc.append(sampleFit.AICc[n])
                    newSampleFit.BIC.append(sampleFit.BIC[n])

        self.fitting.sampleFits.append(newSampleFit)
        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))
Exemplo n.º 19
0
class ProtPKPDFilterPopulation(ProtPKPD):
    """ Filter a population by some criterion\n
        Protocol created by http://www.kinestatpharma.com\n """
    _label = 'filter population'

    #--------------------------- DEFINE param functions --------------------------------------------

    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam(
            'inputPopulation',
            params.PointerParam,
            label="Population",
            important=True,
            pointerClass='PKPDFitting',
            help='It must be a fitting coming from a bootstrap sample')
        form.addParam(
            'filterType',
            params.EnumParam,
            choices=["Exclude", "Keep", "Keep confidence interval"],
            label="Filter mode",
            default=0,
            help='Exclude or keep samples meeting the following condition\n')
        form.addParam('condition', params.StringParam, label="Condition", default="$(AICc)>-10 or $(R2)<0.7",
                      help='Example: $(Cl)>0.25 and $(tlag)>0\n'\
                           'Example for the confidence interval: $(Cl) 95 (keep the central 95% of clearance).\n'\
                           'The variables R2, R2adj, AIC, AICc, and BIC can be used, \n'\
                           'e.g., $(AICc)>-10 selects those elements with suspicious fitting.\n'\
                           'Confidence intervals cannot be placed on the quality parameters (R2, R2adj, ...)')

    #--------------------------- INSERT steps functions --------------------------------------------
    def _insertAllSteps(self):
        self._insertFunctionStep('runFilter',
                                 self.inputPopulation.get().getObjId(),
                                 self.filterType.get(), self.condition.get())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def runFilter(self, objId, filterType, condition):
        self.population = self.readFitting(
            self.inputPopulation.get().fnFitting, cls="PKPDSampleFitBootstrap")
        self.printSection("Filtering population")

        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.population.fnExperiment)
        self.fitting.predictor = self.population.predictor
        self.fitting.predicted = self.population.predicted
        self.fitting.modelParameterUnits = self.population.modelParameterUnits
        self.fitting.modelParameters = self.population.modelParameters
        self.fitting.modelDescription = self.population.modelDescription

        newSampleFit = PKPDSampleFitBootstrap()
        newSampleFit.parameters = None
        filterType = self.filterType.get()
        for sampleFit in self.population.sampleFits:
            newSampleFit.sampleName = sampleFit.sampleName
            if newSampleFit.parameters == None:
                newSampleFit.parameters = np.empty(
                    (0, sampleFit.parameters.shape[1]))
                newSampleFit.xB = []
                newSampleFit.yB = []
                newSampleFit.R2 = []
                newSampleFit.R2adj = []
                newSampleFit.AIC = []
                newSampleFit.AICc = []
                newSampleFit.BIC = []

            if filterType <= 1:
                conditionToEvaluate = self.condition.get()
            else:
                tokens = self.condition.get().strip().split(' ')
                variable = tokens[0][2:-1]
                confidenceLevel = float(tokens[1])
                columnIdx = -1
                for j in range(len(self.population.modelParameters)):
                    if self.population.modelParameters[j] == variable:
                        columnIdx = j
                        break
                if columnIdx == -1:
                    raise Exception(
                        "Cannot find %s amongst the model variables" %
                        variable)
                values = sampleFit.parameters[:, columnIdx]
                alpha_2 = (100 - confidenceLevel) / 2
                limits = np.percentile(values, [alpha_2, 100 - alpha_2])
                conditionToEvaluate = "%s>=%f and %s<=%f" % (
                    tokens[0], limits[0], tokens[0], limits[1])
                print("Condition to evaluate: %s" % conditionToEvaluate)

            for n in range(0, len(sampleFit.R2)):
                evaluatedCondition = copy.copy(conditionToEvaluate)
                evaluatedCondition = evaluatedCondition.replace(
                    '$(R2)', "(%f)" % sampleFit.R2[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(R2adj)', "(%f)" % sampleFit.R2adj[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(AIC)', "(%f)" % sampleFit.AIC[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(AICc)', "(%f)" % sampleFit.AICc[n])
                evaluatedCondition = evaluatedCondition.replace(
                    '$(BIC)', "(%f)" % sampleFit.BIC[n])

                for j in range(len(self.population.modelParameters)):
                    evaluatedCondition = evaluatedCondition.replace(
                        '$(%s)' % self.population.modelParameters[j],
                        "(%f)" % sampleFit.parameters[n, j])
                evaluatedCondition = eval(evaluatedCondition)
                if (filterType == 0 and not evaluatedCondition) or (
                        filterType >= 1 and evaluatedCondition):
                    newSampleFit.parameters = np.vstack(
                        [newSampleFit.parameters, sampleFit.parameters[n, :]])
                    newSampleFit.xB += sampleFit.xB
                    newSampleFit.yB += sampleFit.yB
                    newSampleFit.R2.append(sampleFit.R2[n])
                    newSampleFit.R2adj.append(sampleFit.R2adj[n])
                    newSampleFit.AIC.append(sampleFit.AIC[n])
                    newSampleFit.AICc.append(sampleFit.AICc[n])
                    newSampleFit.BIC.append(sampleFit.BIC[n])

        self.fitting.sampleFits.append(newSampleFit)
        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))

    def createOutputStep(self):
        self._defineOutputs(outputPopulation=self.fitting)
        self._defineSourceRelation(self.inputPopulation, self.fitting)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        if self.filterType.get() == 0:
            filterType = "Exclude"
        elif self.filterType.get() == 1:
            filterType = "Keep"
        elif self.filterType.get() == 2:
            filterType = "Keep confidence interval"
        msg = ["Filter type: %s" % filterType]
        msg.append("Condition: %s" % self.condition.get())
        return msg

    def _validate(self):
        msg = []
        if not self.inputPopulation.get().fnFitting.get().endswith(
                "bootstrapPopulation.pkpd"):
            msg.append("Population must be a bootstrap sample")
        return msg
Exemplo n.º 20
0
class ProtPKPDODERefine(ProtPKPDODEBase):
    """ Refinement of an ODE protocol. The parameters are reestimated with a finer sampling rate.
    """

    _label = 'ODE refinement'

    #--------------------------- DEFINE param functions --------------------------------------------
    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam('inputODE', params.PointerParam, label="Input ODE model",
                      pointerClass='ProtPKPDMonoCompartment, ProtPKPDMonoCompartmentUrine, ProtPKPDTwoCompartments, '\
                                   'ProtPKPDTwoCompartmentsAutoinduction, ProtPKPDTwoCompartmentsClint, '\
                                   'ProtPKPDTwoCompartmentsClintCl, '\
                                   'ProtPKPDTwoCompartmentsClintMetabolite, ProtPKPDTwoCompartmentsUrine, '\
                                   'ProtPKPDODERefine',
                      help='Select a run of an ODE model')
        form.addParam('deltaT', params.FloatParam, default=0.5, label='Step (min)', expertLevel=LEVEL_ADVANCED)
        form.addParam('fitType', params.EnumParam, choices=["Linear","Logarithmic","Relative","Same as previous protocol"], label="Fit mode", default=3,
                      help='Linear: sum (Cobserved-Cpredicted)^2\nLogarithmic: sum(log10(Cobserved)-log10(Cpredicted))^2\n'\
                           "Relative: sum ((Cobserved-Cpredicted)/Cobserved)^2")
        form.addParam('bounds', params.StringParam, label="Parameter bounds", default="",
                      help="If empty, same bounds as for the previous protocol")

    #--------------------------- INSERT steps functions --------------------------------------------
    def _insertAllSteps(self):
        self._insertFunctionStep('runFit',self.inputODE.get().getObjId(), self.deltaT.get())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def parseBounds(self, boundsString):
        if boundsString!="" and boundsString!=None:
            tokens=boundsString.split(';')
            if len(tokens)!=self.getNumberOfParameters():
                raise Exception("The number of bound intervals does not match the number of parameters")
            self.boundsList=[]
            for token in tokens:
                values = token.strip().split(',')
                self.boundsList.append((float(values[0][1:]),float(values[1][:-1])))

    def setBounds(self,sample):
        self.parseBounds(self.protODE.bounds.get() if self.bounds.get()=="" else self.bounds.get())
        self.setBoundsFromBoundsList()

    def setBoundsFromBoundsList(self):
        Nbounds = len(self.boundsList)
        Nsource = self.drugSource.getNumberOfParameters()
        Nmodel = self.model.getNumberOfParameters()
        if Nbounds!=Nsource+Nmodel:
            raise "The number of parameters (%d) and bounds (%d) are different"%(Nsource+Nmodel,Nbounds)
        self.boundsSource = self.boundsList[0:Nsource]
        self.boundsPK = self.boundsList[Nsource:]
        self.model.bounds = self.boundsPK

    def getBounds(self):
        return self.boundsList

    def createModel(self):
        return self.inputODE.get().createModel()

    def setTimeRange(self, sample):
        self.inputODE.get().setTimeRange(sample)

    def setVarNames(self,varNameX,varNameY):
        ProtPKPDODEBase.setVarNames(self,varNameX,varNameY)
        self.inputODE.get().setVarNames(varNameX,varNameY)

    def setModel(self,model):
        ProtPKPDODEBase.setModel(self,model)
        self.inputODE.get().setModel(model)

    def setupModel(self):
        ProtPKPDODEBase.setupModel(self)
        self.inputODE.get().setModel(self.model)

    def clearGroupParameters(self):
        ProtPKPDODEBase.clearGroupParameters(self)
        self.inputODE.get().clearGroupParameters()

    def getConfidenceInterval(self):
        return self.inputODE.get().getConfidenceInterval()

    def runFit(self, objId, deltaT):
        self.protODE = self.inputODE.get()
        self.experiment = self.readExperiment(self.protODE.outputExperiment.fnPKPD)
        self.fitting = self.readFitting(self.protODE.outputFitting.fnFitting)

        # Get the X and Y variable names
        self.varNameX = self.fitting.predictor.varName
        if type(self.fitting.predicted)==list:
            self.varNameY = [v.varName for v in self.fitting.predicted]
        else:
            self.varNameY = self.fitting.predicted.varName
        self.protODE.experiment = self.experiment
        self.protODE.setVarNames(self.varNameX, self.varNameY)

        # Create output object
        self.fitting = PKPDFitting()
        self.fitting.fnExperiment.set(self.experiment.fnPKPD.get())
        self.fitting.predictor=self.experiment.variables[self.varNameX]
        self.fitting.predicted=self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        fitTypeN = self.protODE.fitType.get() if self.fitType.get()==3 else self.fitType.get()
        if fitTypeN==0:
            fitType = "linear"
        elif fitTypeN==1:
            fitType = "log"
        elif fitTypeN==2:
            fitType = "relative"

        parameterNames = None
        for groupName, group in self.experiment.groups.items():
            self.printSection("Fitting "+groupName)
            self.protODE.clearGroupParameters()
            self.clearGroupParameters()

            for sampleName in group.sampleList:
                print("   Sample "+sampleName)
                sample = self.experiment.samples[sampleName]

                self.protODE.createDrugSource()
                self.protODE.setupModel()

                # Setup self model
                self.drugSource = self.protODE.drugSource
                self.drugSourceList = self.protODE.drugSourceList
                self.model = self.protODE.model
                self.modelList = self.protODE.modelList
                self.model.deltaT = self.deltaT.get()
                self.model.setXVar(self.varNameX)
                self.model.setYVar(self.varNameY)

                # Get the values to fit
                x, y = sample.getXYValues(self.varNameX,self.varNameY)
                print("X= "+str(x))
                print("Y= "+str(y))

                # Interpret the dose
                self.protODE.varNameX = self.varNameX
                self.protODE.varNameY = self.varNameY
                self.protODE.model = self.model
                self.protODE.setTimeRange(sample)
                sample.interpretDose()

                self.drugSource.setDoses(sample.parsedDoseList, self.model.t0, self.model.tF)
                self.protODE.configureSource(self.drugSource)
                self.model.drugSource = self.drugSource

                # Prepare the model
                self.model.setSample(sample)
                self.calculateParameterUnits(sample)
                if self.fitting.modelParameterUnits==None:
                    self.fitting.modelParameterUnits = self.parameterUnits

                # Get the initial parameters
                if parameterNames==None:
                    parameterNames = self.getParameterNames()
                parameters0 = []
                for parameterName in parameterNames:
                    parameters0.append(float(sample.descriptors[parameterName]))
                print("Initial solution: %s"%str(parameters0))
                print(" ")

                # Set bounds
                self.setBounds(sample)
                self.setXYValues(x, y)
                self.parameters = parameters0

            self.printSetup()
            self.x = self.mergeLists(self.XList)
            self.y = self.mergeLists(self.YList)

            optimizer2 = PKPDLSOptimizer(self,fitType)
            optimizer2.optimize()
            optimizer2.setConfidenceInterval(self.protODE.getConfidenceInterval())
            self.setParameters(optimizer2.optimum)

            n=0
            for sampleName in group.sampleList:
                sample = self.experiment.samples[sampleName]

                # Keep this result
                sampleFit = PKPDSampleFit()
                sampleFit.sampleName = sample.sampleName
                sampleFit.x = x
                sampleFit.y = y
                sampleFit.yp = self.yPredicted
                sampleFit.yl = self.yPredictedLower
                sampleFit.yu = self.yPredictedUpper
                sampleFit.parameters = self.parameters
                sampleFit.modelEquation = self.getEquation()
                sampleFit.copyFromOptimizer(optimizer2)
                self.fitting.sampleFits.append(sampleFit)

                # Add the parameters to the sample and experiment
                for varName, varUnits, description, varValue in izip(self.getParameterNames(), self.parameterUnits, self.getParameterDescriptions(), self.parameters):
                    self.experiment.addParameterToSample(sampleName, varName, varUnits, description, varValue, rewrite=True)

                n+=1

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.getDescription()
        self.fitting.write(self._getPath("fitting.pkpd"))
        self.experiment.write(self._getPath("experiment.pkpd"))

    def createOutputStep(self):
        self._defineOutputs(outputFitting=self.fitting)
        self._defineOutputs(outputExperiment=self.experiment)
        self._defineSourceRelation(self.inputODE.get(), self.fitting)
        self._defineSourceRelation(self.inputODE.get(), self.experiment)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        msg = []
        msg.append("New sampling rate: %f"%self.deltaT.get())
        return msg

    def _validate(self):
        return []
Exemplo n.º 21
0
class ProtPKPDFitBootstrap(ProtPKPDFitBase):
    """ Bootstrap estimate of generic fit models.\n
        Protocol created by http://www.kinestatpharma.com\n"""
    _label = 'fit bootstrap'

    #--------------------------- DEFINE param functions --------------------------------------------
    def _defineParams(self, form):
        form.addSection('Input')
        form.addParam(
            'inputFit',
            params.PointerParam,
            label="Input Fit model",
            pointerClass='ProtPKPDGenericFit, ProtPKPDDissolutionFit',
            help='Select a run of a fitted model')
        form.addParam('Nbootstrap',
                      params.IntParam,
                      label="Bootstrap samples",
                      default=200,
                      expertLevel=LEVEL_ADVANCED,
                      help='Number of bootstrap realizations for each sample')
        form.addParam('confidenceInterval',
                      params.FloatParam,
                      label="Confidence interval",
                      default=95,
                      expertLevel=LEVEL_ADVANCED,
                      help='Confidence interval for the fitted parameters')

    #--------------------------- INSERT steps functions --------------------------------------------
    def _insertAllSteps(self):
        self._insertFunctionStep('runFit',
                                 self.inputFit.get().getObjId(),
                                 self.Nbootstrap.get(),
                                 self.confidenceInterval.get())
        self._insertFunctionStep('createOutputStep')

    #--------------------------- STEPS functions --------------------------------------------
    def runFit(self, objId, Nbootstrap, confidenceInterval):
        self.protFit = self.inputFit.get()
        self.experiment = self.readExperiment(
            self.protFit.outputExperiment.fnPKPD)
        self.fitting = self.readFitting(self.protFit.outputFitting.fnFitting)

        # Get the X and Y variable names
        self.varNameX = self.fitting.predictor.varName
        self.varNameY = self.fitting.predicted.varName
        self.protFit.experiment = self.experiment
        self.protFit.varNameX = self.varNameX
        self.protFit.varNameY = self.varNameY

        # Setup model
        self.printSection("Model setup")
        self.protFit.model = self.protFit.createModel()
        self.protFit.model.setExperiment(self.experiment)
        self.protFit.model.setXVar(self.varNameX)
        self.protFit.model.setYVar(self.varNameY)
        self.protFit.setupFromFormParameters()
        self.protFit.setupModel()
        self.protFit.model.setBounds(self.protFit.bounds.get())
        self.protFit.model.printSetup()
        self.model = self.protFit.model

        # Setup self as model
        self.boundsList = self.model.bounds

        # Create output object
        self.fitting = PKPDFitting("PKPDSampleFitBootstrap")
        self.fitting.fnExperiment.set(self.experiment.fnPKPD.get())
        self.fitting.predictor = self.experiment.variables[self.varNameX]
        self.fitting.predicted = self.experiment.variables[self.varNameY]
        self.fitting.modelParameterUnits = None

        # Actual fitting
        if self.protFit.fitType.get() == 0:
            fitType = "linear"
        elif self.protFit.fitType.get() == 1:
            fitType = "log"
        elif self.protFit.fitType.get() == 2:
            fitType = "relative"

        parameterNames = self.model.getParameterNames()
        for sampleName, sample in self.experiment.samples.items():
            self.printSection("Fitting " + sampleName)

            x, y = sample.getXYValues(self.varNameX, self.varNameY)
            print("X= " + str(x))
            print("Y= " + str(y))
            print(" ")

            self.model.setXYValues(x, y)
            self.prepareForSampleAnalysis(sampleName)
            self.model.calculateParameterUnits(sample)
            if self.fitting.modelParameterUnits == None:
                self.fitting.modelParameterUnits = self.model.parameterUnits
            self.model.prepare()
            if self.model.bounds == None:
                continue
            print(" ")

            # Get the initial parameters
            parameters0 = []
            for parameterName in parameterNames:
                parameters0.append(float(sample.descriptors[parameterName]))
            print("Initial solution: %s" % str(parameters0))
            print(" ")

            # Output object
            sampleFit = PKPDSampleFitBootstrap()
            sampleFit.sampleName = sample.sampleName
            sampleFit.parameters = np.zeros(
                (self.Nbootstrap.get(), len(parameters0)), np.double)
            sampleFit.xB = []
            sampleFit.yB = []

            # Bootstrap samples
            firstX = x[0]  # From [array(...)] to array(...)
            firstY = y[0]  # From [array(...)] to array(...)
            idx = [k for k in range(0, len(firstX))]
            for n in range(0, self.Nbootstrap.get()):
                ok = False
                while not ok:
                    lenToUse = len(idx)
                    idxB = sorted(np.random.choice(idx, lenToUse))
                    xB = [np.asarray([firstX[i] for i in idxB])]
                    yB = [np.asarray([firstY[i] for i in idxB])]

                    print("Bootstrap sample %d" % n)
                    print("X= " + str(xB))
                    print("Y= " + str(yB))
                    self.model.setXYValues(xB, yB)
                    self.model.parameters = parameters0

                    optimizer2 = PKPDLSOptimizer(self.model, fitType)
                    optimizer2.verbose = 0
                    try:
                        optimizer2.optimize()
                        ok = True
                    except Exception as e:
                        print(e)
                        raise (e)
                        ok = False

                # Evaluate the quality on the whole data set
                self.model.setXYValues(x, y)
                optimizer2.evaluateQuality()
                print(optimizer2.optimum)
                print("   R2 = %f R2Adj=%f AIC=%f AICc=%f BIC=%f"%(optimizer2.R2,optimizer2.R2adj,optimizer2.AIC,\
                                                                   optimizer2.AICc,optimizer2.BIC))

                # Keep this result
                sampleFit.parameters[n, :] = optimizer2.optimum
                sampleFit.xB.append(str(xB[0]))
                sampleFit.yB.append(str(yB[0]))
                sampleFit.copyFromOptimizer(optimizer2)

            self.fitting.sampleFits.append(sampleFit)

        self.fitting.modelParameters = self.getParameterNames()
        self.fitting.modelDescription = self.model.getDescription()
        self.fitting.write(self._getPath("bootstrapPopulation.pkpd"))

    def createOutputStep(self):
        self._defineOutputs(outputPopulation=self.fitting)
        self._defineSourceRelation(self.inputFit.get(), self.fitting)

    #--------------------------- INFO functions --------------------------------------------
    def _summary(self):
        msg = []
        msg.append("Number of bootstrap realizations: %d" %
                   self.Nbootstrap.get())
        msg.append("Confidence interval: %f" % self.confidenceInterval.get())
        return msg

    def _validate(self):
        return []