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()
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): 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)
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 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 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
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
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)
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)
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())
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"))
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
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 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"))
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
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 []
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 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"))
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
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 []
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 []