def runAdjust(self, targetWeight): scaleModel = PKPDAllometricScale() scaleModel.load(self.inputAllometric.get().fnScale.get()) self.population = self.readFitting(self.inputPopulation.get().fnFitting,cls="PKPDSampleFitBootstrap") self.experiment = PKPDExperiment() self.experiment.load(self.population.fnExperiment.get()) for sampleFit in self.population.sampleFits: sample = self.experiment.samples[sampleFit.sampleName] sampleWeight = float(sample.getDescriptorValue(scaleModel.predictor)) sample.setDescriptorValue(scaleModel.predictor,targetWeight) for varName, varUnits in scaleModel.averaged_vars: if varName in self.population.modelParameters: idx = self.population.modelParameters.index(varName) targetValue = scaleModel.models[varName][0] sampleFit.parameters[0][idx] = targetValue for varName, varUnits in scaleModel.scaled_vars: if varName in self.population.modelParameters: idx = self.population.modelParameters.index(varName) k = scaleModel.models[varName][0] a = scaleModel.models[varName][1] targetValue = k*math.pow(targetWeight,a) currentValue = k*math.pow(sampleWeight,a) for j in range(sampleFit.parameters.shape[0]): sampleFit.parameters[j][idx] *= targetValue/currentValue self.experiment.write(self._getPath("experiment.pkpd")) self.population.fnExperiment.set(self._getPath("experiment.pkpd")) self.population.write(self._getPath("bootstrapPopulation.pkpd"))
def solve(self, objId1): self.experiment = self.readExperiment(self.inputExperiment.get().fnPKPD) # Create output object self.outputExperiment = None timeRange = self.experiment.getRange(self.timeVar.get()) for sampleName, sample in self.experiment.samples.items(): # Get t, A t=np.asarray(sample.getValues(self.timeVar.get()),dtype=np.float64) A=np.asarray(sample.getValues(self.amountVar.get()),dtype=np.float64) if t[0]>0: t=np.insert(t,0,0) # Add (0,0) to the profile A=np.insert(A,0,0) t, A = uniqueFloatValues(t, A) if self.resampleT.get()>0: B = InterpolatedUnivariateSpline(t, A, k=1) t = np.arange(np.min(t),np.max(t)+self.resampleT.get(),self.resampleT.get()) A = B(t) # Find C and Cp C, Cp = self.calculateConcentrations2(t,A) if self.outputExperiment is None: self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Cvar = PKPDVariable() Cvar.varName = "C" Cvar.varType = PKPDVariable.TYPE_NUMERIC Cvar.role = PKPDVariable.ROLE_MEASUREMENT Lunits = createUnit("L") Cvar.units = createUnit(divideUnits(self.experiment.getVarUnits(self.amountVar.get()),Lunits.unit)) Cvar.comment = "Concentration central compartment" Cpvar = PKPDVariable() Cpvar.varName = "Cp" Cpvar.varType = PKPDVariable.TYPE_NUMERIC Cpvar.role = PKPDVariable.ROLE_MEASUREMENT Cpvar.units = createUnit(divideUnits(self.experiment.getVarUnits(self.amountVar.get()),Lunits.unit)) Cpvar.comment = "Concentration peripheral compartment" self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Cvar.varName] = Cvar self.outputExperiment.variables[Cpvar.varName] = Cpvar self.outputExperiment.general["title"]="Inverse Loo-Riegelman" self.outputExperiment.general["comment"]="" self.addSample(sampleName,t,C,Cp) self.outputExperiment.write(self._getPath("experiment.pkpd"))
def prepareForAnalysis(self): if self.resampleT.get() > 0: self.experimentSimulated = PKPDExperiment() self.experimentSimulated.variables[ self.fitting.predicted.varName] = self.fitting.predicted self.experimentSimulated.variables[ self.fitting.predictor.varName] = self.fitting.predictor self.experimentSimulated.general[ "title"] = "Simulated response from dissolution profiles" self.experimentSimulated.general[ "comment"] = "Simulated response from dissolution profiles"
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 setupUnderlyingProtocol(self, prot): prot.getXYvars() prot.experiment = PKPDExperiment() prot.experiment.load(prot.outputExperiment.fnPKPD.get()) prot.clearGroupParameters() prot.createDrugSource() prot.setupModel() return prot.experiment
def createOutputStep(self, objId): fnFile = os.path.basename(self.inputFile.get()) copyFile(self.inputFile.get(), self._getPath(fnFile)) tables = self.readTables(self._getPath(fnFile)) for tableName, sampleNames, allT, allMeasurements in tables: self.experiment = PKPDExperiment() self.experiment.general["title"] = self.title.get() self.experiment.general["comment"] = self.comment.get() # Add variables if not self.addVar(self.experiment, self.tVar.get()): raise Exception("Cannot process time variable") if not self.addVar(self.experiment, self.xVar.get()): raise Exception("Cannot process measurement variable") tvarName = self.tVar.get().split(';')[0].replace(';', '') xvarName = self.xVar.get().split(';')[0].replace(';', '') # Create the samples for sampleName in sampleNames: self.experiment.samples[sampleName] = PKPDSample() self.experiment.samples[sampleName].parseTokens( [sampleName], self.experiment.variables, self.experiment.doses, self.experiment.groups) self.experiment.samples[sampleName].addMeasurementPattern( [sampleName, tvarName, xvarName]) samplePtr = self.experiment.samples[sampleName] exec("samplePtr.measurement_%s=%s" % (tvarName, allT)) # Fill the samples for i in range(len(allT)): for j in range(len(sampleNames)): samplePtr = self.experiment.samples[sampleNames[j]] exec('samplePtr.measurement_%s.append("%s")' % (xvarName, allMeasurements[i][j])) self.experiment.write( self._getPath("experiment%s.pkpd" % tableName)) self.experiment._printToStream(sys.stdout) self._defineOutputs( **{"outputExperiment%s" % tableName: self.experiment})
def createOutputExperiment(self): tvitroVar = PKPDVariable() tvitroVar.varName = "tvitro" tvitroVar.varType = PKPDVariable.TYPE_NUMERIC tvitroVar.role = PKPDVariable.ROLE_TIME tvitroVar.units = createUnit(self.experimentInVivo.getTimeUnits().unit) tvitroVar.comment = "tvitro" AdissolVar = PKPDVariable() AdissolVar.varName = "Adissol" AdissolVar.varType = PKPDVariable.TYPE_NUMERIC AdissolVar.role = PKPDVariable.ROLE_MEASUREMENT AdissolVar.units = createUnit(PKPDUnit.UNIT_NONE) AdissolVar.comment = "Amount disolved in vitro" self.outputExperiment = PKPDExperiment() self.outputExperiment.variables[tvitroVar.varName] = tvitroVar self.outputExperiment.variables[AdissolVar.varName] = AdissolVar self.outputExperiment.general["title"] = "In-vitro target simulation" self.outputExperiment.general["comment"] = ""
def getData(self, fnPKPD, XvarName, YvarName): experiment = PKPDExperiment() experiment.load(fnPKPD) self.timeVarName = XvarName self.CVarName = YvarName xmin = 1e38 xmax = -1e38 for sampleName, sample in experiment.samples.items(): xValues, _ = self.getPlotValues(sample) xmin = min(xmin, min(xValues)) xmax = max(xmax, max(xValues)) dataDict = {} # key will be time values xrange = np.arange(xmin, xmax, (xmax - xmin) / 300.0) for sampleName, sample in experiment.samples.items(): xValues, yValues = self.getPlotValues(sample) xValuesUnique, yValuesUnique = uniqueFloatValues(xValues, yValues) B = InterpolatedUnivariateSpline(xValuesUnique, yValuesUnique, k=1) yrange = B(xrange) for x, y in izip(xrange, yrange): if x in dataDict: dataDict[x].append(y) else: dataDict[x] = [y] sortedTime = sorted(dataDict.keys()) if self.prot.showSummary.get(): # We will store five values (min, 25%, 50%, 75%, max) # for each of the time entries computed percentileList = [0, 25, 50, 75, 100] Y = np.zeros((len(sortedTime), 5)) for i, t in enumerate(sortedTime): Y[i, :] = np.percentile(dataDict[t], percentileList) else: Y = np.zeros((len(sortedTime), len(experiment.samples))) for i, t in enumerate(sortedTime): for j, C in enumerate(dataDict[t]): Y[i, j] = C return sortedTime, Y
def readExperiment(self, fnIn, show=True, fullRead=True): experiment = PKPDExperiment() experiment.load(fnIn, fullRead=fullRead) if show: self.printSection("Reading %s" % fnIn) experiment._printToStream(sys.stdout) return experiment
def createOutputStep(self): fnTmp = self._getExtraPath("aux.pkpd") fh = open(fnTmp, "w") fh.write("[EXPERIMENT] ===========================\n") fh.write("title=%s\n" % self.newTitle.get()) fh.write("comment=%s\n" % self.newComment.get()) fh.write("\n") fh.write("[VARIABLES] ============================\n") fh.write("%s\n" % self.newVariables.get()) fh.write("\n") fh.write("[VIAS] ================================\n") fh.write("%s\n" % self.newVias.get()) fh.write("\n") fh.write("[DOSES] ================================\n") fh.write("%s\n" % self.newDoses.get()) fh.write("\n") fh.write("[GROUPS] ================================\n") fh.write("%s\n" % self.newGroups.get()) fh.write("\n") fh.write("[SAMPLES] ================================\n") fh.write("%s\n" % self.newSamples.get()) fh.write("\n") fh.write("[MEASUREMENTS] ===========================\n") fh.write("%s\n" % self.newMeasurements.get()) fh.write("\n") fh.close() experiment = PKPDExperiment() experiment.load(fnTmp, verifyIntegrity=False) self.writeExperiment(experiment, self._getPath("experiment.pkpd")) self._defineOutputs(outputExperiment=experiment)
def createOutputStep(self): if self.splitOrGather.get() == 0: experiment = self.readExperiment(self.inputExperiment.get().fnPKPD) listOfSamples = [] g = 1 for sampleName in experiment.samples: listOfSamples.append(sampleName) if len(listOfSamples) == self.groupSize.get(): self.createSubGroup(g, experiment, listOfSamples) listOfSamples = [] g += 1 if len(listOfSamples) != 0: self.createSubGroup(g, experiment, listOfSamples) else: newExperiment = PKPDExperiment() for ptrExperiment in self.inputExperiments: newExperiment.gather( self.readExperiment(ptrExperiment.get().fnPKPD)) self.writeExperiment(newExperiment, self._getPath("experiment.pkpd")) self._defineOutputs(outputExperiment=newExperiment) for ptrExperiment in self.inputExperiments: self._defineSourceRelation(ptrExperiment, newExperiment)
def _validate(self): import re errors = [] if self.prefix1.get() == self.prefix2.get(): experiment1 = PKPDExperiment() experiment1.load(self.inputExperiment1.get().fnPKPD) experiment2 = PKPDExperiment() experiment2.load(self.inputExperiment2.get().fnPKPD) # Check if there are repeated doses for doseName1 in experiment1.doses: if doseName1 in experiment2.doses: errors.append("Dose %s is repeated in both experiments" % doseName1) # Check if there are repeated samples for sampleName1 in experiment1.samples: if sampleName1 in experiment2.samples: errors.append("Sample %s is repeated in both experiments" % sampleName1) if len(errors) > 0: errors.append("Use the prefixes in the Advanced options") return errors
def calculateAllLevy(self): L1 = [] for ptrExperiment in self.inputLevyplots: experiment = PKPDExperiment() experiment.load(ptrExperiment.get().fnPKPD.get()) x, y = experiment.getXYMeanValues("tvivo", "tvitro") L1.append((x, y)) tvivo, tvitro = computeXYmean(L1, common=True) x, y = twoWayUniqueFloatValues(tvivo, tvitro) Bt = InterpolatedUnivariateSpline(x, y, k=1) vtvitroReinterpolated = np.zeros(len(tvivo)) for i in range(len(tvivo)): tvivoi = tvivo[i] vtvitroReinterpolated[i] = Bt(tvivoi) tvitroReinterpolatedVar = experiment.variables["tvitro"] tvivoVar = experiment.variables["tvivo"] self.outputExperimentSingle = PKPDExperiment() self.outputExperimentSingle.variables[ tvitroReinterpolatedVar.varName] = tvitroReinterpolatedVar self.outputExperimentSingle.variables[tvivoVar.varName] = tvivoVar self.outputExperimentSingle.general["title"] = "Levy plot" self.outputExperimentSingle.general["comment"] = "tvitro vs tvivo" sampleName = "jointLevyPlot" newSampleSingle = PKPDSample() newSampleSingle.sampleName = sampleName newSampleSingle.variableDictPtr = self.outputExperimentSingle.variables newSampleSingle.descriptors = {} newSampleSingle.addMeasurementColumn("tvitro", vtvitroReinterpolated) newSampleSingle.addMeasurementColumn("tvivo", tvivo) self.outputExperimentSingle.samples[sampleName] = newSampleSingle self.outputExperimentSingle.addLabelToSample(sampleName, "from", "individual---vesel", "meanVivo---meanVitro") self.outputExperimentSingle.write(self._getPath("experiment.pkpd"))
def runDrop(self, objId, varsToDrop): import copy experiment = self.readExperiment(self.inputExperiment.get().fnPKPD) self.printSection("Dropping variables") varsToDrop = [] for varName in self.varsToDrop.get().split(','): varsToDrop.append(varName.strip()) filteredExperiment = PKPDExperiment() filteredExperiment.general = copy.copy(experiment.general) filteredExperiment.variables = {} for varName, variable in experiment.variables.items(): if not varName in varsToDrop: filteredExperiment.variables[varName] = copy.copy(variable) filteredExperiment.samples = {} filteredExperiment.doses = copy.copy(experiment.doses) for sampleKey, sample in experiment.samples.items(): candidateSample = PKPDSample() candidateSample.variableDictPtr = filteredExperiment.variables candidateSample.doseDictPtr = filteredExperiment.doses candidateSample.sampleName = copy.copy(sample.sampleName) candidateSample.doseList = copy.copy(sample.doseList) candidateSample.descriptors = copy.copy(sample.descriptors) candidateSample.measurementPattern = [] for varName in sample.measurementPattern: if not varName in varsToDrop: candidateSample.measurementPattern.append(varName) exec( "candidateSample.measurement_%s = copy.copy(sample.measurement_%s)" % (varName, varName)) filteredExperiment.samples[ candidateSample.varName] = candidateSample self.writeExperiment(filteredExperiment, self._getPath("experiment.pkpd")) self.experiment = filteredExperiment
def deconvolve(self, objId1): self.experiment = self.readExperiment( self.inputExperiment.get().fnPKPD) # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Avar = PKPDVariable() Avar.varName = "A" Avar.varType = PKPDVariable.TYPE_NUMERIC Avar.role = PKPDVariable.ROLE_MEASUREMENT Avar.units = createUnit("none") self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Avar.varName] = Avar self.outputExperiment.general[ "title"] = "Deconvolution of the amount released" self.outputExperiment.general[ "comment"] = "Amount released at any time t" # Get the input sample from another experiment if necessary sampleFrom = None if self.externalIV.get() == self.ANOTHER_INPUT: anotherExperiment = self.readExperiment( self.externalIVODE.get().outputExperiment.fnPKPD) for _, sampleFrom in anotherExperiment.samples.items( ): # Take the first sample from the reference break timeRange = self.experiment.getRange(self.timeVar.get()) for sampleName, sample in self.experiment.samples.items(): # Get t, Cp t = np.asarray(sample.getValues(self.timeVar.get()), dtype=np.float64) Cp = np.asarray(sample.getValues(self.concVar.get()), dtype=np.float64) Cp = np.clip(Cp, 0.0, None) t = np.insert(t, 0, 0) # Add (0,0) to the profile Cp = np.insert(Cp, 0, 0) t, Cp = uniqueFloatValues(t, Cp) if self.resampleT.get() > 0: B = InterpolatedUnivariateSpline(t, Cp, k=1) t = np.arange(np.min(t), np.max(t) + self.resampleT.get(), self.resampleT.get()) Cp = B(t) # Calculate AUC0t AUC0t = calculateAUC0t(t, Cp) AUC0inf = float(AUC0t[-1]) # Calculate peripheral if self.externalIV.get() == self.SAME_INPUT: sampleFrom = sample Cl = float(sampleFrom.descriptors['Cl']) V = float(sampleFrom.descriptors['V']) Clp = float(sampleFrom.descriptors['Clp']) Vp = float(sampleFrom.descriptors['Vp']) k12 = Clp / V k21 = Clp / Vp Cperipheral = self.calculateCperipheral(t, Cp, k12, k21) # Deconvolve k10 = Cl / V A = (Cp + Cperipheral + k10 * AUC0t) / k10 if self.normalize.get(): A *= 100 / AUC0inf if self.saturate.get(): A = np.clip(A, None, 100.0) A = np.clip(A, 0, None) if self.smooth: if t[0] > 0: t = np.insert(t, 0, 0) A = np.insert(A, 0, 0) if self.saturate.get() and self.normalize.get(): A = np.clip(A, None, 100.0) A = np.clip(smoothPchip(t, A), 0, None) if self.considerBioaval.get() == self.BIOAVAIL_DIV: A /= sample.getBioavailability() elif self.considerBioaval.get() == self.BIOAVAIL_MULT: A *= sample.getBioavailability() self.addSample(sampleName, t, A) self.outputExperiment.write(self._getPath("experiment.pkpd"))
def runFilter(self, objId, filterType, condition): import copy experiment = self.readExperiment(self.inputExperiment.get().fnPKPD) self.printSection("Filtering") if self.filterType.get() == 0: filterType = "exclude" elif self.filterType.get() == 1: filterType = "keep" elif self.filterType.get() == 2: filterType = "rmNA" elif self.filterType.get() == 3: filterType = "rmLL" elif self.filterType.get() == 4: filterType = "subsLL" elif self.filterType.get() == 5: filterType = "subsUL" filteredExperiment = PKPDExperiment() filteredExperiment.general = copy.copy(experiment.general) filteredExperiment.variables = copy.copy(experiment.variables) filteredExperiment.samples = {} filteredExperiment.doses = {} filteredExperiment.vias = {} usedDoses = [] for sampleKey, sample in experiment.samples.items(): candidateSample = PKPDSample() candidateSample.variableDictPtr = copy.copy(sample.variableDictPtr) candidateSample.doseDictPtr = copy.copy(sample.doseDictPtr) candidateSample.sampleName = copy.copy(sample.sampleName) candidateSample.doseList = copy.copy(sample.doseList) candidateSample.descriptors = copy.copy(sample.descriptors) candidateSample.measurementPattern = copy.copy( sample.measurementPattern) N = 0 # Number of initial measurements if len(sample.measurementPattern) > 0: aux = getattr(sample, "measurement_%s" % sample.measurementPattern[0]) N = len(aux) if N == 0: continue # Create empty output variables Nvar = len(sample.measurementPattern) convertToFloat = [] for i in range(0, Nvar): exec("candidateSample.measurement_%s = []" % sample.measurementPattern[i]) convertToFloat.append( sample.variableDictPtr[sample.measurementPattern[i]]. varType == PKPDVariable.TYPE_NUMERIC) for n in range(0, N): toAdd = [] okToAddTimePoint = True conditionPython = copy.copy(condition) for i in range(0, Nvar): ldict = {} exec( "aux=sample.measurement_%s[%d]" % (sample.measurementPattern[i], n), locals(), ldict) aux = ldict['aux'] if filterType == "rmNA": if aux == "NA" or aux == "None": okToAddTimePoint = False else: toAdd.append(aux) elif filterType == "rmLL": if aux == "LLOQ" or aux == "ULOQ": okToAddTimePoint = False else: toAdd.append(aux) elif filterType == "subsLL": okToAddTimePoint = True if aux == "LLOQ": toAdd.append(str(self.substitute.get())) else: toAdd.append(aux) elif filterType == "subsUL": okToAddTimePoint = True if aux == "ULOQ": toAdd.append(str(self.substitute.get())) else: toAdd.append(aux) else: # Keep or exclude toAdd.append(aux) varString = "$(%s)" % sample.measurementPattern[i] if varString in conditionPython: if aux == "NA": okToAddTimePoint = False else: if convertToFloat[i]: conditionPython = conditionPython.replace( varString, "%f" % float(aux)) else: conditionPython = conditionPython.replace( varString, "'%s'" % aux) if (filterType == "exclude" or filterType == "keep") and okToAddTimePoint: okToAddTimePoint = eval(conditionPython, {"__builtins__": None}, {}) if filterType == "exclude": okToAddTimePoint = not okToAddTimePoint if okToAddTimePoint: for i in range(0, Nvar): exec("candidateSample.measurement_%s.append('%s')" % (sample.measurementPattern[i], toAdd[i])) N = len( getattr(sample, "measurement_%s" % sample.measurementPattern[0] )) # Number of final measurements if N != 0: filteredExperiment.samples[ candidateSample.sampleName] = candidateSample for doseName in candidateSample.doseList: if not doseName in usedDoses: usedDoses.append(doseName) if len(usedDoses) > 0: for doseName in usedDoses: filteredExperiment.doses[doseName] = copy.copy( experiment.doses[doseName]) viaName = experiment.doses[doseName].via.viaName if not viaName in filteredExperiment.vias: filteredExperiment.vias[viaName] = copy.copy( experiment.vias[viaName]) self.writeExperiment(filteredExperiment, self._getPath("experiment.pkpd")) self.experiment = filteredExperiment
class ProtPKPDInhSimulate(ProtPKPD): """ Simulate inhalation PK\n See Hartung2020. Protocol created by http://www.kinestatpharma.com\n """ _label = 'simulate inhalation' #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam('ptrDeposition', params.PointerParam, pointerClass='PKDepositionParameters', label="Deposition") form.addParam( 'doseMultiplier', params.FloatParam, default=1.0, label='Dose multiplier', expertLevel=LEVEL_ADVANCED, help="Multiply the dose in the deposition file by this factor") form.addParam( 'substanceMultiplier', params.StringParam, default="1 1 1 1 1 1 1 1", label='Substance multiplier', expertLevel=LEVEL_ADVANCED, help= 'Multiply a substance related parameter by this factor. This is a vector with the order: \n' '1. Solubility (br) \n' '2. Solubility (alv) \n' '3. Dissolution rate (br) \n' '4. Dissolution rate (alv) \n' '5. Permeability (br) \n' '6. Permeability (alv) \n' '7. Partition coefficient (br) \n' '8. Partition coefficient (alv)') form.addParam( 'physiologyMultiplier', params.StringParam, default="1 1 1 1 1 1 1 1 1", label='Physiology multiplier', expertLevel=LEVEL_ADVANCED, help= 'Multiply a physiology related parameter by this factor. This is a vector with the order: \n' '1. Mucociliary clearance\n' '2. Fluid volume (br)\n' '3. Fluid volume (alv)\n' '4. Tissue volume (br)\n' '5. Tissue volume (alv)\n' '6. Surface area (br)\n' '7. Surface area (alv)\n' '8. Perfusion (br)\n' '9. Perfusion (alv)\n') form.addParam('ptrPK', params.PointerParam, pointerClass='PKPDExperiment', label="PK parameters") form.addParam( 'pkMultiplier', params.StringParam, default="1 1 1 1 1 1", label='PK multiplier', expertLevel=LEVEL_ADVANCED, help= 'Multiply a substance related parameter by this factor. This is a vector with the order: \n' '1. Systemic clearance (Cl)\n' '2. Systemic apparent volume (V)\n' '3. Flow between compartments (Q)\n' '4. Peripheral apparent volume (Vp)\n' '5. Absorption (k01)\n' '6. Oral bioavailability (F)\n') form.addParam('ciliarySpeedType', params.EnumParam, choices=['Exponential', 'Fit', 'Interpolated'], default=2, label='Ciliary speed', expertLevel=LEVEL_ADVANCED) form.addParam('simulationTime', params.FloatParam, label="Simulation time (min)", default=10 * 24 * 60) form.addParam('deltaT', params.FloatParam, label='Time step (min)', default=1, expertLevel=LEVEL_ADVANCED) form.addParam( 'diameters', params.StringParam, label='Diameters (um)', default="0.1,1.1,0.1; 1.2,9.2,0.2", help= 'Diameters to analyze. Syntax: start1, stop1, step1; start2, stop2, step2; ... They will be ' 'used as arguments of numpy.arange', expertLevel=LEVEL_ADVANCED) form.addParam('volMultiplier', params.FloatParam, label='Particle volume multiplier', default=1, expertLevel=LEVEL_ADVANCED) #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('runSimulation') self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def runSimulation(self): self.deposition = PKDepositionParameters() self.deposition.setFiles(self.ptrDeposition.get().fnSubstance.get(), self.ptrDeposition.get().fnLung.get(), self.ptrDeposition.get().fnDeposition.get()) self.deposition.doseMultiplier = self.doseMultiplier.get() self.deposition.read() substanceParams = PKSubstanceLungParameters() substanceParams.multiplier = [ float(x) for x in self.substanceMultiplier.get().split() ] substanceParams.read(self.ptrDeposition.get().fnSubstance.get()) lungParams = PKPhysiologyLungParameters() lungParams.multiplier = [ float(x) for x in self.physiologyMultiplier.get().split() ] lungParams.read(self.ptrDeposition.get().fnLung.get()) pkParams = PKPDExperiment() pkParams.load(self.ptrPK.get().fnPKPD) pkLungParams = PKLung() pkLungParams.prepare( substanceParams, lungParams, pkParams, [float(x) for x in self.pkMultiplier.get().split()], self.ciliarySpeedType.get()) # diameters = np.concatenate((np.arange(0.1,1.1,0.1),np.arange(1.2,9.2,0.2))) # [um] evalStr = "np.concatenate((" + ",".join([ "np.arange(" + x.strip() + ")" for x in self.diameters.get().split(";") ]) + "))" diameters = eval(evalStr, {'np': np}) Sbnd = self.volMultiplier.get() * diam2vol(diameters) tt = np.arange(0, self.simulationTime.get() + self.deltaT.get(), self.deltaT.get()) sol = saturable_2D_upwind_IE(lungParams, pkLungParams, self.deposition, tt, Sbnd) # Postprocessing depositionData = self.deposition.getData() alvDose = np.sum(depositionData['alveolar']) bronchDose = np.sum(depositionData['bronchial']) lungDose = alvDose + bronchDose Aalvsolid = sol['A']['alv']['solid'] Aalvfluid = sol['A']['alv']['fluid'] Aalvtissue = sol['A']['alv']['tissue'] AsysGut = sol['A']['sys']['gut'] AsysPer = sol['A']['sys']['per'] AsysCtr = sol['A']['sys']['ctr'] Atisbr = sol['A']['br']['tissue'] Abrtissue = Atisbr Vtisbr = lungParams.getBronchial()['fVol'] * lungParams.getSystemic( )['OWlung'] Cavgbr = Atisbr / Vtisbr Abrcleared = sol['A']['br']['clear'] Abrcleared = np.reshape(Abrcleared, Abrcleared.size) Abrsolid = sol['A']['br']['solid'] Abrfluid = sol['A']['br']['fluid'] Acleared = sol['A']['sys']['clear'] + AsysGut - AsysGut[0] lungRetention = 100 * (lungDose - Acleared) / lungDose # in percent of lung dose Csysnmol = sol['C']['sys']['ctr'] Csys = Csysnmol * substanceParams.getData()['MW'] CsysPer = AsysPer * substanceParams.getData( )['MW'] / pkLungParams.pkData['Vp'] # Create output self.experimentLungRetention = PKPDExperiment() self.experimentLungRetention.general["title"] = "Inhalation simulate" tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit("min") Rvar = PKPDVariable() Rvar.varName = "Retention" Rvar.varType = PKPDVariable.TYPE_NUMERIC Rvar.role = PKPDVariable.ROLE_MEASUREMENT Rvar.units = createUnit("none") Rvar.comment = "Lung retention (% lung dose)" Cnmolvar = PKPDVariable() Cnmolvar.varName = "Cnmol" Cnmolvar.varType = PKPDVariable.TYPE_NUMERIC Cnmolvar.role = PKPDVariable.ROLE_MEASUREMENT Cnmolvar.units = createUnit("nmol/mL") Cnmolvar.comment = "Central compartment concentration" Cvar = PKPDVariable() Cvar.varName = "C" Cvar.varType = PKPDVariable.TYPE_NUMERIC Cvar.role = PKPDVariable.ROLE_MEASUREMENT Cvar.units = createUnit("g/mL") Cvar.comment = "Central compartment concentration" alvTissueVar = PKPDVariable() alvTissueVar.varName = "alvTissue" alvTissueVar.varType = PKPDVariable.TYPE_NUMERIC alvTissueVar.role = PKPDVariable.ROLE_MEASUREMENT alvTissueVar.units = createUnit("nmol") alvTissueVar.comment = "Amount in alveoli" alvSolidVar = PKPDVariable() alvSolidVar.varName = "alvSolid" alvSolidVar.varType = PKPDVariable.TYPE_NUMERIC alvSolidVar.role = PKPDVariable.ROLE_MEASUREMENT alvSolidVar.units = createUnit("nmol") alvSolidVar.comment = "Amount undissolved in alveoli" alvFluidVar = PKPDVariable() alvFluidVar.varName = "alvFluid" alvFluidVar.varType = PKPDVariable.TYPE_NUMERIC alvFluidVar.role = PKPDVariable.ROLE_MEASUREMENT alvFluidVar.units = createUnit("nmol") alvFluidVar.comment = "Amount in alveolar lining fluid" brTissueVar = PKPDVariable() brTissueVar.varName = "brTissue" brTissueVar.varType = PKPDVariable.TYPE_NUMERIC brTissueVar.role = PKPDVariable.ROLE_MEASUREMENT brTissueVar.units = createUnit("nmol") brTissueVar.comment = "Amount in bronchii" brSolidVar = PKPDVariable() brSolidVar.varName = "brSolid" brSolidVar.varType = PKPDVariable.TYPE_NUMERIC brSolidVar.role = PKPDVariable.ROLE_MEASUREMENT brSolidVar.units = createUnit("nmol") brSolidVar.comment = "Amount undissolved in bronchii" brFluidVar = PKPDVariable() brFluidVar.varName = "brFluid" brFluidVar.varType = PKPDVariable.TYPE_NUMERIC brFluidVar.role = PKPDVariable.ROLE_MEASUREMENT brFluidVar.units = createUnit("nmol") brFluidVar.comment = "Amount in bronchial lining fluid" brClvar = PKPDVariable() brClvar.varName = "brClear" brClvar.varType = PKPDVariable.TYPE_NUMERIC brClvar.role = PKPDVariable.ROLE_MEASUREMENT brClvar.units = createUnit("nmol") brClvar.comment = "Cumulative amount cleared by mucociliary elevator" brCTisvar = PKPDVariable() brCTisvar.varName = "CbrTis" brCTisvar.varType = PKPDVariable.TYPE_NUMERIC brCTisvar.role = PKPDVariable.ROLE_MEASUREMENT brCTisvar.units = createUnit("nmol/mL") brCTisvar.comment = "Concentration in bronchial tissue" sysGutVar = PKPDVariable() sysGutVar.varName = "sysAbsorption" sysGutVar.varType = PKPDVariable.TYPE_NUMERIC sysGutVar.role = PKPDVariable.ROLE_MEASUREMENT sysGutVar.units = createUnit("nmol") sysGutVar.comment = "Amount in absorption compartment" sysCtrVar = PKPDVariable() sysCtrVar.varName = "sysCentral" sysCtrVar.varType = PKPDVariable.TYPE_NUMERIC sysCtrVar.role = PKPDVariable.ROLE_MEASUREMENT sysCtrVar.units = createUnit("nmol") sysCtrVar.comment = "Amount in central compartment" sysPerVar = PKPDVariable() sysPerVar.varName = "sysPeripheral" sysPerVar.varType = PKPDVariable.TYPE_NUMERIC sysPerVar.role = PKPDVariable.ROLE_MEASUREMENT sysPerVar.units = createUnit("nmol") sysPerVar.comment = "Amount in peripheral compartment" CsysPerVar = PKPDVariable() CsysPerVar.varName = "Cp" CsysPerVar.varType = PKPDVariable.TYPE_NUMERIC CsysPerVar.role = PKPDVariable.ROLE_MEASUREMENT CsysPerVar.units = createUnit("g/mL") CsysPerVar.comment = "Concentration in peripheral compartment" doseNmolVar = PKPDVariable() doseNmolVar.varName = "dose_nmol" doseNmolVar.varType = PKPDVariable.TYPE_NUMERIC doseNmolVar.role = PKPDVariable.ROLE_LABEL doseNmolVar.units = createUnit("nmol") doseNmolVar.comment = "Input dose in nmol" doseThroatVar = PKPDVariable() doseThroatVar.varName = "throat_dose_nmol" doseThroatVar.varType = PKPDVariable.TYPE_NUMERIC doseThroatVar.role = PKPDVariable.ROLE_LABEL doseThroatVar.units = createUnit("nmol") doseThroatVar.comment = "Throat dose in nmol" doseLungVar = PKPDVariable() doseLungVar.varName = "lung_dose_nmol" doseLungVar.varType = PKPDVariable.TYPE_NUMERIC doseLungVar.role = PKPDVariable.ROLE_LABEL doseLungVar.units = createUnit("nmol") doseLungVar.comment = "Lung dose in nmol" doseBronchialVar = PKPDVariable() doseBronchialVar.varName = "bronchial_dose_nmol" doseBronchialVar.varType = PKPDVariable.TYPE_NUMERIC doseBronchialVar.role = PKPDVariable.ROLE_LABEL doseBronchialVar.units = createUnit("nmol") doseBronchialVar.comment = "Bronchial dose in nmol" doseAlveolarVar = PKPDVariable() doseAlveolarVar.varName = "alveolar_dose_nmol" doseAlveolarVar.varType = PKPDVariable.TYPE_NUMERIC doseAlveolarVar.role = PKPDVariable.ROLE_LABEL doseAlveolarVar.units = createUnit("nmol") doseAlveolarVar.comment = "Alveolar dose in nmol" mccClearedLungDoseFractionVar = PKPDVariable() mccClearedLungDoseFractionVar.varName = "mcc_cleared_lung_dose_fraction" mccClearedLungDoseFractionVar.varType = PKPDVariable.TYPE_NUMERIC mccClearedLungDoseFractionVar.role = PKPDVariable.ROLE_LABEL mccClearedLungDoseFractionVar.units = createUnit("None") mccClearedLungDoseFractionVar.comment = "MCC cleared lung dose fraction" self.experimentLungRetention.variables["t"] = tvar self.experimentLungRetention.variables["Retention"] = Rvar self.experimentLungRetention.variables["Cnmol"] = Cnmolvar self.experimentLungRetention.variables["C"] = Cvar self.experimentLungRetention.variables["alvTissue"] = alvTissueVar self.experimentLungRetention.variables["alvFluid"] = alvFluidVar self.experimentLungRetention.variables["alvSolid"] = alvSolidVar self.experimentLungRetention.variables["brTissue"] = brTissueVar self.experimentLungRetention.variables["brFluid"] = brFluidVar self.experimentLungRetention.variables["brSolid"] = brSolidVar self.experimentLungRetention.variables["brClear"] = brClvar self.experimentLungRetention.variables["CbrTis"] = brCTisvar self.experimentLungRetention.variables["sysCentral"] = sysCtrVar self.experimentLungRetention.variables["sysAbsoprtion"] = sysGutVar self.experimentLungRetention.variables["sysPeripheral"] = sysPerVar self.experimentLungRetention.variables["Cp"] = CsysPerVar self.experimentLungRetention.variables["dose_nmol"] = doseNmolVar self.experimentLungRetention.variables[ "throat_dose_nmol"] = doseThroatVar self.experimentLungRetention.variables["lung_dose_nmol"] = doseLungVar self.experimentLungRetention.variables[ "bronchial_dose_nmol"] = doseBronchialVar self.experimentLungRetention.variables[ "alveolar_dose_nmol"] = doseAlveolarVar self.experimentLungRetention.variables[ "mcc_cleared_lung_dose_fraction"] = mccClearedLungDoseFractionVar # Samples simulationSample = PKPDSample() simulationSample.sampleName = "simulation" simulationSample.addMeasurementColumn("t", tt) simulationSample.addMeasurementColumn("Retention", lungRetention) simulationSample.addMeasurementColumn("Cnmol", Csysnmol) simulationSample.addMeasurementColumn("C", Csys) simulationSample.addMeasurementColumn("alvFluid", Aalvfluid) simulationSample.addMeasurementColumn("alvTissue", Aalvtissue) simulationSample.addMeasurementColumn("alvSolid", Aalvsolid) simulationSample.addMeasurementColumn("brFluid", Abrfluid) simulationSample.addMeasurementColumn("brTissue", Abrtissue) simulationSample.addMeasurementColumn("brSolid", Abrsolid) simulationSample.addMeasurementColumn("brClear", Abrcleared) simulationSample.addMeasurementColumn("CbrTis", Cavgbr) simulationSample.addMeasurementColumn("sysAbsorption", AsysGut) simulationSample.addMeasurementColumn("sysCentral", AsysCtr) simulationSample.addMeasurementColumn("sysPeripheral", AsysPer) simulationSample.addMeasurementColumn("Cp", CsysPer) simulationSample.setDescriptorValue("dose_nmol", depositionData['dose_nmol']) simulationSample.setDescriptorValue("throat_dose_nmol", depositionData['throat']) lungDose = depositionData['dose_nmol'] - depositionData['throat'] simulationSample.setDescriptorValue("lung_dose_nmol", lungDose) simulationSample.setDescriptorValue("bronchial_dose_nmol", bronchDose) simulationSample.setDescriptorValue("alveolar_dose_nmol", alvDose) simulationSample.setDescriptorValue("mcc_cleared_lung_dose_fraction", Abrcleared[-1] / lungDose) self.experimentLungRetention.samples[ "simulmvarNameation"] = simulationSample self.experimentLungRetention.write(self._getPath("experiment.pkpd")) # Plots import matplotlib.pyplot as plt lungData = lungParams.getBronchial() Xbnd = np.sort([0] + lungData['end_cm'].tolist() + lungData['pos'].tolist()) Xctr = Xbnd[:-1] + np.diff(Xbnd) / 2 tvec = tt / 60 T = np.max(tvec) Cflu = sol['C']['br']['fluid'] Cs = substanceParams.getData()['Cs_br'] plt.figure(figsize=(15, 9)) plt.title('Concentration in bronchial fluid (Cs=%f [uM])' % Cs) plt.imshow(Cflu, interpolation='bilinear', aspect='auto', extent=[np.min(Xctr), np.max(Xctr), T, 0]) plt.clim(0, Cs) plt.xlim(np.min(Xctr), np.max(Xctr)) plt.ylim(0, T) plt.colorbar() plt.ylabel('Time [h]') plt.xlabel('Distance from throat [cm]') plt.savefig(self._getPath('concentrationBronchialFluid.png')) Ctis = sol['C']['br']['fluid'] plt.figure(figsize=(15, 9)) plt.title('Concentration in bronchial tissue') plt.imshow(Ctis, interpolation='bilinear', aspect='auto', extent=[np.min(Xctr), np.max(Xctr), T, 0]) plt.xlim(np.min(Xctr), np.max(Xctr)) plt.ylim(0, T) plt.colorbar() plt.ylabel('Time [h]') plt.xlabel('Distance from throat [cm]') plt.savefig(self._getPath('concentrationBronchialTissue.png')) def createOutputStep(self): self._defineOutputs(outputExperiment=self.experimentLungRetention) self._defineSourceRelation(self.ptrDeposition.get(), self.experimentLungRetention) self._defineSourceRelation(self.ptrPK.get(), self.experimentLungRetention) def _citations(self): return ['Hartung2020']
def runSimulation(self): self.deposition = PKDepositionParameters() self.deposition.setFiles(self.ptrDeposition.get().fnSubstance.get(), self.ptrDeposition.get().fnLung.get(), self.ptrDeposition.get().fnDeposition.get()) self.deposition.doseMultiplier = self.doseMultiplier.get() self.deposition.read() substanceParams = PKSubstanceLungParameters() substanceParams.multiplier = [ float(x) for x in self.substanceMultiplier.get().split() ] substanceParams.read(self.ptrDeposition.get().fnSubstance.get()) lungParams = PKPhysiologyLungParameters() lungParams.multiplier = [ float(x) for x in self.physiologyMultiplier.get().split() ] lungParams.read(self.ptrDeposition.get().fnLung.get()) pkParams = PKPDExperiment() pkParams.load(self.ptrPK.get().fnPKPD) pkLungParams = PKLung() pkLungParams.prepare( substanceParams, lungParams, pkParams, [float(x) for x in self.pkMultiplier.get().split()], self.ciliarySpeedType.get()) # diameters = np.concatenate((np.arange(0.1,1.1,0.1),np.arange(1.2,9.2,0.2))) # [um] evalStr = "np.concatenate((" + ",".join([ "np.arange(" + x.strip() + ")" for x in self.diameters.get().split(";") ]) + "))" diameters = eval(evalStr, {'np': np}) Sbnd = self.volMultiplier.get() * diam2vol(diameters) tt = np.arange(0, self.simulationTime.get() + self.deltaT.get(), self.deltaT.get()) sol = saturable_2D_upwind_IE(lungParams, pkLungParams, self.deposition, tt, Sbnd) # Postprocessing depositionData = self.deposition.getData() alvDose = np.sum(depositionData['alveolar']) bronchDose = np.sum(depositionData['bronchial']) lungDose = alvDose + bronchDose Aalvsolid = sol['A']['alv']['solid'] Aalvfluid = sol['A']['alv']['fluid'] Aalvtissue = sol['A']['alv']['tissue'] AsysGut = sol['A']['sys']['gut'] AsysPer = sol['A']['sys']['per'] AsysCtr = sol['A']['sys']['ctr'] Atisbr = sol['A']['br']['tissue'] Abrtissue = Atisbr Vtisbr = lungParams.getBronchial()['fVol'] * lungParams.getSystemic( )['OWlung'] Cavgbr = Atisbr / Vtisbr Abrcleared = sol['A']['br']['clear'] Abrcleared = np.reshape(Abrcleared, Abrcleared.size) Abrsolid = sol['A']['br']['solid'] Abrfluid = sol['A']['br']['fluid'] Acleared = sol['A']['sys']['clear'] + AsysGut - AsysGut[0] lungRetention = 100 * (lungDose - Acleared) / lungDose # in percent of lung dose Csysnmol = sol['C']['sys']['ctr'] Csys = Csysnmol * substanceParams.getData()['MW'] CsysPer = AsysPer * substanceParams.getData( )['MW'] / pkLungParams.pkData['Vp'] # Create output self.experimentLungRetention = PKPDExperiment() self.experimentLungRetention.general["title"] = "Inhalation simulate" tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit("min") Rvar = PKPDVariable() Rvar.varName = "Retention" Rvar.varType = PKPDVariable.TYPE_NUMERIC Rvar.role = PKPDVariable.ROLE_MEASUREMENT Rvar.units = createUnit("none") Rvar.comment = "Lung retention (% lung dose)" Cnmolvar = PKPDVariable() Cnmolvar.varName = "Cnmol" Cnmolvar.varType = PKPDVariable.TYPE_NUMERIC Cnmolvar.role = PKPDVariable.ROLE_MEASUREMENT Cnmolvar.units = createUnit("nmol/mL") Cnmolvar.comment = "Central compartment concentration" Cvar = PKPDVariable() Cvar.varName = "C" Cvar.varType = PKPDVariable.TYPE_NUMERIC Cvar.role = PKPDVariable.ROLE_MEASUREMENT Cvar.units = createUnit("g/mL") Cvar.comment = "Central compartment concentration" alvTissueVar = PKPDVariable() alvTissueVar.varName = "alvTissue" alvTissueVar.varType = PKPDVariable.TYPE_NUMERIC alvTissueVar.role = PKPDVariable.ROLE_MEASUREMENT alvTissueVar.units = createUnit("nmol") alvTissueVar.comment = "Amount in alveoli" alvSolidVar = PKPDVariable() alvSolidVar.varName = "alvSolid" alvSolidVar.varType = PKPDVariable.TYPE_NUMERIC alvSolidVar.role = PKPDVariable.ROLE_MEASUREMENT alvSolidVar.units = createUnit("nmol") alvSolidVar.comment = "Amount undissolved in alveoli" alvFluidVar = PKPDVariable() alvFluidVar.varName = "alvFluid" alvFluidVar.varType = PKPDVariable.TYPE_NUMERIC alvFluidVar.role = PKPDVariable.ROLE_MEASUREMENT alvFluidVar.units = createUnit("nmol") alvFluidVar.comment = "Amount in alveolar lining fluid" brTissueVar = PKPDVariable() brTissueVar.varName = "brTissue" brTissueVar.varType = PKPDVariable.TYPE_NUMERIC brTissueVar.role = PKPDVariable.ROLE_MEASUREMENT brTissueVar.units = createUnit("nmol") brTissueVar.comment = "Amount in bronchii" brSolidVar = PKPDVariable() brSolidVar.varName = "brSolid" brSolidVar.varType = PKPDVariable.TYPE_NUMERIC brSolidVar.role = PKPDVariable.ROLE_MEASUREMENT brSolidVar.units = createUnit("nmol") brSolidVar.comment = "Amount undissolved in bronchii" brFluidVar = PKPDVariable() brFluidVar.varName = "brFluid" brFluidVar.varType = PKPDVariable.TYPE_NUMERIC brFluidVar.role = PKPDVariable.ROLE_MEASUREMENT brFluidVar.units = createUnit("nmol") brFluidVar.comment = "Amount in bronchial lining fluid" brClvar = PKPDVariable() brClvar.varName = "brClear" brClvar.varType = PKPDVariable.TYPE_NUMERIC brClvar.role = PKPDVariable.ROLE_MEASUREMENT brClvar.units = createUnit("nmol") brClvar.comment = "Cumulative amount cleared by mucociliary elevator" brCTisvar = PKPDVariable() brCTisvar.varName = "CbrTis" brCTisvar.varType = PKPDVariable.TYPE_NUMERIC brCTisvar.role = PKPDVariable.ROLE_MEASUREMENT brCTisvar.units = createUnit("nmol/mL") brCTisvar.comment = "Concentration in bronchial tissue" sysGutVar = PKPDVariable() sysGutVar.varName = "sysAbsorption" sysGutVar.varType = PKPDVariable.TYPE_NUMERIC sysGutVar.role = PKPDVariable.ROLE_MEASUREMENT sysGutVar.units = createUnit("nmol") sysGutVar.comment = "Amount in absorption compartment" sysCtrVar = PKPDVariable() sysCtrVar.varName = "sysCentral" sysCtrVar.varType = PKPDVariable.TYPE_NUMERIC sysCtrVar.role = PKPDVariable.ROLE_MEASUREMENT sysCtrVar.units = createUnit("nmol") sysCtrVar.comment = "Amount in central compartment" sysPerVar = PKPDVariable() sysPerVar.varName = "sysPeripheral" sysPerVar.varType = PKPDVariable.TYPE_NUMERIC sysPerVar.role = PKPDVariable.ROLE_MEASUREMENT sysPerVar.units = createUnit("nmol") sysPerVar.comment = "Amount in peripheral compartment" CsysPerVar = PKPDVariable() CsysPerVar.varName = "Cp" CsysPerVar.varType = PKPDVariable.TYPE_NUMERIC CsysPerVar.role = PKPDVariable.ROLE_MEASUREMENT CsysPerVar.units = createUnit("g/mL") CsysPerVar.comment = "Concentration in peripheral compartment" doseNmolVar = PKPDVariable() doseNmolVar.varName = "dose_nmol" doseNmolVar.varType = PKPDVariable.TYPE_NUMERIC doseNmolVar.role = PKPDVariable.ROLE_LABEL doseNmolVar.units = createUnit("nmol") doseNmolVar.comment = "Input dose in nmol" doseThroatVar = PKPDVariable() doseThroatVar.varName = "throat_dose_nmol" doseThroatVar.varType = PKPDVariable.TYPE_NUMERIC doseThroatVar.role = PKPDVariable.ROLE_LABEL doseThroatVar.units = createUnit("nmol") doseThroatVar.comment = "Throat dose in nmol" doseLungVar = PKPDVariable() doseLungVar.varName = "lung_dose_nmol" doseLungVar.varType = PKPDVariable.TYPE_NUMERIC doseLungVar.role = PKPDVariable.ROLE_LABEL doseLungVar.units = createUnit("nmol") doseLungVar.comment = "Lung dose in nmol" doseBronchialVar = PKPDVariable() doseBronchialVar.varName = "bronchial_dose_nmol" doseBronchialVar.varType = PKPDVariable.TYPE_NUMERIC doseBronchialVar.role = PKPDVariable.ROLE_LABEL doseBronchialVar.units = createUnit("nmol") doseBronchialVar.comment = "Bronchial dose in nmol" doseAlveolarVar = PKPDVariable() doseAlveolarVar.varName = "alveolar_dose_nmol" doseAlveolarVar.varType = PKPDVariable.TYPE_NUMERIC doseAlveolarVar.role = PKPDVariable.ROLE_LABEL doseAlveolarVar.units = createUnit("nmol") doseAlveolarVar.comment = "Alveolar dose in nmol" mccClearedLungDoseFractionVar = PKPDVariable() mccClearedLungDoseFractionVar.varName = "mcc_cleared_lung_dose_fraction" mccClearedLungDoseFractionVar.varType = PKPDVariable.TYPE_NUMERIC mccClearedLungDoseFractionVar.role = PKPDVariable.ROLE_LABEL mccClearedLungDoseFractionVar.units = createUnit("None") mccClearedLungDoseFractionVar.comment = "MCC cleared lung dose fraction" self.experimentLungRetention.variables["t"] = tvar self.experimentLungRetention.variables["Retention"] = Rvar self.experimentLungRetention.variables["Cnmol"] = Cnmolvar self.experimentLungRetention.variables["C"] = Cvar self.experimentLungRetention.variables["alvTissue"] = alvTissueVar self.experimentLungRetention.variables["alvFluid"] = alvFluidVar self.experimentLungRetention.variables["alvSolid"] = alvSolidVar self.experimentLungRetention.variables["brTissue"] = brTissueVar self.experimentLungRetention.variables["brFluid"] = brFluidVar self.experimentLungRetention.variables["brSolid"] = brSolidVar self.experimentLungRetention.variables["brClear"] = brClvar self.experimentLungRetention.variables["CbrTis"] = brCTisvar self.experimentLungRetention.variables["sysCentral"] = sysCtrVar self.experimentLungRetention.variables["sysAbsoprtion"] = sysGutVar self.experimentLungRetention.variables["sysPeripheral"] = sysPerVar self.experimentLungRetention.variables["Cp"] = CsysPerVar self.experimentLungRetention.variables["dose_nmol"] = doseNmolVar self.experimentLungRetention.variables[ "throat_dose_nmol"] = doseThroatVar self.experimentLungRetention.variables["lung_dose_nmol"] = doseLungVar self.experimentLungRetention.variables[ "bronchial_dose_nmol"] = doseBronchialVar self.experimentLungRetention.variables[ "alveolar_dose_nmol"] = doseAlveolarVar self.experimentLungRetention.variables[ "mcc_cleared_lung_dose_fraction"] = mccClearedLungDoseFractionVar # Samples simulationSample = PKPDSample() simulationSample.sampleName = "simulation" simulationSample.addMeasurementColumn("t", tt) simulationSample.addMeasurementColumn("Retention", lungRetention) simulationSample.addMeasurementColumn("Cnmol", Csysnmol) simulationSample.addMeasurementColumn("C", Csys) simulationSample.addMeasurementColumn("alvFluid", Aalvfluid) simulationSample.addMeasurementColumn("alvTissue", Aalvtissue) simulationSample.addMeasurementColumn("alvSolid", Aalvsolid) simulationSample.addMeasurementColumn("brFluid", Abrfluid) simulationSample.addMeasurementColumn("brTissue", Abrtissue) simulationSample.addMeasurementColumn("brSolid", Abrsolid) simulationSample.addMeasurementColumn("brClear", Abrcleared) simulationSample.addMeasurementColumn("CbrTis", Cavgbr) simulationSample.addMeasurementColumn("sysAbsorption", AsysGut) simulationSample.addMeasurementColumn("sysCentral", AsysCtr) simulationSample.addMeasurementColumn("sysPeripheral", AsysPer) simulationSample.addMeasurementColumn("Cp", CsysPer) simulationSample.setDescriptorValue("dose_nmol", depositionData['dose_nmol']) simulationSample.setDescriptorValue("throat_dose_nmol", depositionData['throat']) lungDose = depositionData['dose_nmol'] - depositionData['throat'] simulationSample.setDescriptorValue("lung_dose_nmol", lungDose) simulationSample.setDescriptorValue("bronchial_dose_nmol", bronchDose) simulationSample.setDescriptorValue("alveolar_dose_nmol", alvDose) simulationSample.setDescriptorValue("mcc_cleared_lung_dose_fraction", Abrcleared[-1] / lungDose) self.experimentLungRetention.samples[ "simulmvarNameation"] = simulationSample self.experimentLungRetention.write(self._getPath("experiment.pkpd")) # Plots import matplotlib.pyplot as plt lungData = lungParams.getBronchial() Xbnd = np.sort([0] + lungData['end_cm'].tolist() + lungData['pos'].tolist()) Xctr = Xbnd[:-1] + np.diff(Xbnd) / 2 tvec = tt / 60 T = np.max(tvec) Cflu = sol['C']['br']['fluid'] Cs = substanceParams.getData()['Cs_br'] plt.figure(figsize=(15, 9)) plt.title('Concentration in bronchial fluid (Cs=%f [uM])' % Cs) plt.imshow(Cflu, interpolation='bilinear', aspect='auto', extent=[np.min(Xctr), np.max(Xctr), T, 0]) plt.clim(0, Cs) plt.xlim(np.min(Xctr), np.max(Xctr)) plt.ylim(0, T) plt.colorbar() plt.ylabel('Time [h]') plt.xlabel('Distance from throat [cm]') plt.savefig(self._getPath('concentrationBronchialFluid.png')) Ctis = sol['C']['br']['fluid'] plt.figure(figsize=(15, 9)) plt.title('Concentration in bronchial tissue') plt.imshow(Ctis, interpolation='bilinear', aspect='auto', extent=[np.min(Xctr), np.max(Xctr), T, 0]) plt.xlim(np.min(Xctr), np.max(Xctr)) plt.ylim(0, T) plt.colorbar() plt.ylabel('Time [h]') plt.xlabel('Distance from throat [cm]') plt.savefig(self._getPath('concentrationBronchialTissue.png'))
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 ProtPKPDDeconvolutionWagnerNelson(ProtPKPD): """ Calculate the absorption profile of an in vivo concentration profile using the Wagner-Nelson approach. This is only valid for profiles that have been modelled with a monocompartment PK model. The formula is Fabs(t)=(Cp(t)+Ke*AUC0t(t))/(Ke*AUC0inf) where Ke=Cl/V In this implementation it is assumed that AUC0inf is the last AUC0t observed, meaning that Cp(t) has almost vanished in the last samples""" _label = 'deconvolution Wagner Nelson' SAME_INPUT = 0 ANOTHER_INPUT = 1 BIOAVAIL_NONE = 0 BIOAVAIL_MULT = 1 BIOAVAIL_DIV = 2 #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam( 'inputExperiment', params.PointerParam, label="In-vivo profiles", pointerClass='PKPDExperiment', help= 'Make sure that it has a clearance parameter (Cl) and central volume (V)' ) form.addParam( 'externalIV', params.EnumParam, choices=[ 'Get impulse response from the same input fit', 'Get impulse response from another fit' ], label='Impulse response source', default=self.SAME_INPUT, help= "The impulse response is an estimate of the intravenous response") form.addParam('externalIVODE', params.PointerParam, label="External impulse response ODE model", condition='externalIV==1', pointerClass='ProtPKPDMonoCompartment, ProtPKPDTwoCompartments,ProtPKPDODERefine,' \ ' ProtPKPDTwoCompartmentsClint, ProtPKPDTwoCompartmentsClintCl', help='Select a run of an ODE model. It should be ideally the intravenous response.') form.addParam('timeVar', params.StringParam, label="Time variable", default="t", help='Which variable contains the time stamps.') form.addParam('concVar', params.StringParam, label="Concentration variable", default="Cp", help='Which variable contains the plasma concentration.') form.addParam( 'normalize', params.BooleanParam, label="Normalize by dose", default=True, help= 'Normalize the output by AUC0inf, so that a total absorption is represented by 100.' ) form.addParam( 'saturate', params.BooleanParam, label="Saturate at 100%", default=True, condition='normalize', help= 'Saturate the absorption so that there cannot be values beyond 100' ) form.addParam('considerBioaval', params.EnumParam, label="Consider bioavailability", default=self.BIOAVAIL_NONE, choices=[ 'Do not correct', 'Multiply deconvolution by bioavailability', 'Divide deconvolution by bioavailability' ], help='Take into account the bioavailability') form.addParam( 'resampleT', params.FloatParam, label="Resample profiles (time step)", default=-1, help= 'Resample the input profiles at this time step (make sure it is in the same units as the input). ' 'Leave it to -1 for no resampling') form.addParam( 'smooth', params.BooleanParam, label="Monotonic smooth", default=True, help= 'Apply a Pchip interpolation to make sure that the Adissolved is monotonically increasing' ) #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('deconvolve', self.inputExperiment.get().getObjId()) self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def addSample(self, sampleName, t, y): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.descriptors = {} newSample.addMeasurementPattern(["A"]) newSample.addMeasurementColumn("t", t) newSample.addMeasurementColumn("A", y) self.outputExperiment.samples[sampleName] = newSample def estimateAUCrightTail(self, t, Cp, Cl, V): idx = Cp > 0 x = t[idx] y = np.log10(Cp[idx]) ydiff = np.diff(y) idx = -1 while ydiff[idx] < 0: idx -= 1 if idx < -3: p = np.polyfit(x[idx:], y[idx:], 1) Ke = Cl / V lastCt = np.power(10, p[0] * x[-1] + p[1]) return lastCt / np.abs(Ke) else: return 0 def deconvolve(self, objId1): self.experiment = self.readExperiment( self.inputExperiment.get().fnPKPD) # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Avar = PKPDVariable() Avar.varName = "A" Avar.varType = PKPDVariable.TYPE_NUMERIC Avar.role = PKPDVariable.ROLE_MEASUREMENT Avar.units = createUnit("none") self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Avar.varName] = Avar self.outputExperiment.general[ "title"] = "Deconvolution of the amount released" self.outputExperiment.general[ "comment"] = "Amount released at any time t" # Get the input sample from another experiment if necessary sampleFrom = None if self.externalIV.get() == self.ANOTHER_INPUT: anotherExperiment = self.readExperiment( self.externalIVODE.get().outputExperiment.fnPKPD) for _, sampleFrom in anotherExperiment.samples.items( ): # Take the first sample from the reference break timeRange = self.experiment.getRange(self.timeVar.get()) for sampleName, sample in self.experiment.samples.items(): # Get t, Cp t = np.asarray(sample.getValues(self.timeVar.get()), dtype=np.float64) Cp = np.asarray(sample.getValues(self.concVar.get()), dtype=np.float64) Cp = np.clip(Cp, 0.0, None) t = np.insert(t, 0, 0) # Add (0,0) to the profile Cp = np.insert(Cp, 0, 0) t, Cp = uniqueFloatValues(t, Cp) if self.resampleT.get() > 0: B = InterpolatedUnivariateSpline(t, Cp, k=1) t = np.arange(np.min(t), np.max(t) + self.resampleT.get(), self.resampleT.get()) Cp = B(t) # Calculate AUC0t AUC0t = calculateAUC0t(t, Cp) # Deconvolve if self.externalIV.get() == self.SAME_INPUT: sampleFrom = sample Cl = float(sampleFrom.descriptors['Cl']) V = float(sampleFrom.descriptors['V']) Ke = Cl / V AUC0inf = float(AUC0t[-1]) + self.estimateAUCrightTail( t, Cp, Cl, V) A = (Cp + Ke * AUC0t) / Ke if self.normalize.get(): A *= 100 / AUC0inf if self.saturate.get(): A = np.clip(A, None, 100.0) A = np.clip(A, 0, None) if self.smooth: if t[0] > 0: t = np.insert(t, 0, 0) A = np.insert(A, 0, 0) if self.saturate.get() and self.normalize.get(): A = np.clip(A, None, 100.0) A = np.clip(smoothPchip(t, A), 0, None) if self.saturate.get() and self.normalize.get(): A = np.clip(A, None, 100.0) if self.considerBioaval.get() == self.BIOAVAIL_DIV: A /= sample.getBioavailability() elif self.considerBioaval.get() == self.BIOAVAIL_MULT: A *= sample.getBioavailability() self.addSample(sampleName, t, A) self.outputExperiment.write(self._getPath("experiment.pkpd")) def createOutputStep(self): self._defineOutputs(outputExperiment=self.outputExperiment) self._defineSourceRelation(self.inputExperiment.get(), self.outputExperiment) def _validate(self): retval = [] if self.externalIV.get() == self.ANOTHER_INPUT: sample = self.readExperiment(self.externalIVODE.get( ).outputExperiment.fnPKPD).getFirstSample() else: sample = self.readExperiment( self.inputExperiment.get().fnPKPD).getFirstSample() if sample is None: reval.append('Cannot find a sample in the input experiment') else: if sample.getDescriptorValue('Cl') is None: retval.append('Cannot find Cl in the input experiment') if sample.getDescriptorValue('V') is None: retval.append('Cannot find V in the input experiment') return retval def _summary(self): retval = [] return retval
class ProtPKPDODESimulate2(ProtPKPDODEBase): """ Simulate a complex sequence of doses. Each dose has its own PK profile, and the overall profile is the addition of all the individual profiles. Only the parameters from the first fitting of each model are considered. The first dose goes with the first model, the second dose with the second model, ... A single profile is simulated that is the addition of the different simulations for each one of the input models.""" _label = 'PK simulate (complex)' #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam('inputODEs', params.MultiPointerParam, label="Input ODE models", pointerClass='ProtPKPDMonoCompartment, ProtPKPDTwoCompartments, ProtPKPDMonoCompartmentPD, ProtPKPDTwoCompartmentsBothPD, '\ 'ProtPKPDODERefine, ProtPKPDTwoCompartmentsClint, ProtPKPDTwoCompartmentsClintCl', help='Select a run of an ODE model') form.addParam('doses', params.TextParam, label="Doses", height=5, width=50, default="", help="Structure: [Dose Name] ; [Via] ; [Dose type] ; [time] ; [dose] \n"\ "The dose name should have no space or special character\n"\ "The via should be one present in the input experiment to the ODE model.\n"\ "Valid units are: h, mg, ug, ...\n"\ "The description is either a bolus or an infusion as shown in the examples\n"\ "\nIt is important that there are two semicolons.\n"\ "Examples:\n"\ "Infusion0; via=Intravenous; infusion; t=0.500000:0.750000 h; d=60 mg/h\n"\ "Bolus0; via=Oral; bolus; t=0.000000 min; d=60 mg\n"\ "RepeatedBolus; via=Oral; repeated_bolus; t=0:24:120 h; d=60 mg") form.addParam('t0', params.FloatParam, label="Initial time (see help)", default=0, help="Same units as input experiment") form.addParam('tF', params.FloatParam, label="Final time (see help)", default=24 * 7, help="Same units as input experiment") form.addParam('deltaT', params.FloatParam, label="Time step (see help)", default=0.5, expertLevel=LEVEL_ADVANCED, help="Same units as input experiment") #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('runSimulate') self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def addSample(self, sampleName, doseList, simulationsX, y): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.doseDictPtr = self.outputExperiment.doses newSample.descriptors = {} newSample.doseList = doseList if type(self.varNameY) != list: newSample.addMeasurementPattern([self.varNameY]) newSample.addMeasurementColumn("t", simulationsX) newSample.addMeasurementColumn(self.varNameY, y) else: for j in range(len(self.varNameY)): newSample.addMeasurementPattern([self.varNameY[j]]) newSample.addMeasurementColumn("t", simulationsX) for j in range(len(self.varNameY)): newSample.addMeasurementColumn(self.varNameY[j], y[j]) self.outputExperiment.samples[sampleName] = newSample def runSimulate(self): # Take first experiment self.protODE = self.inputODEs[0].get() if hasattr(self.protODE, "outputExperiment"): self.experiment = self.readExperiment( self.protODE.outputExperiment.fnPKPD, show=False) elif hasattr(self.protODE, "outputExperiment1"): self.experiment = self.readExperiment( self.protODE.outputExperiment1.fnPKPD, show=False) else: raise Exception("Cannot find an outputExperiment in the input ODE") if hasattr(self.protODE, "outputFitting"): self.fitting = self.readFitting( self.protODE.outputFitting.fnFitting, show=False) elif hasattr(self.protODE, "outputFitting1"): self.fitting = self.readFitting( self.protODE.outputFitting1.fnFitting, show=False) self.varNameX = self.fitting.predictor.varName if type(self.fitting.predicted) != list: self.varNameY = self.fitting.predicted.varName else: self.varNameY = [var.varName for var in self.fitting.predicted] # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Nsamples = int( math.ceil((self.tF.get() - self.t0.get()) / self.deltaT.get())) + 1 if tvar.units == PKPDUnit.UNIT_TIME_MIN: Nsamples *= 60 self.outputExperiment.variables[self.varNameX] = tvar if type(self.fitting.predicted) != list: self.outputExperiment.variables[ self.varNameY] = self.experiment.variables[self.varNameY] else: for varName in self.varNameY: self.outputExperiment.variables[ varName] = self.experiment.variables[varName] self.outputExperiment.general["title"] = "Simulated ODE response" self.outputExperiment.general["comment"] = "Simulated ODE response" self.outputExperiment.vias = self.experiment.vias # Read the doses doseLines = [] for line in self.doses.get().replace('\n', ';;').split(';;'): doseLines.append(line) doseIdx = 0 simulationsY = None doseList = [] for protODEPtr in self.inputODEs: self.protODE = protODEPtr.get() if hasattr(self.protODE, "outputExperiment"): self.experiment = self.readExperiment( self.protODE.outputExperiment.fnPKPD, show=False) elif hasattr(self.protODE, "outputExperiment1"): self.experiment = self.readExperiment( self.protODE.outputExperiment1.fnPKPD, show=False) else: raise Exception( "Cannot find an outputExperiment in the input ODE") if hasattr(self.protODE, "outputFitting"): self.fitting = self.readFitting( self.protODE.outputFitting.fnFitting, show=False) elif hasattr(self.protODE, "outputFitting1"): self.fitting = self.readFitting( self.protODE.outputFitting1.fnFitting, show=False) for viaName in self.experiment.vias: if not viaName in self.outputExperiment.vias: self.outputExperiment.vias[viaName] = copy.copy( self.experiment.vias[viaName]) # Create drug source self.clearGroupParameters() self.createDrugSource() # Setup model self.model = self.protODE.createModel() self.model.setExperiment(self.outputExperiment) self.model.deltaT = self.deltaT.get() self.model.setXVar(self.varNameX) self.model.setYVar(self.varNameY) self.model.x = [ self.t0.get() + i * self.model.deltaT for i in range(0, Nsamples) ] self.modelList.append(self.model) tokens = doseLines[doseIdx].split(';') if len(tokens) < 5: print("Skipping dose: ", line) continue dosename = tokens[0].strip() self.outputExperiment.doses[dosename] = PKPDDose() self.outputExperiment.doses[dosename].parseTokens( tokens, self.outputExperiment.vias) doseList.append(dosename) auxSample = PKPDSample() auxSample.descriptors = {} auxSample.doseDictPtr = self.outputExperiment.doses auxSample.variableDictPtr = self.outputExperiment.variables auxSample.doseList = [dosename] auxSample.interpretDose() self.drugSource.setDoses(auxSample.parsedDoseList, self.t0.get() - 10, self.tF.get() + 10) self.model.drugSource = self.drugSource # Simulate the different responses simulationsX = self.model.x self.setTimeRange(None) parameters = self.fitting.sampleFits[0].parameters print("Input model: %s" % self.protODE.getObjLabel()) print("Sample name: %s" % self.fitting.sampleFits[0].sampleName) print("Parameters: ", parameters) print("Dose: %s" % doseLines[doseIdx]) print(" ") # Prepare source and this object self.protODE.configureSource(self.drugSource) parameterNames = self.getParameterNames( ) # Necessary to count the number of source and PK parameters # Prepare the model y = self.forwardModel(parameters, [simulationsX] * self.getResponseDimension()) # Keep results if simulationsY is None: simulationsY = copy.copy(y) else: for j in range(self.getResponseDimension()): simulationsY[j] += y[j] doseIdx += 1 self.addSample("Simulation", doseList, simulationsX, simulationsY[0]) self.outputExperiment.write(self._getPath("experiment.pkpd")) def createOutputStep(self): self._defineOutputs(outputExperiment=self.outputExperiment) for protODEPtr in self.inputODEs: self._defineSourceRelation(protODEPtr.get(), self.outputExperiment) #--------------------------- INFO functions -------------------------------------------- def _summary(self): msg = [] return msg def _validate(self): msg = [] return msg
def testDissolutionWorkflow(self): # Create invivo data experimentStr = """ [EXPERIMENT] =========================== comment = title = Dissolution [VARIABLES] ============================ C ; none ; numeric[%f] ; measurement ; Concentration in solution (%) t ; min ; numeric[%f] ; time ; Time in minutes since start [VIAS] ================================ [DOSES] ================================ [GROUPS] ================================ __Profile [SAMPLES] ================================ Profile; group=__Profile [MEASUREMENTS] =========================== Profile ; t; C 0 0 2.5 1.7 5 8.3 7.5 13.3 10 20.0 20 44.0 30 61.0 40 70.7 60 78.0 80 79.7 100 80.7 120 80.0 160 81.3 200 82.0 240 82.3 """ fnExperiment = "experimentInVitro.pkpd" fhExperiment = open(fnExperiment, "w") fhExperiment.write(experimentStr) fhExperiment.close() print("Import Experiment in vitro") protImport = self.newProtocol(ProtImportExperiment, objLabel='pkpd - import experiment in vitro', inputFile=fnExperiment) self.launchProtocol(protImport) self.assertIsNotNone(protImport.outputExperiment.fnPKPD, "There was a problem with the import") self.validateFiles('protImport', protImport) os.remove(fnExperiment) # Fit a Weibull dissolution print("Fitting Weibull model ...") protWeibull = self.newProtocol(ProtPKPDDissolutionFit, objLabel='pkpd - fit dissolution Weibull', globalSearch=True, modelType=3) protWeibull.inputExperiment.set(protImport.outputExperiment) self.launchProtocol(protWeibull) self.assertIsNotNone(protWeibull.outputExperiment.fnPKPD, "There was a problem with the dissolution model ") self.assertIsNotNone(protWeibull.outputFitting.fnFitting, "There was a problem with the dissolution model ") self.validateFiles('ProtPKPDDissolutionFit', ProtPKPDDissolutionFit) experiment = PKPDExperiment() experiment.load(protWeibull.outputExperiment.fnPKPD) Vmax = float(experiment.samples['Profile'].descriptors['Vmax']) self.assertTrue(Vmax>80 and Vmax<82) lambdda = float(experiment.samples['Profile'].descriptors['lambda']) self.assertTrue(lambdda>0.009 and lambdda<0.011) b = float(experiment.samples['Profile'].descriptors['b']) self.assertTrue(b>1.4 and b<1.5) fitting = PKPDFitting() fitting.load(protWeibull.outputFitting.fnFitting) self.assertTrue(fitting.sampleFits[0].R2>0.997) # Create invivo data experimentStr = """ [EXPERIMENT] =========================== comment = Generated as C(t)=D0/V*Ka/(Ka-Ke)*)(exp(-Ke*t)-exp(-Ka*t)) title = My experiment [VARIABLES] ============================ Cp ; ug/L ; numeric[%f] ; measurement ; Plasma concentration t ; min ; numeric[%f] ; time ; [VIAS] ================================ Oral; splineXY5; tlag min; bioavailability=1.000000 [DOSES] ================================ Bolus1; via=Oral; bolus; t=0.000000 h; d=200 ug [GROUPS] ================================ __Individual1 [SAMPLES] ================================ Individual1; dose=Bolus1; group=__Individual1 [MEASUREMENTS] =========================== Individual1 ; t; Cp """ t = np.arange(0,1000,10) Cp = unitResponse(100,50,0.05,0.2,t-20)+unitResponse(100,50,0.05,0.2,t-120) for n in range(t.size): experimentStr+="%f %f\n"%(t[n],Cp[n]) fnExperiment ="experimentInVivo.pkpd" fhExperiment = open(fnExperiment,"w") fhExperiment.write(experimentStr) fhExperiment.close() print("Import Experiment in vivo") protImportInVivo = self.newProtocol(ProtImportExperiment, objLabel='pkpd - import experiment in vivo', inputFile=fnExperiment) self.launchProtocol(protImportInVivo) self.assertIsNotNone(protImportInVivo.outputExperiment.fnPKPD, "There was a problem with the import") self.validateFiles('protImport', protImportInVivo) os.remove(fnExperiment) # NCA numeric print("NCA numeric ...") protNCA = self.newProtocol(ProtPKPDNCANumeric, objLabel='pkpd - nca numeric') protNCA.inputExperiment.set(protImportInVivo.outputExperiment) self.launchProtocol(protNCA) self.assertIsNotNone(protNCA.outputExperiment.fnPKPD, "There was a problem with the NCA numeric") self.validateFiles('prot', protNCA) experiment = PKPDExperiment() experiment.load(protNCA.outputExperiment.fnPKPD) AUC0t = float(experiment.samples['Individual1'].descriptors['AUC0t']) self.assertTrue(AUC0t > 960 and AUC0t < 980) AUMC0t = float(experiment.samples['Individual1'].descriptors['AUMC0t']) self.assertTrue(AUMC0t > 305000 and AUMC0t < 306000) Cmax = float(experiment.samples['Individual1'].descriptors['Cmax']) self.assertTrue(Cmax > 2.7 and Cmax < 2.9) Tmax = float(experiment.samples['Individual1'].descriptors['Tmax']) self.assertTrue(Tmax > 155 and Tmax < 165) MRT = float(experiment.samples['Individual1'].descriptors['MRT']) self.assertTrue(MRT > 314 and MRT < 315) # Fit Order 1 print("Fitting splines5-monocompartment model ...") protModelInVivo = self.newProtocol(ProtPKPDMonoCompartment, objLabel='pkpd - fit monocompartment', bounds="(15.0, 30.0); (0.0, 400.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.0, 1.0); (0.15, 0.25); (47, 53)" ) protModelInVivo.inputExperiment.set(protImportInVivo.outputExperiment) self.launchProtocol(protModelInVivo) self.assertIsNotNone(protModelInVivo.outputExperiment.fnPKPD, "There was a problem with the PK model") self.assertIsNotNone(protModelInVivo.outputFitting.fnFitting, "There was a problem with the PK model") self.validateFiles('ProtPKPDMonoCompartment', ProtPKPDMonoCompartment) experiment = PKPDExperiment() experiment.load(protModelInVivo.outputExperiment.fnPKPD) V = float(experiment.samples['Individual1'].descriptors['V']) self.assertTrue(V>46 and V<54) Cl = float(experiment.samples['Individual1'].descriptors['Cl']) self.assertTrue(Cl>0.18 and Cl<0.22) fitting = PKPDFitting() fitting.load(protModelInVivo.outputFitting.fnFitting) self.assertTrue(fitting.sampleFits[0].R2>0.995) # Deconvolve the in vivo print("Deconvolving in vivo ...") protDeconv = self.newProtocol(ProtPKPDDeconvolve, objLabel='pkpd - deconvolution' ) protDeconv.inputODE.set(protModelInVivo) self.launchProtocol(protDeconv) self.assertIsNotNone(protDeconv.outputExperiment.fnPKPD, "There was a problem with the deconvolution") self.validateFiles('ProtPKPDDeconvolve', ProtPKPDDeconvolve) # Levy plot print("Levy plot ...") protLevy = self.newProtocol(ProtPKPDDissolutionLevyPlot, objLabel='pkpd - levy plot' ) protLevy.inputInVitro.set(protWeibull) protLevy.inputInVivo.set(protDeconv) self.launchProtocol(protLevy) self.assertIsNotNone(protLevy.outputExperiment.fnPKPD, "There was a problem with the Levy plot") self.validateFiles('ProtPKPDDissolutionLevyPlot', ProtPKPDDissolutionLevyPlot) # IVIVC print("In vitro-in vivo correlation ...") protIVIVC = self.newProtocol(ProtPKPDDissolutionIVIVC, timeScale=5, responseScale=1, objLabel='pkpd - ivivc' ) protIVIVC.inputInVitro.set(protWeibull) protIVIVC.inputInVivo.set(protDeconv) self.launchProtocol(protIVIVC) self.assertIsNotNone(protIVIVC.outputExperimentFabs.fnPKPD, "There was a problem with the IVIVC") self.assertIsNotNone(protIVIVC.outputExperimentAdissol.fnPKPD, "There was a problem with the IVIVC") self.validateFiles('ProtPKPDDissolutionIVIVC', ProtPKPDDissolutionIVIVC) # IVIVC generic print("In vitro-in vivo generic ...") protIVIVCG = self.newProtocol(ProtPKPDDissolutionIVIVCGeneric, timeScale='$[k1]*$(t)+$[k2]*np.power($(t),2)+$[k3]*np.power($(t),3)', timeBounds='k1: [0,3]; k2: [-0.1,0.01]; k3: [0,1e-3]', responseScale='$[A]*$(Adissol)+$[B]+$[C]*np.power($(Adissol),2)', responseBounds='A: [0.01,1]; B: [-50,30]; C: [-0.05,0.05]', objLabel='pkpd - ivivc generic' ) protIVIVCG.inputInVitro.set(protWeibull) protIVIVCG.inputInVivo.set(protDeconv) self.launchProtocol(protIVIVCG) self.assertIsNotNone(protIVIVCG.outputExperimentFabs.fnPKPD, "There was a problem with the IVIVC Generic") self.validateFiles('ProtPKPDDissolutionIVIVCG', ProtPKPDDissolutionIVIVCGeneric) # IVIVC splines print("In vitro-in vivo splies ...") protIVIVCS = self.newProtocol(ProtPKPDDissolutionIVIVCSplines, timeScale=1, responseScale=1, objLabel='pkpd - ivivc splines' ) protIVIVCS.inputInVitro.set(protWeibull) protIVIVCS.inputInVivo.set(protDeconv) self.launchProtocol(protIVIVCS) self.assertIsNotNone(protIVIVCS.outputExperimentFabs.fnPKPD, "There was a problem with the IVIVC Splines") self.validateFiles('ProtPKPDDissolutionIVIVCS', ProtPKPDDissolutionIVIVCSplines) # Dissolution simulation print("IVIV+PK simulation ...") protIVIVPKL = self.newProtocol(ProtPKPDDissolutionPKSimulation, objLabel='pkpd - ivivc+pk', conversionType=1, inputN=1, tF=16.66, addIndividuals=True, inputDose=200 ) protIVIVPKL.inputInVitro.set(protWeibull.outputFitting) protIVIVPKL.inputPK.set(protModelInVivo.outputFitting) protIVIVPKL.inputLevy.set(protLevy.outputExperiment) self.launchProtocol(protIVIVPKL) self.assertIsNotNone(protIVIVPKL.outputExperiment.fnPKPD, "There was a problem with the simulation") self.validateFiles('ProtPKPDDissolutionPKSimulation', ProtPKPDDissolutionPKSimulation) # Dissolution simulation print("IVIV+PK simulation ...") protIVIVPKS = self.newProtocol(ProtPKPDDissolutionPKSimulation, objLabel='pkpd - ivivc+pk', inputN=1, tF=16.66, addIndividuals=True, inputDose=200 ) protIVIVPKS.inputInVitro.set(protWeibull.outputFitting) protIVIVPKS.inputPK.set(protModelInVivo.outputFitting) protIVIVPKS.inputIvIvC.set(protIVIVCS.outputExperimentFabs) self.launchProtocol(protIVIVPKS) self.assertIsNotNone(protIVIVPKS.outputExperiment.fnPKPD, "There was a problem with the simulation") self.validateFiles('ProtPKPDDissolutionPKSimulation', ProtPKPDDissolutionPKSimulation) # Internal validity print("Internal validity ...") protInternal = self.newProtocol(ProtPKPDIVIVCInternalValidity, objLabel='pkpd - internal validity') protInternal.inputExperiment.set(protNCA.outputExperiment) protInternal.inputSimulated.set(protIVIVPKL.outputExperiment) self.launchProtocol(protInternal) fnSummary = protInternal._getPath("summary.txt") self.assertTrue(os.path.exists(fnSummary)) lineNo = 0 for line in open(fnSummary).readlines(): tokens = line.split('=') if lineNo == 0: AUCmean = np.abs(float(tokens[-1])) self.assertTrue(AUCmean < 20) elif lineNo == 1: Cmaxmean = np.abs(float(tokens[-1])) self.assertTrue(Cmaxmean < 13) lineNo += 1 # Internal validity print("Internal validity ...") protInternal = self.newProtocol(ProtPKPDIVIVCInternalValidity, objLabel='pkpd - internal validity') protInternal.inputExperiment.set(protNCA.outputExperiment) protInternal.inputSimulated.set(protIVIVPKS.outputExperiment) self.launchProtocol(protInternal) fnSummary = protInternal._getPath("summary.txt") self.assertTrue(os.path.exists(fnSummary)) lineNo = 0 for line in open(fnSummary).readlines(): tokens = line.split('=') if lineNo == 0: AUCmean = np.abs(float(tokens[-1])) self.assertTrue(AUCmean < 10) elif lineNo == 1: Cmaxmean = np.abs(float(tokens[-1])) self.assertTrue(Cmaxmean < 20) lineNo += 1
class ProtPKPDDissolutionIVIVCJoin(ProtPKPD): """ Join several IVIVCs into a single one. The strategy is to compute the average of all the plots involved in the IVIVC process: 1) tvivo -> tvitro; 2) tvitro -> Adissol; 3) Adissol->FabsPredicted. The plot tvivo-Fabs comes after the IVIVC process, while the plot tvivo-FabsOrig is the observed one in the input files. These two plots need not be exactly the same. """ _label = 'dissol ivivc join avg' #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam( 'inputIVIVCs', params.MultiPointerParam, label="IVIVCs Fabs", pointerClass='PKPDExperiment', help= 'Choose experiments with IVIV correlations (only the Fabs experiments)' ) #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('calculateAllIvIvC') self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def calculateAllIvIvC(self): L1 = [] L2 = [] L3 = [] L4 = [] L5 = [] for ptrExperiment in self.inputIVIVCs: experiment = PKPDExperiment() experiment.load(ptrExperiment.get().fnPKPD.get()) x, y = experiment.getXYMeanValues("tvivo", "tvitroReinterpolated") L1.append((x, y)) x, y = experiment.getXYMeanValues("tvivo", "Fabs") L2.append((x, y)) x, y = experiment.getXYMeanValues("AdissolReinterpolated", "FabsPredicted") L3.append((x, y)) x, y = experiment.getXYMeanValues("FabsPredicted", "Fabs") L4.append((x, y)) x, y = experiment.getXYMeanValues("tvitroReinterpolated", "AdissolReinterpolated") L5.append((x, y)) tvivo1, tvitroReinterpolatedY = computeXYmean(L1, common=True) tvivoOrig, FabsOrig = computeXYmean(L2, common=True) AdissolReinterpolatedX, FabsPredictedY = computeXYmean(L3, common=True) FabsPredictedX, Fabs = computeXYmean(L4, common=True) tvitroReinterpolatedX, AdissolReinterpolatedY = computeXYmean( L5, common=True) x, y = twoWayUniqueFloatValues(tvivo1, tvitroReinterpolatedY) Bt = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(tvitroReinterpolatedX, AdissolReinterpolatedY) BtA = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(tvivoOrig, FabsOrig) BtF = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(AdissolReinterpolatedX, FabsPredictedY) BAF = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(FabsPredictedX, Fabs) BFF = InterpolatedUnivariateSpline(x, y, k=1) vtvitroReinterpolated = np.zeros(len(tvivo1)) vAdissolReinterpolated = np.zeros(len(tvivo1)) vFabs = np.zeros(len(tvivo1)) vFabsPredicted = np.zeros(len(tvivo1)) vFabsOrig = np.zeros(len(tvivo1)) for i in range(len(tvivo1)): tvivoi = tvivo1[i] vtvitroReinterpolated[i] = Bt(tvivoi) vAdissolReinterpolated[i] = BtA(vtvitroReinterpolated[i]) vFabsPredicted[i] = BAF(vAdissolReinterpolated[i]) vFabs[i] = BFF(vFabsPredicted[i]) vFabsOrig[i] = BtF(tvivoi) tvitroReinterpolatedVar = experiment.variables["tvitroReinterpolated"] AdissolReinterpolatedVar = experiment.variables[ "AdissolReinterpolated"] tvivoVar = experiment.variables["tvivo"] FabsOrigVar = copy.copy(experiment.variables["Fabs"]) FabsOrigVar.varName = "FabsOriginal" FabsVar = experiment.variables["Fabs"] FabsVar.comment += ". After IVIVC: tvivo->tvitro->Adissol->Fabs " FabsPredictedVar = experiment.variables["FabsPredicted"] self.outputExperimentFabsSingle = PKPDExperiment() self.outputExperimentFabsSingle.variables[ tvitroReinterpolatedVar.varName] = tvitroReinterpolatedVar self.outputExperimentFabsSingle.variables[ AdissolReinterpolatedVar.varName] = AdissolReinterpolatedVar self.outputExperimentFabsSingle.variables[tvivoVar.varName] = tvivoVar self.outputExperimentFabsSingle.variables[FabsVar.varName] = FabsVar self.outputExperimentFabsSingle.variables[ FabsPredictedVar.varName] = FabsPredictedVar self.outputExperimentFabsSingle.variables[ FabsOrigVar.varName] = FabsOrigVar self.outputExperimentFabsSingle.general[ "title"] = "In-vitro In-vivo correlation" self.outputExperimentFabsSingle.general[ "comment"] = "Fabs vs Predicted Fabs" sampleName = "jointIVIVC" newSampleFabsSingle = PKPDSample() newSampleFabsSingle.sampleName = sampleName newSampleFabsSingle.variableDictPtr = self.outputExperimentFabsSingle.variables newSampleFabsSingle.descriptors = {} newSampleFabsSingle.addMeasurementColumn("tvitroReinterpolated", vtvitroReinterpolated) newSampleFabsSingle.addMeasurementColumn("AdissolReinterpolated", vAdissolReinterpolated) newSampleFabsSingle.addMeasurementColumn("tvivo", tvivo1) newSampleFabsSingle.addMeasurementColumn("FabsPredicted", vFabsPredicted) newSampleFabsSingle.addMeasurementColumn("Fabs", vFabs) newSampleFabsSingle.addMeasurementColumn("FabsOriginal", vFabsOrig) self.outputExperimentFabsSingle.samples[ sampleName] = newSampleFabsSingle self.outputExperimentFabsSingle.addLabelToSample( sampleName, "from", "individual---vesel", "AvgVivo---AvgVitro") self.outputExperimentFabsSingle.write( self._getPath("experimentFabsSingle.pkpd")) def createOutputStep(self): self._defineOutputs( outputExperimentFabsSingle=self.outputExperimentFabsSingle) for ptrExperiment in self.inputIVIVCs: self._defineSourceRelation(ptrExperiment.get(), self.outputExperimentFabsSingle) def _validate(self): retval = [] for ptrExperiment in self.inputIVIVCs: if not "experimentFabs" in ptrExperiment.get().fnPKPD.get(): retval.append("You can only take Fabs files") return retval def _summary(self): return []
def calculateAllIvIvC(self): L1 = [] L2 = [] L3 = [] L4 = [] L5 = [] for ptrExperiment in self.inputIVIVCs: experiment = PKPDExperiment() experiment.load(ptrExperiment.get().fnPKPD.get()) x, y = experiment.getXYMeanValues("tvivo", "tvitroReinterpolated") L1.append((x, y)) x, y = experiment.getXYMeanValues("tvivo", "Fabs") L2.append((x, y)) x, y = experiment.getXYMeanValues("AdissolReinterpolated", "FabsPredicted") L3.append((x, y)) x, y = experiment.getXYMeanValues("FabsPredicted", "Fabs") L4.append((x, y)) x, y = experiment.getXYMeanValues("tvitroReinterpolated", "AdissolReinterpolated") L5.append((x, y)) tvivo1, tvitroReinterpolatedY = computeXYmean(L1, common=True) tvivoOrig, FabsOrig = computeXYmean(L2, common=True) AdissolReinterpolatedX, FabsPredictedY = computeXYmean(L3, common=True) FabsPredictedX, Fabs = computeXYmean(L4, common=True) tvitroReinterpolatedX, AdissolReinterpolatedY = computeXYmean( L5, common=True) x, y = twoWayUniqueFloatValues(tvivo1, tvitroReinterpolatedY) Bt = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(tvitroReinterpolatedX, AdissolReinterpolatedY) BtA = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(tvivoOrig, FabsOrig) BtF = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(AdissolReinterpolatedX, FabsPredictedY) BAF = InterpolatedUnivariateSpline(x, y, k=1) x, y = twoWayUniqueFloatValues(FabsPredictedX, Fabs) BFF = InterpolatedUnivariateSpline(x, y, k=1) vtvitroReinterpolated = np.zeros(len(tvivo1)) vAdissolReinterpolated = np.zeros(len(tvivo1)) vFabs = np.zeros(len(tvivo1)) vFabsPredicted = np.zeros(len(tvivo1)) vFabsOrig = np.zeros(len(tvivo1)) for i in range(len(tvivo1)): tvivoi = tvivo1[i] vtvitroReinterpolated[i] = Bt(tvivoi) vAdissolReinterpolated[i] = BtA(vtvitroReinterpolated[i]) vFabsPredicted[i] = BAF(vAdissolReinterpolated[i]) vFabs[i] = BFF(vFabsPredicted[i]) vFabsOrig[i] = BtF(tvivoi) tvitroReinterpolatedVar = experiment.variables["tvitroReinterpolated"] AdissolReinterpolatedVar = experiment.variables[ "AdissolReinterpolated"] tvivoVar = experiment.variables["tvivo"] FabsOrigVar = copy.copy(experiment.variables["Fabs"]) FabsOrigVar.varName = "FabsOriginal" FabsVar = experiment.variables["Fabs"] FabsVar.comment += ". After IVIVC: tvivo->tvitro->Adissol->Fabs " FabsPredictedVar = experiment.variables["FabsPredicted"] self.outputExperimentFabsSingle = PKPDExperiment() self.outputExperimentFabsSingle.variables[ tvitroReinterpolatedVar.varName] = tvitroReinterpolatedVar self.outputExperimentFabsSingle.variables[ AdissolReinterpolatedVar.varName] = AdissolReinterpolatedVar self.outputExperimentFabsSingle.variables[tvivoVar.varName] = tvivoVar self.outputExperimentFabsSingle.variables[FabsVar.varName] = FabsVar self.outputExperimentFabsSingle.variables[ FabsPredictedVar.varName] = FabsPredictedVar self.outputExperimentFabsSingle.variables[ FabsOrigVar.varName] = FabsOrigVar self.outputExperimentFabsSingle.general[ "title"] = "In-vitro In-vivo correlation" self.outputExperimentFabsSingle.general[ "comment"] = "Fabs vs Predicted Fabs" sampleName = "jointIVIVC" newSampleFabsSingle = PKPDSample() newSampleFabsSingle.sampleName = sampleName newSampleFabsSingle.variableDictPtr = self.outputExperimentFabsSingle.variables newSampleFabsSingle.descriptors = {} newSampleFabsSingle.addMeasurementColumn("tvitroReinterpolated", vtvitroReinterpolated) newSampleFabsSingle.addMeasurementColumn("AdissolReinterpolated", vAdissolReinterpolated) newSampleFabsSingle.addMeasurementColumn("tvivo", tvivo1) newSampleFabsSingle.addMeasurementColumn("FabsPredicted", vFabsPredicted) newSampleFabsSingle.addMeasurementColumn("Fabs", vFabs) newSampleFabsSingle.addMeasurementColumn("FabsOriginal", vFabsOrig) self.outputExperimentFabsSingle.samples[ sampleName] = newSampleFabsSingle self.outputExperimentFabsSingle.addLabelToSample( sampleName, "from", "individual---vesel", "AvgVivo---AvgVitro") self.outputExperimentFabsSingle.write( self._getPath("experimentFabsSingle.pkpd"))
class ProtPKPDDeconvolve(ProtPKPDODEBase): """ Deconvolve the drug dissolution from a compartmental model.""" _label = 'dissol deconv' BIOAVAIL_NONE = 0 BIOAVAIL_MULT = 1 BIOAVAIL_DIV = 2 #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam('inputODE', params.PointerParam, label="Input ODE model", pointerClass='ProtPKPDMonoCompartment, ProtPKPDTwoCompartments,ProtPKPDODERefine,'\ ' ProtPKPDTwoCompartmentsClint, ProtPKPDTwoCompartmentsClintCl', help='Select a run of an ODE model') form.addParam('normalize', params.BooleanParam, label="Normalize by dose", default=True, help='Normalize the output by the input dose, so that a total absorption is represented by 100.') form.addParam('considerBioaval', params.EnumParam, label="Consider bioavailability", default=self.BIOAVAIL_NONE, choices=['Do not correct','Multiply deconvolution by bioavailability','Divide deconvolution by bioavailability'], help='Take into account the bioavailability') form.addParam('saturate', params.BooleanParam, label="Saturate at 100%", default=True, condition='normalize', help='Saturate the absorption so that there cannot be values beyond 100') form.addParam('removeTlag', params.BooleanParam, label="Remove tlag effect", default=True, help='If set to True, then the deconvolution is performed ignoring the the tlag in the absorption.' 'This homogeneizes the different responses.') #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('deconvolve',self.inputODE.get().getObjId()) self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def addSample(self, sampleName, t, y): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.descriptors = {} newSample.addMeasurementPattern(["A"]) tUnique, yUnique = twoWayUniqueFloatValues(t,y) newSample.addMeasurementColumn("t", tUnique) newSample.addMeasurementColumn("A",yUnique) self.outputExperiment.samples[sampleName] = newSample def deconvolve(self, objId): self.protODE = self.inputODE.get() self.experiment = self.readExperiment(self.protODE.outputExperiment.fnPKPD) self.fitting = self.readFitting(self.protODE.outputFitting.fnFitting) self.varNameX = self.fitting.predictor.varName self.varNameY = self.fitting.predicted.varName # Create drug source self.clearGroupParameters() self.createDrugSource() # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Avar = PKPDVariable() Avar.varName = "A" Avar.varType = PKPDVariable.TYPE_NUMERIC Avar.role = PKPDVariable.ROLE_MEASUREMENT if self.normalize.get(): Avar.units = createUnit("none") else: Avar.units = createUnit(self.experiment.getDoseUnits()) self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Avar.varName] = Avar self.outputExperiment.general["title"]="Deconvolution of the amount released" self.outputExperiment.general["comment"]="Amount released at any time t" # Simulate the different responses timeRange = self.experiment.getRange(self.varNameX) deltaT = 0.5 t = np.arange(0.0,timeRange[1],deltaT) for sampleName, sample in self.experiment.samples.items(): self.printSection("Deconvolving "+sampleName) sample.interpretDose() drugSource = DrugSource() drugSource.setDoses(sample.parsedDoseList, 0.0, timeRange[1]) p=[] tlag=0 for paramName in drugSource.getParameterNames(): p.append(float(sample.getDescriptorValue(paramName))) if paramName.endswith('_tlag') and self.removeTlag.get(): tlag=float(sample.getDescriptorValue(paramName)) drugSource.setParameters(p) cumulatedDose=0.0 A=t*0.0 # Allocate memory totalReleased = drugSource.getAmountReleasedUpTo(10*t[-1]) print("t(min) A(%s)"%Avar.units._toString()) for i in range(t.size): cumulatedDose+=drugSource.getAmountReleasedAt(t[i],deltaT) A[i]=cumulatedDose if self.normalize.get(): A[i] *= 100.0/totalReleased print("%f %f"%(t[i],A[i])) # print("%f %f %f %f"%(t[i], A[i], drugSource.getAmountReleasedAt(t[i], 0.5), drugSource.getAmountReleasedUpTo(t[i] + 0.5))) if self.saturate.get() and self.normalize.get(): A = np.clip(A,None,100.0) if self.considerBioaval.get()==self.BIOAVAIL_DIV: A /= sample.getBioavailability() elif self.considerBioaval.get()==self.BIOAVAIL_MULT: A *= sample.getBioavailability() self.addSample(sampleName,t-tlag,A) self.outputExperiment.write(self._getPath("experiment.pkpd")) def createOutputStep(self): self._defineOutputs(outputExperiment=self.outputExperiment) self._defineSourceRelation(self.inputODE.get(), self.outputExperiment) def _validate(self): return [] def _summary(self): return []
class ProtPKPDDeconvolutionLooRiegelmanInverse(ProtPKPD): """ Given a profile of amount absorbed, find the central and peripheral concentrations that gave raise to it. This is an inverse Loo-Riegelman problem. The parameters of this protocol are defined as microconstants. Remind that k10=Cl*V, k12=Clp*V, k21=Clp*Vp """ # Reference: Humbert, H., Cabiac, M.D., Bosshardt, H. In vitro-in vivo correlation of a modified-release oral # form of ketotifen: in vitro dissolution rate specification. J. Pharm Sci 1994, 83, 131-136 _label = 'inverse Loo-Riegelman' #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam('inputExperiment', params.PointerParam, label="In-vivo profiles", pointerClass='PKPDExperiment', help='It should have the amount absorbed') form.addParam('timeVar', params.StringParam, label="Time variable", default="t", help='Which variable contains the time stamps.') form.addParam('amountVar', params.StringParam, label="Absorbed amount variable", default="A", help='Which variable contains the amount absorbed.') form.addParam('resampleT', params.FloatParam, label="Resample profiles (time step)", default=0.1, help='Resample the input profiles at this time step (make sure it is in the same units as the input). ' 'Leave it to -1 for no resampling') form.addParam('k10', params.FloatParam, label="Elimination rate (k10)", help='Units t^-1') form.addParam('k12', params.FloatParam, label="Rate from central to peripheral (k12)", help='Units t^-1') form.addParam('k21', params.FloatParam, label="Rate from peripheral to central (k21)", help='Units t^-1') form.addParam('V', params.FloatParam, label="Central volume (V) [L]") form.addParam('Vp', params.FloatParam, label="Peripheral volume (Vp) [L]") #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('solve',self.inputExperiment.get().getObjId()) self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def addSample(self, sampleName, t, C, Cp): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.descriptors = {} newSample.addMeasurementPattern(["C","Cp"]) newSample.addMeasurementColumn("t", t) newSample.addMeasurementColumn("C", C) newSample.addMeasurementColumn("Cp", Cp) self.outputExperiment.samples[sampleName] = newSample def calculateConcentrations(self,t,A): k10 = float(self.k10.get()) k12 = float(self.k12.get()) k21 = float(self.k21.get()) V = float(self.V.get()) Vp = float(self.Vp.get()) C = np.zeros(t.shape) Cp = np.zeros(t.shape) AUC0t = np.zeros(t.shape) for n in range(1,C.size): DeltaA=np.abs(A[n]-A[n-1]) DeltaT=t[n]-t[n-1] DeltaT2=DeltaT/2 K1 = np.exp(-k21 * DeltaT) K2 = k10/(1+k12*DeltaT2+k10*DeltaT2) C[n] = DeltaA/V - Vp*Cp[n-1]/V*K1 + C[n-1]*k12*DeltaT2-C[n-1]*k12/k21*(1-K1)\ -C[n-1]*k10*DeltaT2-AUC0t[n-1]*K2 DeltaC = C[n]-C[n-1] # Update AUC0t if DeltaC>0: # Trapezoidal in the raise AUC0t[n] = AUC0t[n-1] + DeltaT/2 * (C[n - 1] + C[n]) else: # Log-trapezoidal in the decay if C[n-1] > 0 and C[n] > 0: decrement = C[n-1] / C[n] K = math.log(decrement) AUC0t[n] = AUC0t[n - 1] + DeltaT * (C[n-1] - C[n]) / K else: AUC0t[n] = AUC0t[n - 1] Cp[n] = Cp[n-1]*K1+k12/k21*C[n-1]*(1-K1)+k12*DeltaC*DeltaT2 if C[n]<0.0: C[n]=0.0 if Cp[n]<0.0: Cp[n]=0.0 return C, Cp def calculateConcentrations2(self,t,A): k10 = float(self.k10.get()) k12 = float(self.k12.get()) k21 = float(self.k21.get()) V = float(self.V.get()) Vp = float(self.Vp.get()) C = np.zeros(t.shape) Cp = np.zeros(t.shape) # Clp = k12*V for n in range(1,C.size): DeltaA=np.abs(A[n]-A[n-1]) DeltaT=t[n]-t[n-1] # Q12 = Clp*(C[n-1]-Cp[n-1]) # C[n]=C[n-1]+(-Cl*C[n-1]/V-Q12/V)*DeltaT+DeltaA/V # Cp[n]=Cp[n-1]+Q12/Vp*DeltaT # Q12 = Clp*(C[n-1]-Cp[n-1]) # C[n]=C[n-1]-k10*C[n-1]*DeltaT-Q12/V*DeltaT+DeltaA/V # Cp[n]=Cp[n-1]+Q12/Vp*DeltaT # C[n]=C[n-1]-k10*C[n-1]*DeltaT-(Clp*(C[n-1]-Cp[n-1]))/V*DeltaT+DeltaA/V # Cp[n]=Cp[n-1]+(Clp*(C[n-1]-Cp[n-1]))/Vp*DeltaT # C[n]=C[n-1]-k10*C[n-1]*DeltaT-Clp/V*C[n-1]*DeltaT+Clp/V*Cp[n-1]*DeltaT+DeltaA/V # Cp[n]=Cp[n-1]+Clp/Vp*C[n-1]*DeltaT-Clp/Vp*Cp[n-1]*DeltaT C[n]=C[n-1]-k10*C[n-1]*DeltaT-k12*C[n-1]*DeltaT+k21*Vp/V*Cp[n-1]*DeltaT+DeltaA/V Cp[n]=Cp[n-1]+k12*V/Vp*C[n-1]*DeltaT-k21*Cp[n-1]*DeltaT if C[n]<0.0: C[n]=0.0 if Cp[n]<0.0: Cp[n]=0.0 return C, Cp def solve(self, objId1): self.experiment = self.readExperiment(self.inputExperiment.get().fnPKPD) # Create output object self.outputExperiment = None timeRange = self.experiment.getRange(self.timeVar.get()) for sampleName, sample in self.experiment.samples.items(): # Get t, A t=np.asarray(sample.getValues(self.timeVar.get()),dtype=np.float64) A=np.asarray(sample.getValues(self.amountVar.get()),dtype=np.float64) if t[0]>0: t=np.insert(t,0,0) # Add (0,0) to the profile A=np.insert(A,0,0) t, A = uniqueFloatValues(t, A) if self.resampleT.get()>0: B = InterpolatedUnivariateSpline(t, A, k=1) t = np.arange(np.min(t),np.max(t)+self.resampleT.get(),self.resampleT.get()) A = B(t) # Find C and Cp C, Cp = self.calculateConcentrations2(t,A) if self.outputExperiment is None: self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Cvar = PKPDVariable() Cvar.varName = "C" Cvar.varType = PKPDVariable.TYPE_NUMERIC Cvar.role = PKPDVariable.ROLE_MEASUREMENT Lunits = createUnit("L") Cvar.units = createUnit(divideUnits(self.experiment.getVarUnits(self.amountVar.get()),Lunits.unit)) Cvar.comment = "Concentration central compartment" Cpvar = PKPDVariable() Cpvar.varName = "Cp" Cpvar.varType = PKPDVariable.TYPE_NUMERIC Cpvar.role = PKPDVariable.ROLE_MEASUREMENT Cpvar.units = createUnit(divideUnits(self.experiment.getVarUnits(self.amountVar.get()),Lunits.unit)) Cpvar.comment = "Concentration peripheral compartment" self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Cvar.varName] = Cvar self.outputExperiment.variables[Cpvar.varName] = Cpvar self.outputExperiment.general["title"]="Inverse Loo-Riegelman" self.outputExperiment.general["comment"]="" self.addSample(sampleName,t,C,Cp) self.outputExperiment.write(self._getPath("experiment.pkpd")) def createOutputStep(self): self._defineOutputs(outputExperiment=self.outputExperiment) self._defineSourceRelation(self.inputExperiment.get(), self.outputExperiment) def _validate(self): return [] def _summary(self): retval = [] return retval
def deconvolve(self, objId): self.protODE = self.inputODE.get() self.experiment = self.readExperiment(self.protODE.outputExperiment.fnPKPD) self.fitting = self.readFitting(self.protODE.outputFitting.fnFitting) self.varNameX = self.fitting.predictor.varName self.varNameY = self.fitting.predicted.varName # Create drug source self.clearGroupParameters() self.createDrugSource() # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Avar = PKPDVariable() Avar.varName = "A" Avar.varType = PKPDVariable.TYPE_NUMERIC Avar.role = PKPDVariable.ROLE_MEASUREMENT if self.normalize.get(): Avar.units = createUnit("none") else: Avar.units = createUnit(self.experiment.getDoseUnits()) self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Avar.varName] = Avar self.outputExperiment.general["title"]="Deconvolution of the amount released" self.outputExperiment.general["comment"]="Amount released at any time t" # Simulate the different responses timeRange = self.experiment.getRange(self.varNameX) deltaT = 0.5 t = np.arange(0.0,timeRange[1],deltaT) for sampleName, sample in self.experiment.samples.items(): self.printSection("Deconvolving "+sampleName) sample.interpretDose() drugSource = DrugSource() drugSource.setDoses(sample.parsedDoseList, 0.0, timeRange[1]) p=[] tlag=0 for paramName in drugSource.getParameterNames(): p.append(float(sample.getDescriptorValue(paramName))) if paramName.endswith('_tlag') and self.removeTlag.get(): tlag=float(sample.getDescriptorValue(paramName)) drugSource.setParameters(p) cumulatedDose=0.0 A=t*0.0 # Allocate memory totalReleased = drugSource.getAmountReleasedUpTo(10*t[-1]) print("t(min) A(%s)"%Avar.units._toString()) for i in range(t.size): cumulatedDose+=drugSource.getAmountReleasedAt(t[i],deltaT) A[i]=cumulatedDose if self.normalize.get(): A[i] *= 100.0/totalReleased print("%f %f"%(t[i],A[i])) # print("%f %f %f %f"%(t[i], A[i], drugSource.getAmountReleasedAt(t[i], 0.5), drugSource.getAmountReleasedUpTo(t[i] + 0.5))) if self.saturate.get() and self.normalize.get(): A = np.clip(A,None,100.0) if self.considerBioaval.get()==self.BIOAVAIL_DIV: A /= sample.getBioavailability() elif self.considerBioaval.get()==self.BIOAVAIL_MULT: A *= sample.getBioavailability() self.addSample(sampleName,t-tlag,A) self.outputExperiment.write(self._getPath("experiment.pkpd"))
class ProtPKPDDeconvolutionLooRiegelman(ProtPKPD): """ Calculate the absorption profile of an in vivo concentration profile using the Loo-Riegelman approach. This is only valid for profiles that have been modelled with a two-compartments PK model. The formula is Fabs(t)=(Cp(t)+Cperipheral(t)+K10*AUC0t(t))/(K10*AUC0inf) where K10=Cl/V and Cperipheral(t_n)=k12*Delta Cp*Delta t/2+k12/k21 * Cp(t_n-1)(1-exp(-k21*Delta t))+Cperipheral(t_n-1)*exp(-k21*Delta t) In this implementation it is assumed that AUC0inf is the last AUC0t observed, meaning that Cp(t) has almost vanished in the last samples. This protocol is much more accurate when the input Cp(t) is reinterpolated to a small time step like 0.5 minutes. Reference: Leon Shargel, Susanna Wu-Pong, Andrew B.C. Yu. Applied Biopharmaceutics & Pharmacokinetics, 6e. McGraw Hill, 1999. Chap. 7""" _label = 'deconvolution Loo-Riegelman' SAME_INPUT = 0 ANOTHER_INPUT = 1 BIOAVAIL_NONE = 0 BIOAVAIL_MULT = 1 BIOAVAIL_DIV = 2 #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam( 'inputExperiment', params.PointerParam, label="In-vivo profiles", pointerClass='PKPDExperiment', help= 'Make sure that it has a clearance parameter (Cl) and central volume (V)' ) form.addParam( 'externalIV', params.EnumParam, choices=[ 'Get impulse response from the same input fit', 'Get impulse response from another fit' ], label='Impulse response source', default=self.SAME_INPUT, help= "The impulse response is an estimate of the intravenous response") form.addParam('externalIVODE', params.PointerParam, label="External impulse response ODE model", condition='externalIV==1', pointerClass='ProtPKPDMonoCompartment, ProtPKPDTwoCompartments,ProtPKPDODERefine,' \ ' ProtPKPDTwoCompartmentsClint, ProtPKPDTwoCompartmentsClintCl', help='Select a run of an ODE model. It should be ideally the intravenous response.') form.addParam('timeVar', params.StringParam, label="Time variable", default="t", help='Which variable contains the time stamps.') form.addParam('concVar', params.StringParam, label="Concentration variable", default="Cp", help='Which variable contains the plasma concentration.') form.addParam( 'normalize', params.BooleanParam, label="Normalize by dose", default=True, help= 'Normalize the output by AUC0inf, so that a total absorption is represented by 100.' ) form.addParam( 'saturate', params.BooleanParam, label="Saturate at 100%", default=True, help= 'Saturate the absorption so that there cannot be values beyond 100' ) form.addParam('considerBioaval', params.EnumParam, label="Consider bioavailability", default=self.BIOAVAIL_NONE, choices=[ 'Do not correct', 'Multiply deconvolution by bioavailability', 'Divide deconvolution by bioavailability' ], help='Take into account the bioavailability') form.addParam( 'resampleT', params.FloatParam, label="Resample profiles (time step)", default=0.5, help= 'Resample the input profiles at this time step (make sure it is in the same units as the input). ' 'Leave it to -1 for no resampling') form.addParam( 'smooth', params.BooleanParam, label="Monotonic smooth", default=True, help= 'Apply a Pchip interpolation to make sure that the Adissolved is monotonically increasing' ) #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('deconvolve', self.inputExperiment.get().getObjId()) self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def addSample(self, sampleName, t, y): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.descriptors = {} newSample.addMeasurementPattern(["A"]) newSample.addMeasurementColumn("t", t) newSample.addMeasurementColumn("A", y) self.outputExperiment.samples[sampleName] = newSample def calculateCperipheral(self, t, Cp, k12, k21): Cperipheral = np.zeros(t.shape) for n in range(1, Cperipheral.size): DeltaCp = np.abs(Cp[n] - Cp[n - 1]) DeltaT = t[n] - t[n - 1] Cperipheral[n] = k12*DeltaCp*DeltaT*0.5 + \ k12 / k21 * Cp[n-1]*(1 - np.exp(-k21 * DeltaT)) + \ Cperipheral[n-1] * np.exp(-k21 * DeltaT) if Cperipheral[n] < 0.0: Cperipheral[n] = 0.0 return Cperipheral def deconvolve(self, objId1): self.experiment = self.readExperiment( self.inputExperiment.get().fnPKPD) # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Avar = PKPDVariable() Avar.varName = "A" Avar.varType = PKPDVariable.TYPE_NUMERIC Avar.role = PKPDVariable.ROLE_MEASUREMENT Avar.units = createUnit("none") self.outputExperiment.variables[tvar.varName] = tvar self.outputExperiment.variables[Avar.varName] = Avar self.outputExperiment.general[ "title"] = "Deconvolution of the amount released" self.outputExperiment.general[ "comment"] = "Amount released at any time t" # Get the input sample from another experiment if necessary sampleFrom = None if self.externalIV.get() == self.ANOTHER_INPUT: anotherExperiment = self.readExperiment( self.externalIVODE.get().outputExperiment.fnPKPD) for _, sampleFrom in anotherExperiment.samples.items( ): # Take the first sample from the reference break timeRange = self.experiment.getRange(self.timeVar.get()) for sampleName, sample in self.experiment.samples.items(): # Get t, Cp t = np.asarray(sample.getValues(self.timeVar.get()), dtype=np.float64) Cp = np.asarray(sample.getValues(self.concVar.get()), dtype=np.float64) Cp = np.clip(Cp, 0.0, None) t = np.insert(t, 0, 0) # Add (0,0) to the profile Cp = np.insert(Cp, 0, 0) t, Cp = uniqueFloatValues(t, Cp) if self.resampleT.get() > 0: B = InterpolatedUnivariateSpline(t, Cp, k=1) t = np.arange(np.min(t), np.max(t) + self.resampleT.get(), self.resampleT.get()) Cp = B(t) # Calculate AUC0t AUC0t = calculateAUC0t(t, Cp) AUC0inf = float(AUC0t[-1]) # Calculate peripheral if self.externalIV.get() == self.SAME_INPUT: sampleFrom = sample Cl = float(sampleFrom.descriptors['Cl']) V = float(sampleFrom.descriptors['V']) Clp = float(sampleFrom.descriptors['Clp']) Vp = float(sampleFrom.descriptors['Vp']) k12 = Clp / V k21 = Clp / Vp Cperipheral = self.calculateCperipheral(t, Cp, k12, k21) # Deconvolve k10 = Cl / V A = (Cp + Cperipheral + k10 * AUC0t) / k10 if self.normalize.get(): A *= 100 / AUC0inf if self.saturate.get(): A = np.clip(A, None, 100.0) A = np.clip(A, 0, None) if self.smooth: if t[0] > 0: t = np.insert(t, 0, 0) A = np.insert(A, 0, 0) if self.saturate.get() and self.normalize.get(): A = np.clip(A, None, 100.0) A = np.clip(smoothPchip(t, A), 0, None) if self.considerBioaval.get() == self.BIOAVAIL_DIV: A /= sample.getBioavailability() elif self.considerBioaval.get() == self.BIOAVAIL_MULT: A *= sample.getBioavailability() self.addSample(sampleName, t, A) self.outputExperiment.write(self._getPath("experiment.pkpd")) def createOutputStep(self): self._defineOutputs(outputExperiment=self.outputExperiment) self._defineSourceRelation(self.inputExperiment.get(), self.outputExperiment) def _validate(self): return [] def _summary(self): retval = [] return retval
def runSimulate(self): # Take first experiment self.protODE = self.inputODEs[0].get() if hasattr(self.protODE, "outputExperiment"): self.experiment = self.readExperiment( self.protODE.outputExperiment.fnPKPD, show=False) elif hasattr(self.protODE, "outputExperiment1"): self.experiment = self.readExperiment( self.protODE.outputExperiment1.fnPKPD, show=False) else: raise Exception("Cannot find an outputExperiment in the input ODE") if hasattr(self.protODE, "outputFitting"): self.fitting = self.readFitting( self.protODE.outputFitting.fnFitting, show=False) elif hasattr(self.protODE, "outputFitting1"): self.fitting = self.readFitting( self.protODE.outputFitting1.fnFitting, show=False) self.varNameX = self.fitting.predictor.varName if type(self.fitting.predicted) != list: self.varNameY = self.fitting.predicted.varName else: self.varNameY = [var.varName for var in self.fitting.predicted] # Create output object self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.experiment.getTimeUnits().unit) Nsamples = int( math.ceil((self.tF.get() - self.t0.get()) / self.deltaT.get())) + 1 if tvar.units == PKPDUnit.UNIT_TIME_MIN: Nsamples *= 60 self.outputExperiment.variables[self.varNameX] = tvar if type(self.fitting.predicted) != list: self.outputExperiment.variables[ self.varNameY] = self.experiment.variables[self.varNameY] else: for varName in self.varNameY: self.outputExperiment.variables[ varName] = self.experiment.variables[varName] self.outputExperiment.general["title"] = "Simulated ODE response" self.outputExperiment.general["comment"] = "Simulated ODE response" self.outputExperiment.vias = self.experiment.vias # Read the doses doseLines = [] for line in self.doses.get().replace('\n', ';;').split(';;'): doseLines.append(line) doseIdx = 0 simulationsY = None doseList = [] for protODEPtr in self.inputODEs: self.protODE = protODEPtr.get() if hasattr(self.protODE, "outputExperiment"): self.experiment = self.readExperiment( self.protODE.outputExperiment.fnPKPD, show=False) elif hasattr(self.protODE, "outputExperiment1"): self.experiment = self.readExperiment( self.protODE.outputExperiment1.fnPKPD, show=False) else: raise Exception( "Cannot find an outputExperiment in the input ODE") if hasattr(self.protODE, "outputFitting"): self.fitting = self.readFitting( self.protODE.outputFitting.fnFitting, show=False) elif hasattr(self.protODE, "outputFitting1"): self.fitting = self.readFitting( self.protODE.outputFitting1.fnFitting, show=False) for viaName in self.experiment.vias: if not viaName in self.outputExperiment.vias: self.outputExperiment.vias[viaName] = copy.copy( self.experiment.vias[viaName]) # Create drug source self.clearGroupParameters() self.createDrugSource() # Setup model self.model = self.protODE.createModel() self.model.setExperiment(self.outputExperiment) self.model.deltaT = self.deltaT.get() self.model.setXVar(self.varNameX) self.model.setYVar(self.varNameY) self.model.x = [ self.t0.get() + i * self.model.deltaT for i in range(0, Nsamples) ] self.modelList.append(self.model) tokens = doseLines[doseIdx].split(';') if len(tokens) < 5: print("Skipping dose: ", line) continue dosename = tokens[0].strip() self.outputExperiment.doses[dosename] = PKPDDose() self.outputExperiment.doses[dosename].parseTokens( tokens, self.outputExperiment.vias) doseList.append(dosename) auxSample = PKPDSample() auxSample.descriptors = {} auxSample.doseDictPtr = self.outputExperiment.doses auxSample.variableDictPtr = self.outputExperiment.variables auxSample.doseList = [dosename] auxSample.interpretDose() self.drugSource.setDoses(auxSample.parsedDoseList, self.t0.get() - 10, self.tF.get() + 10) self.model.drugSource = self.drugSource # Simulate the different responses simulationsX = self.model.x self.setTimeRange(None) parameters = self.fitting.sampleFits[0].parameters print("Input model: %s" % self.protODE.getObjLabel()) print("Sample name: %s" % self.fitting.sampleFits[0].sampleName) print("Parameters: ", parameters) print("Dose: %s" % doseLines[doseIdx]) print(" ") # Prepare source and this object self.protODE.configureSource(self.drugSource) parameterNames = self.getParameterNames( ) # Necessary to count the number of source and PK parameters # Prepare the model y = self.forwardModel(parameters, [simulationsX] * self.getResponseDimension()) # Keep results if simulationsY is None: simulationsY = copy.copy(y) else: for j in range(self.getResponseDimension()): simulationsY[j] += y[j] doseIdx += 1 self.addSample("Simulation", doseList, simulationsX, simulationsY[0]) self.outputExperiment.write(self._getPath("experiment.pkpd"))