class ProtPKPDDissolutionPKSimulation(ProtPKPD): """ This protocol simulates the pharmacokinetic response of an ODE model when it is given a single dose of an drug whose release is modelled by an in vitro fitting and an in vitro-in vivo correlation.""" _label = 'simulate PK response' #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam( 'inputInVitro', params.PointerParam, label="Dissolution profiles in vitro", pointerClass='PKPDFitting', help='Select a fitting with dissolution profiles. ' 'It is assumed that the input dissolution profile is a percentage, between 0 and 100' ) form.addParam( 'inputPK', params.PointerParam, label="Pharmacokinetic model", pointerClass='PKPDFitting', help='Select the PK model to be simulated with this input') form.addParam( 'usePKExperiment', params.BooleanParam, label="Use experiment from PK fitting", default=True, help='If True, the PK parameters are taken from the same fitting. ' 'If False, they are taken from another experiment') form.addParam( 'inputPKOtherExperiment', params.PointerParam, label="Experiment with PK parameters", pointerClass='PKPDExperiment', condition='not usePKExperiment', help= 'The experiment must have all the PK parameters specified by the PK model' ) form.addParam( 'ignorePKbioavailability', params.BooleanParam, default=False, label='Ignore PK bioavailability', help= 'Ignore the bioavailability from the PK if it has been considered in the IVIVC' ) form.addParam( 'conversionType', params.EnumParam, label='Time/Response scaling', choices=['IVIVC', 'Levy plot', 'None'], default=0, help= 'To convert the dissolution profile into an absorption profile you may use an IVIVC (Fabs output) or a Levy plot. ' 'The Levy plot can better represent what is happening in reality with patients.' ) form.addParam( 'inputIvIvC', params.PointerParam, label="In vitro-In vivo correlation", condition='conversionType==0', pointerClass='PKPDExperiment', help='Select the Fabs output of an in vitro-in vivo correlation') form.addParam('inputLevy', params.PointerParam, label="Levy plot", condition='conversionType==1', pointerClass='PKPDExperiment', help='Select the output of a Levy plot protocol') form.addParam('inputDose', params.FloatParam, label="Dose", default=1, help='Make sure that it is in the same units as the ones at which the PK was estimated. '\ 'This dose will be given simpy once (single dose).') form.addParam( 'includeTlag', params.BooleanParam, label="Include PK tlag", default=True, help= 'If you include the tlag (if available), the simulations will be done with the same PK tlag as ' 'the input PK population. If not, tlag will be set to 0.') form.addParam( 'allCombinations', params.BooleanParam, label="All combinations of dissolutions/PK", default=False, help= 'If set to True, then all combinations of dissolutions and PK profiles are tested. ' 'Otherwise, only a random subset is chosen') form.addParam('inputN', params.IntParam, label="Number of simulations", default=100, condition='not allCombinations') form.addParam('t0', params.FloatParam, label="Initial time (h)", default=0) form.addParam('tF', params.FloatParam, label="Final time (h)", default=48) form.addParam('addIndividuals', params.BooleanParam, label="Add individual simulations", default=True, expertLevel=LEVEL_ADVANCED, help="Individual simulations are added to the output") form.addParam( 'NCAt0', params.StringParam, label="NCA Initial time (h)", default="", help= "The non-compartimental analysis is performed within NCA t0 and NCA tF. Leave empty for the whole period" ) form.addParam( 'NCAtF', params.StringParam, label="NCA Final time (h)", default="", help= "The non-compartimental analysis is performed within NCA t0 and NCA tF. Leave empty for the whole period" ) #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('simulate', self.inputInVitro.get().getObjId(), self.inputPK.get().getObjId(), self.inputDose.get(), self.inputN.get()) self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def getInVitroModels(self): fnFitting = self.inputInVitro.get().fnFitting cls = "PKPDSampleFitBootstrap" if fnFitting.get().find( "bootstrap") != -1 else "" self.fittingInVitro = PKPDFitting(cls) self.fittingInVitro.load(fnFitting) self.invitroClsName = self.fittingInVitro.modelDescription.split( '(')[1].split(')')[0] klass = globals()[self.invitroClsName] self.dissolutionModel = klass() self.dissolutionModel.allowTlag = "tlag" in self.fittingInVitro.modelParameters self.dissolutionPopulation = cls != "" def getScaling(self): self.allTimeScalings = {} self.allResponseScalings = {} if self.conversionType.get() == 0: experiment = self.readExperiment(self.inputIvIvC.get().fnPKPD, show=False) elif self.conversionType.get() == 1: experiment = self.readExperiment(self.inputLevy.get().fnPKPD, show=False) elif self.conversionType.get() == 2: experiment = self.readExperiment( self.inputInVitro.get().fnExperiment, show=False) tvar = experiment.getTimeVariable() for sampleName, sample in experiment.samples.items(): if self.conversionType.get() == 0: vivo = sample.getValues("tvivo") vitro = sample.getValues("tvitroReinterpolated") elif self.conversionType.get() == 1: vivo = sample.getValues("tvivo") vitro = sample.getValues("tvitro") elif self.conversionType.get() == 2: vivo = sample.getValues(tvar) vitro = sample.getValues(tvar) if self.conversionType.get() != 2: fromSample = sample.getDescriptorValue("from") fromIndividual, _ = fromSample.split("---") else: fromSample = sample.sampleName fromIndividual = sample.sampleName if not fromIndividual in self.allTimeScalings.keys(): self.allTimeScalings[fromIndividual] = [] self.allTimeScalings[fromIndividual].append( (np.asarray(vitro, dtype=np.float64), np.asarray(vivo, dtype=np.float64))) if self.conversionType.get() == 0: vivo = sample.getValues("FabsPredicted") vitro = sample.getValues("AdissolReinterpolated") if not fromIndividual in self.allResponseScalings.keys(): self.allResponseScalings[fromIndividual] = [] self.allResponseScalings[fromIndividual].append( (np.asarray(vitro, dtype=np.float64), np.asarray(vivo, dtype=np.float64))) def getPKModels(self): fnFitting = self.inputPK.get().fnFitting cls = "PKPDSampleFitBootstrap" if fnFitting.get().find( "bootstrap") != -1 else "" self.fittingPK = PKPDFitting(cls) self.fittingPK.load(fnFitting) modelDescription = self.fittingPK.modelDescription.split(';')[ 1] # Before ; there is the drug source description self.pkClsName = modelDescription.split('(')[1].split(')')[0] klass = globals()[self.pkClsName] self.pkModel = klass() self.pkModel.t0 = self.t0.get() self.pkModel.tF = self.tF.get() self.timeUnits = self.fittingPK.getTimeUnits().unit if self.timeUnits == PKPDUnit.UNIT_TIME_MIN: self.pkModel.t0 *= 60 self.pkModel.tF *= 60 self.pkModel.drugSource = DrugSource() dose = createDeltaDose(self.inputDose.get(), via=createVia("Oral; numerical")) self.pkModel.drugSource.setDoses([dose], self.pkModel.t0, self.pkModel.tF) self.pkPopulation = cls != "" self.pkNParams = self.pkModel.getNumberOfParameters() self.tlagIdx = None if self.includeTlag.get(): i = 0 for prmName in self.fittingPK.modelParameters: if prmName.endswith('_tlag'): self.tlagIdx = i print("Found tlag in %s at position %d" % (prmName, i)) break i += 1 self.bioavailabilityIdx = None if not self.ignorePKbioavailability.get(): i = 0 for prmName in self.fittingPK.modelParameters: if prmName.endswith('_bioavailability'): self.bioavailabilityIdx = i print("Found bioavailabilityIdx in %s at position %d" % (prmName, i)) break i += 1 def addSample(self, sampleName, t, y, fromSamples): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.doseDictPtr = self.outputExperiment.doses newSample.descriptors = {} newSample.doseList = ["Bolus"] newSample.addMeasurementPattern([self.fittingPK.predicted.varName]) newSample.addMeasurementColumn("t", t) newSample.addMeasurementColumn(self.fittingPK.predicted.varName, y) newSample.descriptors["AUC0t"] = self.AUC0t newSample.descriptors["AUMC0t"] = self.AUMC0t newSample.descriptors["MRT"] = self.MRT newSample.descriptors["Cmax"] = self.Cmax newSample.descriptors["Tmax"] = self.Tmax self.outputExperiment.samples[sampleName] = newSample self.outputExperiment.addLabelToSample(sampleName, "from", "individual---vesel", fromSamples) def NCA(self, t, C): self.AUC0t = 0 self.AUMC0t = 0 t0 = t[0] tperiod0 = 0 # Time at which the dose was given T0 = 0 TF = np.max(t) if self.NCAt0.get() != "" and self.NCAtF.get() != "": T0 = float(self.NCAt0.get()) TF = float(self.NCAtF.get()) if self.timeUnits == PKPDUnit.UNIT_TIME_MIN: T0 *= 60 TF *= 60 for idx in range(0, t.shape[0] - 1): if t[idx] >= T0 and t[idx] <= TF: dt = (t[idx + 1] - t[idx]) if C[idx + 1] >= C[idx]: # Trapezoidal in the raise self.AUC0t += 0.5 * dt * (C[idx] + C[idx + 1]) self.AUMC0t += 0.5 * dt * (C[idx] * t[idx] + C[idx + 1] * t[idx + 1]) else: # Log-trapezoidal in the decay decrement = C[idx] / C[idx + 1] K = math.log(decrement) B = K / dt self.AUC0t += dt * (C[idx] - C[idx + 1]) / K self.AUMC0t += (C[idx] * (t[idx] - tperiod0) - C[idx + 1] * (t[idx + 1] - tperiod0)) / B - ( C[idx + 1] - C[idx]) / (B * B) if idx == 0: self.Cmax = C[idx] self.Tmax = t[idx] - t0 else: if C[idx] > self.Cmax: self.Cmax = C[idx] self.Tmax = t[idx] - t0 self.MRT = self.AUMC0t / self.AUC0t print(" Cmax=%f [%s]" % (self.Cmax, strUnit(self.Cunits.unit))) print(" Tmax=%f [%s]" % (self.Tmax, strUnit(self.timeUnits))) print(" AUC0t=%f [%s]" % (self.AUC0t, strUnit(self.AUCunits))) print(" AUMC0t=%f [%s]" % (self.AUMC0t, strUnit(self.AUMCunits))) print(" MRT=%f [%s]" % (self.MRT, strUnit(self.timeUnits))) def simulate(self, objId1, objId2, inputDose, inputN): import sys self.getInVitroModels() self.getScaling() self.getPKModels() if not self.usePKExperiment: otherPKExperiment = PKPDExperiment() otherPKExperiment.load(self.inputPKOtherExperiment.get().fnPKPD) self.outputExperiment = PKPDExperiment() tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(self.fittingPK.predictor.units.unit) self.Cunits = self.fittingPK.predicted.units self.AUCunits = multiplyUnits(tvar.units.unit, self.Cunits.unit) self.AUMCunits = multiplyUnits(tvar.units.unit, self.AUCunits) if self.addIndividuals.get(): self.outputExperiment.variables["t"] = tvar self.outputExperiment.variables[ self.fittingPK.predicted.varName] = self.fittingPK.predicted self.outputExperiment.general[ "title"] = "Simulated ODE response from IVIVC dissolution profiles" self.outputExperiment.general[ "comment"] = "Simulated ODE response from IVIVC dissolution profiles" for via, _ in self.pkModel.drugSource.vias: self.outputExperiment.vias[via.viaName] = via for dose in self.pkModel.drugSource.parsedDoseList: self.outputExperiment.doses[dose.doseName] = dose AUCvar = PKPDVariable() AUCvar.varName = "AUC0t" AUCvar.varType = PKPDVariable.TYPE_NUMERIC AUCvar.role = PKPDVariable.ROLE_LABEL AUCvar.units = createUnit(strUnit(self.AUCunits)) AUMCvar = PKPDVariable() AUMCvar.varName = "AUMC0t" AUMCvar.varType = PKPDVariable.TYPE_NUMERIC AUMCvar.role = PKPDVariable.ROLE_LABEL AUMCvar.units = createUnit(strUnit(self.AUMCunits)) MRTvar = PKPDVariable() MRTvar.varName = "MRT" MRTvar.varType = PKPDVariable.TYPE_NUMERIC MRTvar.role = PKPDVariable.ROLE_LABEL MRTvar.units = createUnit( self.outputExperiment.getTimeUnits().unit) Cmaxvar = PKPDVariable() Cmaxvar.varName = "Cmax" Cmaxvar.varType = PKPDVariable.TYPE_NUMERIC Cmaxvar.role = PKPDVariable.ROLE_LABEL Cmaxvar.units = createUnit(strUnit(self.Cunits.unit)) Tmaxvar = PKPDVariable() Tmaxvar.varName = "Tmax" Tmaxvar.varType = PKPDVariable.TYPE_NUMERIC Tmaxvar.role = PKPDVariable.ROLE_LABEL Tmaxvar.units = createUnit( self.outputExperiment.getTimeUnits().unit) self.outputExperiment.variables["AUC0t"] = AUCvar self.outputExperiment.variables["AUMC0t"] = AUMCvar self.outputExperiment.variables["MRT"] = MRTvar self.outputExperiment.variables["Cmax"] = Cmaxvar self.outputExperiment.variables["Tmax"] = Tmaxvar t = np.arange(self.pkModel.t0, self.pkModel.tF, 1) if self.usePKExperiment: NPKFits = len(self.fittingPK.sampleFits) invivoFits = self.fittingPK.sampleFits else: NPKFits = len(otherPKExperiment.samples) invivoFits = [x for x in otherPKExperiment.samples.values()] for sample in invivoFits: sample.parameters = [ float(x) for x in sample.getDescriptorValues( self.fittingPK.modelParameters) ] NDissolFits = len(self.fittingInVitro.sampleFits) if self.allCombinations: inputN = NPKFits * NDissolFits AUCarray = np.zeros(inputN) AUMCarray = np.zeros(inputN) MRTarray = np.zeros(inputN) CmaxArray = np.zeros(inputN) TmaxArray = np.zeros(inputN) for i in range(0, inputN): print("Simulation no. %d ----------------------" % i) # Get a random PK model if self.allCombinations: nfit = int(i / NDissolFits) else: nfit = int(random.uniform(0, NPKFits)) sampleFitVivo = invivoFits[nfit] print("In vivo sample name=", sampleFitVivo.sampleName) if self.pkPopulation: nbootstrap = int( random.uniform(0, sampleFitVivo.parameters.shape[0])) pkPrmAll = sampleFitVivo.parameters[nbootstrap, :] else: pkPrmAll = sampleFitVivo.parameters pkPrm = pkPrmAll[-self.pkNParams:] # Get the last Nparams print("PK parameters: ", pkPrm) tlag = 0 if self.includeTlag.get() and (not self.tlagIdx is None): tlag = pkPrmAll[self.tlagIdx] print("tlag: ", tlag) bioavailability = 1 if not self.bioavailabilityIdx is None: bioavailability = pkPrmAll[self.bioavailabilityIdx] print("bioavailability: ", bioavailability) # Get a dissolution profile if self.allCombinations: nfit = i % NDissolFits else: nfit = int(random.uniform(0, NDissolFits)) sampleFitVitro = self.fittingInVitro.sampleFits[nfit] if self.dissolutionPopulation: nbootstrap = int( random.uniform(0, sampleFitVitro.parameters.shape[0])) dissolutionPrm = sampleFitVitro.parameters[nbootstrap, :] else: dissolutionPrm = sampleFitVitro.parameters print( "Dissolution parameters: ", np.array2string(np.asarray(dissolutionPrm, dtype=np.float64), max_line_width=1000)) sys.stdout.flush() if sampleFitVivo.sampleName in self.allTimeScalings: keyToUse = sampleFitVivo.sampleName elif len(self.allTimeScalings) == 1: keyToUse = list(self.allTimeScalings.keys())[0] else: raise Exception("Cannot find %s in the scaling keys" % sampleFitVivo.sampleName) nfit = int(random.uniform(0, len(self.allTimeScalings[keyToUse]))) tvitroLevy, tvivoLevy = self.allTimeScalings[keyToUse][nfit] tvivoLevyUnique, tvitroLevyUnique = uniqueFloatValues( tvivoLevy, tvitroLevy) BLevy = InterpolatedUnivariateSpline(tvivoLevyUnique, tvitroLevyUnique, k=1) tvitro = np.asarray(BLevy(t), dtype=np.float64) A = np.clip( self.dissolutionModel.forwardModel(dissolutionPrm, tvitro)[0], 0, 100) if self.conversionType.get() == 0: # In vitro-in vivo correlation Adissol, Fabs = self.allResponseScalings[keyToUse][nfit] AdissolUnique, FabsUnique = uniqueFloatValues(Adissol, Fabs) B = InterpolatedUnivariateSpline(AdissolUnique, FabsUnique, k=1) A = np.asarray(B(A), dtype=np.float64) # Set the dissolution profile self.pkModel.drugSource.getVia().viaProfile.setXYValues(t, A) C = self.pkModel.forwardModel( pkPrm, [t])[0] # forwardModel returns a list of arrays if tlag != 0.0: B = interp1d(t, C) C = B(np.clip(t - tlag, 0.0, None)) C[0:int(tlag)] = 0.0 C *= bioavailability self.NCA(t, C) AUCarray[i] = self.AUC0t AUMCarray[i] = self.AUMC0t MRTarray[i] = self.MRT CmaxArray[i] = self.Cmax TmaxArray[i] = self.Tmax if self.addIndividuals: self.addSample( "Simulation_%d" % i, t, C, "%s---%s" % (sampleFitVivo.sampleName, sampleFitVitro.sampleName)) # Report NCA statistics alpha_2 = (100 - 95) / 2 limits = np.percentile(AUCarray, [alpha_2, 100 - alpha_2]) fhSummary = open(self._getPath("summary.txt"), "w") self.doublePrint( fhSummary, "AUC %f%% confidence interval=[%f,%f] [%s] mean=%f" % (95, limits[0], limits[1], strUnit( self.AUCunits), np.mean(AUCarray))) limits = np.percentile(AUMCarray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "AUMC %f%% confidence interval=[%f,%f] [%s] mean=%f" % (95, limits[0], limits[1], strUnit( self.AUMCunits), np.mean(AUMCarray))) limits = np.percentile(MRTarray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "MRT %f%% confidence interval=[%f,%f] [%s] mean=%f" % (95, limits[0], limits[1], strUnit( self.timeUnits), np.mean(MRTarray))) limits = np.percentile(CmaxArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Cmax %f%% confidence interval=[%f,%f] [%s] mean=%f" % (95, limits[0], limits[1], strUnit( self.Cunits.unit), np.mean(CmaxArray))) limits = np.percentile(TmaxArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Tmax %f%% confidence interval=[%f,%f] [%s] mean=%f" % (95, limits[0], limits[1], strUnit( self.timeUnits), np.mean(TmaxArray))) fhSummary.close() if self.addIndividuals: self.outputExperiment.write(self._getPath("experiment.pkpd"), writeToExcel=False) def createOutputStep(self): if self.addIndividuals: self._defineOutputs(outputExperiment=self.outputExperiment) self._defineSourceRelation(self.inputInVitro.get(), self.outputExperiment) self._defineSourceRelation(self.inputPK.get(), self.outputExperiment) if self.conversionType.get() == 0: self._defineSourceRelation(self.inputIvIvC.get(), self.outputExperiment) elif self.conversionType.get() == 1: self._defineSourceRelation(self.inputLevy.get(), self.outputExperiment) def _validate(self): retval = [] if self.conversionType.get( ) == 0 and not "experimentFabs" in self.inputIvIvC.get().fnPKPD.get(): retval.append( "If the conversion is done from IVIVC, then you must take the Fabs output" ) return retval def _summary(self): retval = [] retval.append('Dose=%f' % self.inputDose.get()) retval.append('No. simulations=%d' % self.inputN.get()) retval.append(' ') self.addFileContentToMessage(retval, self._getPath("summary.txt")) return retval
class ProtPKPDODESimulate(ProtPKPDODEBase): """ Simulate a population of ODE parameters. These parameters can be specifically given, from a bootstrap population, a previous fitting, or an experiment. AUC0t and AUMC0t are referred to each dose (that is, t=0 is the beginning of the dose). Ctau is the concentration at the end of the dose. Tmin, Tmax, and Ttau are referred to the beginning of the dose. This protocol writes an Excel file (nca.xlsx) in which all the simulations and doses are written.""" _label = 'PK simulate' PRM_POPULATION = 0 PRM_USER_DEFINED = 1 PRM_FITTING = 2 PRM_EXPERIMENT = 3 SRC_ODE = 0 SRC_LIST = 1 VIATYPE_IV = 0 VIATYPE_EV0 = 1 VIATYPE_EV1 = 2 PKTYPE_COMP1 = 0 PKTYPE_COMP2 = 1 PKTYPE_COMP2CLCLINT = 2 #--------------------------- DEFINE param functions -------------------------------------------- def _defineParams(self, form): form.addSection('Input') form.addParam( 'odeSource', params.EnumParam, label='Source of ODE type', choices=['A previous PK fit', 'List'], default=self.SRC_ODE, help= 'The input model is used to define the absorbtion via and the type of distribution and elimination. ' 'Its parameters are not important, only its types') form.addParam('inputODE', params.PointerParam, label="Input ODE model", condition='odeSource==0', pointerClass='ProtPKPDMonoCompartment, ProtPKPDTwoCompartments, ProtPKPDMonoCompartmentPD, ProtPKPDTwoCompartmentsBothPD, '\ 'ProtPKPDODERefine, ProtPKPDTwoCompartmentsClint, ProtPKPDTwoCompartmentsClintCl', help='Select a run of an ODE model. This input is used to learn the kind of model that is needed. The parameters are ' 'taken from the sources below') form.addParam('viaType', params.EnumParam, label='Input via', condition='odeSource==1', default=0, choices=[ 'Intravenous (iv)', 'Extra vascular, 0th order absorption (ev0)', 'Extra vascular, 1st order absorption (ev1)' ], help='Parameters:\n' 'iv (vianame=Intravenous): no parameters\n' 'ev0 (vianame=Oral): Rin, tlag, F (bioavailability)\n' 'ev1 (vianame=Oral): Ka, tlag, F (bioavailability)\n') form.addParam( 'viaPrm', params.TextParam, label="Via parameters", height=8, default="", condition="odeSource==1", help= 'Specify the parameters for the via separated by commas. Example: \n' 'prm1, prm2, prm3\n' '\n' 'Parameters:\n' 'iv: no parameters\n' 'ev0: Rin, tlag, F (bioavailability)\n' 'ev1: Ka, tlag, F (bioavailability)\n') form.addParam('pkType', params.EnumParam, label='PK model', condition='odeSource==1', default=0, choices=[ '1 compartment', '2 compartments', '2 compartments Cl+Clint' ], help='Parameters:\n' '1 compartment: Cl, V\n' '2 compartments: Cl, V, Clp, Vp\n' '2 compartments Cl+Clint: Vmax, Km, Cl, V, Clp, Vp\n') form.addParam('timeUnits', params.StringParam, label='Time units', default='min', condition="odeSource==1", help='min or h') form.addParam('volumeUnits', params.StringParam, label='Volume units', default='L', condition="odeSource==1", help='mL or L') form.addParam( 'paramsSource', params.EnumParam, label="Source of parameters", condition="odeSource==0", choices=[ 'ODE Bootstrap', 'User defined', 'ODE Fitting', 'Experiment' ], default=0, help= "Choose a population of parameters, your own parameters or a previously fitted set of measurements" ) form.addParam( 'inputPopulation', params.PointerParam, label="Input population", condition="paramsSource==0 and odeSource==0", pointerClass='PKPDFitting', pointerCondition="isPopulation", help='It must be a fitting coming from a bootstrap sample') form.addParam( 'prmUser', params.TextParam, label="Simulation parameters", height=8, default="", condition="paramsSource==1 or odeSource==1", help= 'Specify the parameters for the simulation separated by commas. ' 'The parameters must be written in the same order as they are written by the protocol ' 'that generated the ODE model. Example: \n' 'prm1, prm2, prm3, prm4\n' 'prmA, prmB, prmC, prmD\n' '\n' 'If the parameters are not taken from a previous ODE:\n' '1 compartment: Cl, V\n' '2 compartments: Cl, V, Clp, Vp\n' '2 compartments Cl+Clint: Vmax, Km, Cl, V, Clp, Vp\n') form.addParam( 'inputFitting', params.PointerParam, label="Input ODE fitting", condition="paramsSource==2 and odeSource==0", pointerClass='PKPDFitting', help='It must be a fitting coming from a compartmental PK fitting') form.addParam( 'inputExperiment', params.PointerParam, label="Input experiment", condition="paramsSource==3 and odeSource==0", pointerClass='PKPDExperiment', help= 'It must contain the parameters required for the simulation (Cl, V, Clp, Vp, ...)' ) form.addParam('doses', params.TextParam, label="Doses", height=5, width=50, default="RepeatedBolus ; via=Oral; repeated_bolus; t=0:24:120 h; d=60 mg", 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('sampling', params.FloatParam, label="Sampling time (see help)", default=1, help="Same units as input experiment") form.addParam('Nsimulations', params.IntParam, label="Simulation samples", default=200, condition="paramsSource==0 and odeSource==0", expertLevel=LEVEL_ADVANCED, help='Number of simulations') form.addParam( 'addStats', params.BooleanParam, label="Add simulation statistics", default=True, condition="paramsSource==0 and odeSource==0", expertLevel=LEVEL_ADVANCED, help= "Mean, lower and upper confidence levels are added to the output") form.addParam( 'confidenceLevel', params.FloatParam, label="Confidence interval", default=95, expertLevel=LEVEL_ADVANCED, help='Confidence interval for the fitted parameters', condition="addStats and paramsSource==0 and odeSource==0") form.addParam('addIndividuals', params.BooleanParam, label="Add individual simulations", default=False, expertLevel=LEVEL_ADVANCED, help="Individual simulations are added to the output") #--------------------------- INSERT steps functions -------------------------------------------- def _insertAllSteps(self): self._insertFunctionStep('runSimulate', self.Nsimulations.get(), self.confidenceLevel.get(), self.doses.get()) self._insertFunctionStep('createOutputStep') #--------------------------- STEPS functions -------------------------------------------- def addSample(self, sampleName, doseName, simulationsX, y): newSample = PKPDSample() newSample.sampleName = sampleName newSample.variableDictPtr = self.outputExperiment.variables newSample.doseDictPtr = self.outputExperiment.doses newSample.descriptors = {} newSample.doseList = [doseName] tsample = np.arange(0.0, np.max(simulationsX), self.sampling.get()) if type(self.varNameY) != list: newSample.addMeasurementPattern([self.varNameY]) B = InterpolatedUnivariateSpline(simulationsX, y, k=1) newSample.addMeasurementColumn("t", tsample) newSample.addMeasurementColumn(self.varNameY, B(tsample)) else: for j in range(len(self.varNameY)): newSample.addMeasurementPattern([self.varNameY[j]]) newSample.addMeasurementColumn("t", tsample) for j in range(len(self.varNameY)): B = InterpolatedUnivariateSpline(simulationsX, y[j], k=1) newSample.addMeasurementColumn(self.varNameY[j], B(tsample)) newSample.descriptors["FromSample"] = self.fromSample newSample.descriptors["AUC0t"] = self.AUC0t newSample.descriptors["AUMC0t"] = self.AUMC0t newSample.descriptors["MRT"] = self.MRT newSample.descriptors["Cmax"] = self.Cmax newSample.descriptors["Cmin"] = self.Cmin newSample.descriptors["Cavg"] = self.Cavg newSample.descriptors["Tmax"] = self.Tmax newSample.descriptors["Tmin"] = self.Tmin self.outputExperiment.samples[sampleName] = newSample def NCA(self, t, C): AUClist = [] AUMClist = [] Cminlist = [] Cavglist = [] Cmaxlist = [] Ctaulist = [] Tmaxlist = [] Tminlist = [] Ttaulist = [] Ndoses = len(self.drugSource.parsedDoseList) for ndose in range(0, max(Ndoses, 1)): tperiod0 = self.drugSource.parsedDoseList[ndose].t0 if ndose + 1 < Ndoses: tperiodF = self.drugSource.parsedDoseList[ ndose + 1].t0 - self.model.deltaT else: tperiodF = np.max(t) - 1 idx0 = find_nearest(t, tperiod0) idxF = find_nearest(t, tperiodF) if idxF >= len(t) - 1: idxF = len(t) - 2 AUC0t = 0 AUMC0t = 0 t0 = t[idx0 + 1] for idx in range(idx0, idxF + 1): dt = (t[idx + 1] - t[idx]) if C[idx + 1] >= C[idx]: # Trapezoidal in the raise AUC0t += 0.5 * dt * (C[idx] + C[idx + 1]) AUMC0t += 0.5 * dt * (C[idx] * t[idx] + C[idx + 1] * t[idx + 1]) else: # Log-trapezoidal in the decay decrement = C[idx] / C[idx + 1] K = math.log(decrement) B = K / dt AUC0t += dt * (C[idx] - C[idx + 1]) / K AUMC0t += (C[idx] * (t[idx] - tperiod0) - C[idx + 1] * (t[idx + 1] - tperiod0)) / B - ( C[idx + 1] - C[idx]) / (B * B) if idx == idx0: Cmax = C[idx] Tmax = t[idx] - t0 Cmin = C[idx] Tmin = t[idx] - t0 else: if C[idx] < Cmin: Cmin = C[idx] Tmin = t[idx] - t0 elif C[idx] > Cmax: Cmax = C[idx] Tmax = t[idx] - t0 # if ndose==0: # Cmin=C[idx] # Tmin=t[idx]-t0 AUClist.append(AUC0t) AUMClist.append(AUMC0t) Cminlist.append(Cmin) Cmaxlist.append(Cmax) Ctaulist.append(C[idxF]) Ttaulist.append(t[idxF] - t0) Tmaxlist.append(Tmax) Tminlist.append(Tmin) Cavglist.append(AUC0t / (t[idxF] - t[idx0])) print("Fluctuation = Cmax/Cmin") print("Accumulation(1) = Cavg(n)/Cavg(1) %") print("Accumulation(n) = Cavg(n)/Cavg(n-1) %") print("Steady state fraction(n) = Cavg(n)/Cavg(last) %") for ndose in range(0, len(AUClist)): if Cminlist[ndose] != 0: fluctuation = Cmaxlist[ndose] / Cminlist[ndose] else: fluctuation = np.nan if ndose > 0: accumn = Cavglist[ndose] / Cavglist[ndose - 1] else: accumn = 0 print("Dose #%d t=[%f,%f]: Cavg= %f [%s] Cmin= %f [%s] Tmin= %d [%s] Cmax= %f [%s] Tmax= %d [%s] Ctau= %f [%s] Ttau= %d [%s] Fluct= %f %% Accum(1)= %f %% Accum(n)= %f %% SSFrac(n)= %f %% AUC= %f [%s] AUMC= %f [%s]"%\ (ndose+1,t[idx0],t[idxF],Cavglist[ndose], strUnit(self.Cunits.unit), Cminlist[ndose], strUnit(self.Cunits.unit), int(Tminlist[ndose]), strUnit(self.outputExperiment.getTimeUnits().unit), Cmaxlist[ndose], strUnit(self.Cunits.unit), int(Tmaxlist[ndose]), strUnit(self.outputExperiment.getTimeUnits().unit), Ctaulist[ndose], strUnit(self.Cunits.unit), int(Ttaulist[ndose]), strUnit(self.outputExperiment.getTimeUnits().unit), fluctuation*100, Cavglist[ndose]/Cavglist[0]*100, accumn*100, Cavglist[ndose]/Cavglist[-1]*100, AUClist[ndose],strUnit(self.AUCunits), AUMClist[ndose],strUnit(self.AUMCunits))) self.AUC0t = float(AUClist[-1]) self.AUMC0t = float(AUMClist[-1]) self.MRT = self.AUMC0t / self.AUC0t self.Cmin = float(Cminlist[-1]) self.Cmax = float(Cmaxlist[-1]) self.Tmin = float(Tminlist[-1]) self.Tmax = float(Tmaxlist[-1]) self.Cavg = float(Cavglist[-1]) self.Ctau = float(Ctaulist[-1]) self.Ttau = float(Ttaulist[-1]) self.fluctuation = self.Cmax / self.Cmin if self.Cmin > 0 else np.nan self.percentageAccumulation = Cavglist[-1] / Cavglist[0] if Cavglist[ 0] > 0 else np.nan print(" AUC0t=%f [%s]" % (self.AUC0t, strUnit(self.AUCunits))) print(" AUMC0t=%f [%s]" % (self.AUMC0t, strUnit(self.AUMCunits))) print(" MRT=%f [%s]" % (self.MRT, strUnit(self.outputExperiment.getTimeUnits().unit))) print(" Cmax=%f [%s]" % (self.Cmax, strUnit(self.Cunits.unit))) print(" Cmin=%f [%s]" % (self.Cmin, strUnit(self.Cunits.unit))) print(" Cavg=%f [%s]" % (self.Cavg, strUnit(self.Cunits.unit))) print(" Ctau=%f [%s]" % (self.Ctau, strUnit(self.Cunits.unit))) print(" Tmax=%f [%s]" % (self.Tmax, strUnit(self.outputExperiment.getTimeUnits().unit))) print(" Tmin=%f [%s]" % (self.Tmin, strUnit(self.outputExperiment.getTimeUnits().unit))) print(" Ttau=%f [%s]" % (self.Ttau, strUnit(self.outputExperiment.getTimeUnits().unit))) return AUClist, AUMClist, Cminlist, Cavglist, Cmaxlist, Ctaulist, Tmaxlist, Tminlist, Ttaulist def runSimulate(self, Nsimulations, confidenceInterval, doses): if self.odeSource.get() == self.SRC_ODE: self.protODE = self.inputODE.get() if hasattr(self.protODE, "outputExperiment"): self.experiment = self.readExperiment( self.protODE.outputExperiment.fnPKPD) elif hasattr(self.protODE, "outputExperiment1"): self.experiment = self.readExperiment( self.protODE.outputExperiment1.fnPKPD) else: raise Exception( "Cannot find an outputExperiment in the input ODE") if self.paramsSource.get() == ProtPKPDODESimulate.PRM_POPULATION: self.fitting = self.readFitting( self.inputPopulation.get().fnFitting, cls="PKPDSampleFitBootstrap") elif self.paramsSource.get() == ProtPKPDODESimulate.PRM_FITTING: self.fitting = self.readFitting( self.inputFitting.get().fnFitting) else: # User defined or experiment if hasattr(self.protODE, "outputFitting"): self.fitting = self.readFitting( self.protODE.outputFitting.fnFitting) elif hasattr(self.protODE, "outputFitting1"): self.fitting = self.readFitting( self.protODE.outputFitting1.fnFitting) 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] tunits = self.experiment.getTimeUnits().unit else: self.varNameX = 't' self.varNameY = 'C' self.fitting = None self.experiment = None self.protODE = None tunits = unitFromString(self.timeUnits.get()) # Create drug source self.clearGroupParameters() self.createDrugSource() # Create output object self.outputExperiment = PKPDExperiment() self.outputExperiment.general["title"] = "Simulated ODE response" self.outputExperiment.general["comment"] = "Simulated ODE response" # Create the predictor variable tvar = PKPDVariable() tvar.varName = "t" tvar.varType = PKPDVariable.TYPE_NUMERIC tvar.role = PKPDVariable.ROLE_TIME tvar.units = createUnit(tunits) self.outputExperiment.variables[self.varNameX] = tvar # Vias if self.odeSource.get() == self.SRC_ODE: self.outputExperiment.vias = self.experiment.vias else: # "[ViaName]; [ViaType]; [tlag]; [bioavailability]" viaPrmList = [ token for token in self.viaPrm.get().strip().split(',') ] if self.viaType.get() == self.VIATYPE_IV: tokens = [ "Intravenous", "iv", "tlag=0 min", "bioavailability=1" ] elif self.viaType.get() == self.VIATYPE_EV0: tokens = ["Oral", "ev0"] + [ "tlag=" + viaPrmList[-2].strip() + " " + self.timeUnits.get() ] + ["bioavailability=" + viaPrmList[-1].strip()] elif self.viaType.get() == self.VIATYPE_EV1: tokens = ["Oral", "ev1"] + [ "tlag=" + viaPrmList[-2].strip() + " " + self.timeUnits.get() ] + ["bioavailability=" + viaPrmList[-1].strip()] vianame = tokens[0] self.outputExperiment.vias[vianame] = PKPDVia( ptrExperiment=self.outputExperiment) self.outputExperiment.vias[vianame].parseTokens(tokens) # Read the doses dunits = PKPDUnit.UNIT_NONE for line in self.doses.get().replace('\n', ';;').split(';;'): tokens = line.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) dunits = self.outputExperiment.doses[dosename].getDoseUnits() # Create predicted variables if self.odeSource.get() == self.SRC_ODE: 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] else: Cvar = PKPDVariable() Cvar.varName = "C" Cvar.varType = PKPDVariable.TYPE_NUMERIC Cvar.role = PKPDVariable.ROLE_MEASUREMENT Cvar.units = createUnit( divideUnits(dunits.unit, unitFromString(self.volumeUnits.get()))) self.outputExperiment.variables[self.varNameY] = Cvar # Setup model if self.odeSource.get() == self.SRC_ODE: self.model = self.protODE.createModel() if hasattr(self.protODE, "deltaT"): self.model.deltaT = self.protODE.deltaT.get() else: if self.pkType.get() == self.PKTYPE_COMP1: self.model = PK_Monocompartment() elif self.pkType.get() == self.PKTYPE_COMP2: self.model = PK_Twocompartment() elif self.pkType.get() == self.PKTYPE_COMP2CLCLINT: self.model = PK_TwocompartmentsClintCl() self.model.setExperiment(self.outputExperiment) self.model.setXVar(self.varNameX) self.model.setYVar(self.varNameY) Nsamples = int( math.ceil((self.tF.get() - self.t0.get()) / self.model.deltaT)) + 1 self.model.x = [ self.t0.get() + i * self.model.deltaT for i in range(0, Nsamples) ] self.modelList.append(self.model) auxSample = PKPDSample() auxSample.descriptors = {} auxSample.doseDictPtr = self.outputExperiment.doses auxSample.variableDictPtr = self.outputExperiment.variables auxSample.doseList = self.outputExperiment.doses.keys() auxSample.interpretDose() self.drugSource.setDoses(auxSample.parsedDoseList, self.t0.get() - 10, self.tF.get() + 10) self.model.drugSource = self.drugSource # Check units # Dunits = self.outputExperiment.doses[dosename].dunits # Cunits = self.experiment.variables[self.varNameY].units # Process user parameters if self.odeSource.get() == self.SRC_ODE: if self.paramsSource == ProtPKPDODESimulate.PRM_POPULATION: Nsimulations = self.Nsimulations.get() elif self.paramsSource == ProtPKPDODESimulate.PRM_USER_DEFINED: lines = self.prmUser.get().strip().replace('\n', ';;').split(';;') Nsimulations = len(lines) prmUser = [] for line in lines: tokens = line.strip().split(',') prmUser.append([float(token) for token in tokens]) elif self.paramsSource == ProtPKPDODESimulate.PRM_FITTING: Nsimulations = len(self.fitting.sampleFits) else: self.inputExperiment = self.readExperiment( self.inputExperiment.get().fnPKPD) Nsimulations = len(self.inputExperiment.samples) inputSampleNames = self.inputExperiment.samples.keys() else: lines = self.prmUser.get().strip().replace('\n', ';;').split(';;') Nsimulations = len(lines) prmUser = [] for line in lines: tokens = line.strip().split(',') prmUser.append([float(token) for token in tokens]) # Simulate the different responses simulationsX = self.model.x simulationsY = np.zeros( (Nsimulations, len(simulationsX), self.getResponseDimension())) AUCarray = np.zeros(Nsimulations) AUMCarray = np.zeros(Nsimulations) MRTarray = np.zeros(Nsimulations) CminArray = np.zeros(Nsimulations) CmaxArray = np.zeros(Nsimulations) CavgArray = np.zeros(Nsimulations) CtauArray = np.zeros(Nsimulations) TminArray = np.zeros(Nsimulations) TmaxArray = np.zeros(Nsimulations) TtauArray = np.zeros(Nsimulations) fluctuationArray = np.zeros(Nsimulations) percentageAccumulationArray = np.zeros(Nsimulations) wb = openpyxl.Workbook() wb.active.title = "Simulations" for i in range(0, Nsimulations): self.setTimeRange(None) if self.odeSource.get() == self.SRC_ODE: if self.paramsSource == ProtPKPDODESimulate.PRM_POPULATION: # Take parameters randomly from the population nfit = int(random.uniform(0, len(self.fitting.sampleFits))) sampleFit = self.fitting.sampleFits[nfit] nprm = int(random.uniform(0, sampleFit.parameters.shape[0])) parameters = sampleFit.parameters[nprm, :] self.fromSample = "Population %d" % nprm elif self.paramsSource == ProtPKPDODESimulate.PRM_USER_DEFINED: parameters = np.asarray(prmUser[i], np.double) self.fromSample = "User defined" elif self.paramsSource == ProtPKPDODESimulate.PRM_FITTING: parameters = self.fitting.sampleFits[i].parameters self.fromSample = self.fitting.sampleFits[i].sampleName else: parameters = [] self.fromSample = inputSampleNames[i] sample = self.inputExperiment.samples[self.fromSample] for prmName in self.fitting.modelParameters: parameters.append( float(sample.getDescriptorValue(prmName))) else: parameters = np.asarray(viaPrmList[:-2] + prmUser[i], np.double) self.fromSample = "User defined" print("From sample name: %s" % self.fromSample) print("Simulated sample %d: %s" % (i, str(parameters))) # Prepare source and this object self.drugSource.setDoses(auxSample.parsedDoseList, self.model.t0, self.model.tF) if self.protODE is not None: self.protODE.configureSource(self.drugSource) self.model.drugSource = self.drugSource parameterNames = self.getParameterNames( ) # Necessary to count the number of source and PK parameters # Prepare the model self.setParameters(parameters) y = self.forwardModel(parameters, [simulationsX] * self.getResponseDimension()) # Create AUC, AUMC, MRT variables and units if i == 0: if type(self.varNameY) != list: self.Cunits = self.outputExperiment.variables[ self.varNameY].units else: self.Cunits = self.outputExperiment.variables[ self.varNameY[0]].units self.AUCunits = multiplyUnits(tvar.units.unit, self.Cunits.unit) self.AUMCunits = multiplyUnits(tvar.units.unit, self.AUCunits) if self.addStats or self.addIndividuals: fromvar = PKPDVariable() fromvar.varName = "FromSample" fromvar.varType = PKPDVariable.TYPE_TEXT fromvar.role = PKPDVariable.ROLE_LABEL fromvar.units = createUnit("none") AUCvar = PKPDVariable() AUCvar.varName = "AUC0t" AUCvar.varType = PKPDVariable.TYPE_NUMERIC AUCvar.role = PKPDVariable.ROLE_LABEL AUCvar.units = createUnit(strUnit(self.AUCunits)) AUMCvar = PKPDVariable() AUMCvar.varName = "AUMC0t" AUMCvar.varType = PKPDVariable.TYPE_NUMERIC AUMCvar.role = PKPDVariable.ROLE_LABEL AUMCvar.units = createUnit(strUnit(self.AUMCunits)) MRTvar = PKPDVariable() MRTvar.varName = "MRT" MRTvar.varType = PKPDVariable.TYPE_NUMERIC MRTvar.role = PKPDVariable.ROLE_LABEL MRTvar.units = createUnit( self.outputExperiment.getTimeUnits().unit) Cmaxvar = PKPDVariable() Cmaxvar.varName = "Cmax" Cmaxvar.varType = PKPDVariable.TYPE_NUMERIC Cmaxvar.role = PKPDVariable.ROLE_LABEL Cmaxvar.units = createUnit(strUnit(self.Cunits.unit)) Tmaxvar = PKPDVariable() Tmaxvar.varName = "Tmax" Tmaxvar.varType = PKPDVariable.TYPE_NUMERIC Tmaxvar.role = PKPDVariable.ROLE_LABEL Tmaxvar.units = createUnit( self.outputExperiment.getTimeUnits().unit) Cminvar = PKPDVariable() Cminvar.varName = "Cmin" Cminvar.varType = PKPDVariable.TYPE_NUMERIC Cminvar.role = PKPDVariable.ROLE_LABEL Cminvar.units = createUnit(strUnit(self.Cunits.unit)) Tminvar = PKPDVariable() Tminvar.varName = "Tmin" Tminvar.varType = PKPDVariable.TYPE_NUMERIC Tminvar.role = PKPDVariable.ROLE_LABEL Tminvar.units = createUnit( self.outputExperiment.getTimeUnits().unit) Cavgvar = PKPDVariable() Cavgvar.varName = "Cavg" Cavgvar.varType = PKPDVariable.TYPE_NUMERIC Cavgvar.role = PKPDVariable.ROLE_LABEL Cavgvar.units = createUnit(strUnit(self.Cunits.unit)) self.outputExperiment.variables["FromSample"] = fromvar self.outputExperiment.variables["AUC0t"] = AUCvar self.outputExperiment.variables["AUMC0t"] = AUMCvar self.outputExperiment.variables["MRT"] = MRTvar self.outputExperiment.variables["Cmax"] = Cmaxvar self.outputExperiment.variables["Tmax"] = Tmaxvar self.outputExperiment.variables["Cmin"] = Cminvar self.outputExperiment.variables["Tmin"] = Tminvar self.outputExperiment.variables["Cavg"] = Cavgvar excelWriteRow([ "simulationName", "fromSample", "doseNumber", "AUC [%s]" % strUnit(self.AUCunits), "AUMC [%s]" % strUnit(self.AUMCunits), "Cmin [%s]" % strUnit(self.Cunits.unit), "Cavg [%s]" % strUnit(self.Cunits.unit), "Cmax [%s]" % strUnit(self.Cunits.unit), "Ctau [%s]" % strUnit(self.Cunits.unit), "Tmin [%s]" % strUnit(self.outputExperiment.getTimeUnits().unit), "Tmax [%s]" % strUnit(self.outputExperiment.getTimeUnits().unit), "Ttau [%s]" % strUnit(self.outputExperiment.getTimeUnits().unit) ], wb, 1, bold=True) wbRow = 2 # Evaluate AUC, AUMC and MRT in the last full period AUClist, AUMClist, Cminlist, Cavglist, Cmaxlist, Ctaulist, Tmaxlist, Tminlist, Ttaulist = self.NCA( self.model.x, y[0]) for doseNo in range(0, len(AUClist)): excelWriteRow([ "Simulation_%d" % i, self.fromSample, doseNo, AUClist[doseNo], AUMClist[doseNo], Cminlist[doseNo], Cavglist[doseNo], Cmaxlist[doseNo], Ctaulist[doseNo], Tminlist[doseNo], Tmaxlist[doseNo], Ttaulist[doseNo] ], wb, wbRow) wbRow += 1 # Keep results for j in range(self.getResponseDimension()): simulationsY[i, :, j] = y[j] AUCarray[i] = self.AUC0t AUMCarray[i] = self.AUMC0t MRTarray[i] = self.MRT CminArray[i] = self.Cmin CmaxArray[i] = self.Cmax CavgArray[i] = self.Cavg CtauArray[i] = self.Ctau TminArray[i] = self.Tmin TmaxArray[i] = self.Tmax TtauArray[i] = self.Ttau fluctuationArray[i] = self.fluctuation percentageAccumulationArray[i] = self.percentageAccumulation if self.addIndividuals or self.paramsSource != ProtPKPDODESimulate.PRM_POPULATION: self.addSample("Simulation_%d" % i, dosename, simulationsX, y[0]) # Report NCA statistics fhSummary = open(self._getPath("summary.txt"), "w") alpha_2 = (100 - self.confidenceLevel.get()) / 2 limits = np.percentile(AUCarray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "AUC %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.AUCunits), np.mean(AUCarray))) limits = np.percentile(AUMCarray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "AUMC %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.AUMCunits), np.mean(AUMCarray))) limits = np.percentile(MRTarray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "MRT %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.outputExperiment.getTimeUnits().unit), np.mean(MRTarray))) limits = np.percentile(CminArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Cmin %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.Cunits.unit), np.mean(CminArray))) limits = np.percentile(CmaxArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Cmax %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.Cunits.unit), np.mean(CmaxArray))) limits = np.percentile(CavgArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Cavg %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.Cunits.unit), np.mean(CavgArray))) limits = np.percentile(CtauArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Ctau %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.Cunits.unit), np.mean(CtauArray))) limits = np.percentile(TminArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Tmin %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.outputExperiment.getTimeUnits().unit), np.mean(TminArray))) limits = np.percentile(TmaxArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Tmax %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.outputExperiment.getTimeUnits().unit), np.mean(TmaxArray))) limits = np.percentile(TtauArray, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Ttau %f%% confidence interval=[%f,%f] [%s] mean=%f" % (self.confidenceLevel.get(), limits[0], limits[1], strUnit(self.outputExperiment.getTimeUnits().unit), np.mean(TtauArray))) aux = fluctuationArray[~np.isnan(fluctuationArray)] if len(aux) > 0: limits = np.percentile(aux, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Fluctuation %f%% confidence interval=[%f,%f] [%%] mean=%f" % (self.confidenceLevel.get(), limits[0] * 100, limits[1] * 100, np.mean(aux) * 100)) aux = percentageAccumulationArray[~np.isnan(percentageAccumulationArray )] limits = np.percentile(aux, [alpha_2, 100 - alpha_2]) self.doublePrint( fhSummary, "Accum(1) %f%% confidence interval=[%f,%f] [%%] mean=%f" % (self.confidenceLevel.get(), limits[0] * 100, limits[1] * 100, np.mean(aux) * 100)) fhSummary.close() # Calculate statistics if self.addStats and self.odeSource == 0 and self.paramsSource == 0: if self.paramsSource != ProtPKPDODESimulate.PRM_USER_DEFINED: limits = np.percentile(simulationsY, [alpha_2, 100 - alpha_2], axis=0) print("Lower limit NCA") self.NCA(simulationsX, limits[0]) self.fromSample = "LowerLimit" self.addSample("LowerLimit", dosename, simulationsX, limits[0]) print("Mean profile NCA") if self.getResponseDimension() == 1: mu = np.mean(simulationsY, axis=0) self.NCA(simulationsX, mu) else: mu = [] for j in range(self.getResponseDimension()): mu.append(np.mean(simulationsY[:, :, j], axis=0)) self.NCA(simulationsX, mu[0]) self.fromSample = "Mean" self.addSample("Mean", dosename, simulationsX, mu) if self.paramsSource != ProtPKPDODESimulate.PRM_USER_DEFINED: print("Upper limit NCA") self.NCA(simulationsX, limits[1]) self.fromSample = "UpperLimit" self.addSample("UpperLimit", dosename, simulationsX, limits[1]) self.outputExperiment.write(self._getPath("experiment.pkpd")) wb.save(self._getPath("nca.xlsx")) def createOutputStep(self): self._defineOutputs(outputExperiment=self.outputExperiment) if self.odeSource.get() == self.SRC_ODE: self._defineSourceRelation(self.inputODE.get(), self.outputExperiment) if self.paramsSource == ProtPKPDODESimulate.PRM_POPULATION: self._defineSourceRelation(self.inputPopulation.get(), self.outputExperiment) elif self.paramsSource == ProtPKPDODESimulate.PRM_POPULATION: self._defineSourceRelation(self.inputFitting.get(), self.outputExperiment) #--------------------------- INFO functions -------------------------------------------- def _summary(self): msg = [] msg.append("Dose: %s" % self.doses.get()) if self.odeSource == ProtPKPDODESimulate.SRC_ODE and self.paramsSource == ProtPKPDODESimulate.PRM_POPULATION: msg.append("Number of simulations: %d" % self.Nsimulations.get()) elif self.odeSource == ProtPKPDODESimulate.SRC_LIST or self.paramsSource == ProtPKPDODESimulate.PRM_USER_DEFINED: msg.append("Parameters:\n" + self.prmUser.get()) else: msg.append("Parameters from previous fitting") msg.append(" ") self.addFileContentToMessage(msg, self._getPath("summary.txt")) return msg def _validate(self): msg = [] if self.odeSource == self.SRC_ODE and \ self.paramsSource == ProtPKPDODESimulate.PRM_POPULATION and \ not self.inputPopulation.get().fnFitting.get().endswith("bootstrapPopulation.pkpd"): msg.append("Population must be a bootstrap sample") return msg