def testWolfBug(self): if IGNORE_TEST: return trueParameterDct = { "J1_n": 4, "J4_kp": 76411, "J5_k": 80, "J6_k": 9.7, "J9_k": 28, } parametersToFit = [ SBstoat.Parameter("J1_n", lower=1, value=1, upper=8), # 4 SBstoat.Parameter("J4_kp", lower=3600, value=36000, upper=150000), #76411 SBstoat.Parameter("J5_k", lower=10, value=10, upper=160), # 80 SBstoat.Parameter("J6_k", lower=1, value=1, upper=10), # 9.7 SBstoat.Parameter("J9_k", lower=1, value=50, upper=50), # 28 ] ts = NamedTimeseries(csvPath=WOLF_DATA) methods = [] for optName in ["differential_evolution", "leastsq"]: methods.append(SBstoat.OptimizerMethod(optName, {cn.MAX_NFEV: 10})) fitter = ModelFitter(WOLF_MODEL, ts, parametersToFit=parametersToFit, fitterMethods=methods) fitter.fitModel() for name in [p.name for p in parametersToFit]: expected = trueParameterDct[name] actual = fitter.params.valuesdict()[name] self.assertLess(np.abs(np.log10(expected) - np.log10(actual)), 1.5) self.assertTrue(name in fitter.reportFit())
def testFitSuite(self): if IGNORE_TEST: return self._init(numModel=1) fitter = ModelFitter(self.modelSpecifications[0], self.datasets[0], parametersToFit=self.parameterNamesCollection[0]) fitter.fitModel() self.fitter.fitSuite() valuesDct1 = fitter.params.valuesdict() valuesDct2 = self.fitter.params.valuesdict() for name, value in valuesDct1.items(): self.assertLess(np.abs(valuesDct2[name] - value), 0.5)
def __init__(self, modelFitters, modelNames=None, modelWeights=None, fitterMethods=None, numRestart=0, isParallel=False, logger=Logger()): """ Parameters ---------- modelFitters: list-modelFiter modelWeights: list-float how models are weighted in least squares modelNames: list-str fitterMethods: list-optimization methods numRestart: int number of times the minimization is restarted with random initial values for parameters to fit. isParallel: bool runs each fitter in parallel logger: Logger Raises ------ ValueError: len(modelNames) == len(modelFitters) """ self.numModel = len(modelFitters) self.modelWeights = modelWeights if self.modelWeights is None: self.modelWeights = np.repeat(1, self.numModel) self.modelNames = modelNames if self.modelNames is None: self.modelNames = [str(v) for v in range(len(modelSpecifications))] self._numRestart = numRestart self._isParallel = isParallel self.logger = logger # Validation checks if self.numModel != len(self.modelNames): msg = "Length of modelNames must be same as number of modelFitters." raise ValueError(msg) # self.fitterDct = {n: f for n, f in zip(modelNames, modelFitters)} # Construct tha parameters for each model self.parametersCollection = [f.params for f in self.fitterDct.values()] self.parameterManager = _ParameterManager(self.modelNames, self.parametersCollection) self._fitterMethods = ModelFitter.makeMethods( fitterMethods, cn.METHOD_FITTER_DEFAULTS) # Residuals calculations self.residualsServers = [ ResidualsServer(f, None, None, logger=self.logger) for f in self.fitterDct.values() ] self.manager = None # Results self.optimizer = None
def testDeserialize(self): if IGNORE_TEST: return fitter = self.getFitter() fitter.serialize(FILE_SERIALIZE) deserializedFitter = ModelFitter.deserialize(FILE_SERIALIZE) self.assertEqual(fitter.modelSpecification, deserializedFitter.modelSpecification) self.assertEqual(len(fitter.bootstrapResult.fittedStatistic.meanTS), len(deserializedFitter.bootstrapResult.fittedStatistic.meanTS))
def testOptimizerMethod(self): if IGNORE_TEST: return METHOD_NAME = 'differential_evolution' optimizerMethod = ModelFitter.OptimizerMethod( method=METHOD_NAME, kwargs={ "popsize": 100, "atol": 0.001}) fitter1 = self._makeMikeModel(fitterMethods=[METHOD_NAME]) fitter2 = self._makeMikeModel(fitterMethods=[optimizerMethod]) self.assertTrue(True) # Smoke test
def reportFit(self): """ Parameters ---------- Returns ------- """ return ModelFitter.reportTheFit(self.optimizer.minimizerResult, self.params)
def testWolfBug(self): if IGNORE_TEST: return fullDct = { #"J1_n": (1, 1, 8), # 4 #"J4_kp": (3600, 36000, 150000), #76411 #"J5_k": (10, 10, 160), # 80 #"J6_k": (1, 1, 10), # 9.7 "J9_k": (1, 50, 50), # 28 } for parameter in fullDct.keys(): logger = Logger(logLevel=LEVEL_MAX) logger = Logger() ts = NamedTimeseries(csvPath=WOLF_DATA) parameterDct = {parameter: fullDct[parameter]} fitter = ModelFitter(WOLF_MODEL, ts[0:100], parameterDct=parameterDct, logger=logger, fitterMethods=[ "differential_evolution", "leastsq"]) fitter.fitModel() self.assertTrue("J9_k" in fitter.reportFit())
def evaluate(self, stdResiduals:float=0.1, relError:float=0.1, endTime:float=10.0, numPoint:int=30, fractionParameterDeviation:float=0.5, numIteration=NUM_BOOTSTRAP_ITERATION): """ Evaluates model fitting accuracy and bootstrapping for model Parameters ---------- stdResiduals: Standard deviations of variable used in constructing reiduals relError: relative error of parameter used in evaluation endTime: ending time of the simulation numPoint: number of points in the simulatin fractionParameterDeviation: fractional amount that the parameter can vary """ # Construct synthetic observations if self.selectedColumns is None: data = self.roadRunner.simulate(0, endTime, numPoint) else: allColumns = list(self.selectedColumns) if not TIME in allColumns: allColumns.append(TIME) data = self.roadRunner.simulate(0, endTime, numPoint, allColumns) bracketTime = "[%s]" % TIME if bracketTime in data.colnames: # Exclude any column named '[time]' idx = data.colnames.index(bracketTime) dataArr = np.delete(data, idx, axis=1) colnames = list(data.colnames) colnames.remove(bracketTime) colnames = [s[1:-1] if s != TIME else s for s in colnames] simTS = NamedTimeseries(array=dataArr, colnames=colnames) else: simTS = NamedTimeseries(namedArray=data) synthesizer = ObservationSynthesizerRandomErrors( fittedTS=simTS, std=stdResiduals) observedTS = synthesizer.calculate() # Construct the parameter ranges parameterDct = {} for name in self.parameterValueDct.keys(): lower = self.parameterValueDct[name]*(1 - fractionParameterDeviation) upper = self.parameterValueDct[name]*(1 + fractionParameterDeviation) value = np.random.uniform(lower, upper) parameterDct[name] = (lower, upper, value) # Create the fitter fitter = ModelFitter(self.roadRunner, observedTS, selectedColumns=self.selectedColumns, parameterDct=parameterDct, **self.kwargs) msg = "Fitting the parameters %s" % str(self.parameterValueDct.keys()) self.logger.result(msg) # Evaluate the fit fitter.fitModel() self._recordResult(fitter.params, relError, self.fitModelResult) # Evaluate bootstrap fitter.bootstrap(numIteration=numIteration) if fitter.bootstrapResult is not None: if fitter.bootstrapResult.numSimulation > 0: self._recordResult(fitter.bootstrapResult.params, relError, self.bootstrapResult)
def testUpdateValues(self): if IGNORE_TEST: return MULT = 10 parameters = [SBstoat.Parameter(n, lower=l, upper=u, value=v*MULT) for n, l, u, v in zip(PARAMETER_NAMES, LOWERS, UPPERS, VALUES)] parametersCollection = [[parameters[0]], [parameters[0], parameters[2]], [parameters[1]]] parametersCollection = [ModelFitter.mkParameters(c) for c in parametersCollection] for oldParameters, newParameters in zip(PARAMETERS_COLLECTION, parametersCollection): self.manager.updateValues(newParameters) oldValuesDct = oldParameters.valuesdict() newValuesDct = newParameters.valuesdict() trues = [oldValuesDct[k]*MULT == newValuesDct[k] for k in newValuesDct.keys()] self.assertTrue(all(trues))
def testMakeMethods(self): if IGNORE_TEST: return self._init() METHOD = "dummy" def test(methods): result = ModelFitter.makeMethods(methods, None) self.assertTrue(isinstance(result, list)) optimizerMethod = result[0] self.assertEqual(optimizerMethod.method, METHOD) self.assertTrue(isinstance(optimizerMethod.kwargs, dict)) # test([METHOD]) test([METHOD, METHOD]) test([_helpers.OptimizerMethod(method=METHOD, kwargs={})]) # methods = _helpers.OptimizerMethod(method=METHOD, kwargs={"a": 1}) result = ModelFitter.makeMethods([methods, methods], None)
def main(numIteration): """ Calculates the time to run iterations of the benchmark. Parameters ---------- numIteration: int Returns ------- float: time in seconds """ logger = logs.Logger(logLevel=logs.LEVEL_MAX, logPerformance=IS_TEST) fitter = ModelFitter(MODEL, BENCHMARK_PATH, ["k1", "k2"], selectedColumns=['S1', 'S3'], isPlot=IS_PLOT, logger=logger) fitter.fitModel() startTime = time.time() fitter.bootstrap(numIteration=numIteration, reportInterval=numIteration) elapsedTime = time.time() - startTime if IS_TEST: print(fitter.logger.formatPerformanceDF()) fitter.plotFitAll() return elapsedTime
def mkSuiteFitter(modelSpecifications, datasets, parametersCol, modelNames=None, modelWeights=None, fitterMethods=None, numRestart=0, isParallel=False, logger=Logger(), **kwargs): """ Constructs a SuiteFitterCore with fitters that have similar structure. Parameters ---------- modelSpecifications: list-modelSpecification as in ModelFitter datasets: list-observedData as in ModelFitter paramersCol: list-parametersToFit as in ModelFitter modelNames: list-str modelWeights: list-float how models are weighted in least squares fitterMethods: list-optimization methods numRestart: int number of times the minimization is restarted with random initial values for parameters to fit. isParallel: bool run fits in parallel for each fitter logger: Logger kwargs: dict keyword arguments for ModelFitter Returns ------- SuiteFitter """ modelFitters = [] for modelSpecification, dataset, parametersToFit in \ zip(modelSpecifications, datasets, parametersCol): modelFitter = ModelFitter(modelSpecification, dataset, parametersToFit=parametersToFit, logger=logger, **kwargs) modelFitters.append(modelFitter) return SuiteFitter(modelFitters, modelNames=modelNames, modelWeights=modelWeights, fitterMethods=fitterMethods, numRestart=numRestart, isParallel=isParallel, logger=logger)
def testBootstrapAccuracy(self): if IGNORE_TEST: return model = """ J1: S1 -> S2; k1*S1 J2: S2 -> S3; k2*S2 S1 = 1; S2 = 0; S3 = 0; k1 = 0; k2 = 0; """ columns = ["S1", "S3"] fitter = ModelFitter(model, BENCHMARK_PATH, ["k1", "k2"], selectedColumns=columns, isPlot=IS_PLOT) fitter.fitModel() print(fitter.reportFit()) print(fitter.getParameterMeans()) fitter.bootstrap(numIteration=1000, reportInterval=500) #calcObservedFunc=ModelFitter.calcObservedTSNormal, std=0.01) fitter.plotParameterEstimatePairs(['k1', 'k2'], markersize=2) print("Mean: %s" % str(fitter.getParameterMeans())) print("Std: %s" % str(fitter.getParameterStds())) fitter.reportBootstrap()
def test(methods): result = ModelFitter.makeMethods(methods, None) self.assertTrue(isinstance(result, list)) optimizerMethod = result[0] self.assertEqual(optimizerMethod.method, METHOD) self.assertTrue(isinstance(optimizerMethod.kwargs, dict))
IGNORE_TEST = False IS_PLOT = False NAME = "parameter" LOWER = 1 UPPER = 11 VALUE = 5 MODEL_NAMES = ["W", "X", "Y", "Z"] PARAMETER_NAMES = ["A", "B", "C"] LOWERS = [10, 20, 30] UPPERS = [100, 200, 300] VALUES = [15, 25, 35] PARAMETERS = [SBstoat.Parameter(n, lower=l, upper=u, value=v) for n, l, u, v in zip(PARAMETER_NAMES, LOWERS, UPPERS, VALUES)] PARAMETERS_COLLECTION = [[PARAMETERS[0]], [PARAMETERS[0], PARAMETERS[2]], [PARAMETERS[1]]] PARAMETERS_COLLECTION = [ModelFitter.mkParameters(c) for c in PARAMETERS_COLLECTION] METHODS = [SBstoat.OptimizerMethod("differential_evolution", {cn.MAX_NFEV: 100})] METHODS = [SBstoat.OptimizerMethod("leastsq", {cn.MAX_NFEV: 100})] def mkRepeatedList(list, repeat): return [list for _ in range(repeat)] ################ TEST CLASSES ############# class TestParameter(unittest.TestCase): def setUp(self): self.parameter = _Parameter(NAME, lower=LOWER,
SproutyFunc: -> Spry2; HillTime(V_0, K_0, n_0, t) // Species IVs Spry2 = 0; // Parameter values V_0 = 19.9059673; K_0 = 10153.3568; n_0 = 2.52290790; t := time end ''') # sim = model.simulate(0, 7200, 7201) # model.plot() # quit() fitter = ModelFitter(model, "spry2_2a.txt", ["V_0", "K_0", "n_0"], fitterMethods='differential_evolution', parameterDct={ "V_0": (10, 20, 40), "K_0": (1800, 6000, 20000), "n_0": (1, 2, 12) }) fitter.fitModel() print(fitter.reportFit())
# time in days since volunteer exposure # each line in the array is an individual volunteer #SARS_CoV2_sputum.csv and SARS_CoV2_nasal.csv # SARS-CoV-2 data - 9 patients, # for each patient - viral loads from lungs (sputum) and from nasal cavity (swab) # viral levels in log10(RNA copies / ml sputum), ... # respectively log10(RNA copies / nasal swab) # time in days since symptoms onset # corresponding lines in the two arrays belong to an individual patient #SARS.csv # SARS data recorded from 12 patients; # included them just for comparison, probably too few datapoints for model inference # viral levels in log10(RNA copies / ml of nasopharingeal aspirate) # time - only three samples per patient, at 5, 10 and 15 days post symptoms onset # Fit parameters to ts1 from SBstoat.modelFitter import ModelFitter fitter = ModelFitter(ANTIMONY_MODEL, "Influenza-1.txt", ["beta", "kappa", "delta", "p", "c"]) fitter.fitModel() print(fitter.reportFit()) fitter.plotFitAll(numRow=2, numCol=2) fitter.plotResiduals(numRow=2, numCol=2) # Get estimates of parameters fitter.bootstrap(numIteration=2000, reportInterval=500) print(fitter.getFittedParameterStds())
Kms_2 = 1; Kmp_2 = 1; wi1_2 = 1; wi2_2 = 1; wi3_2 = 1; ms_2 = 1; mp_2 = 1; v_3 = 1; kf_3 = 1; kr_3 = 1; Kms_3 = 1; Kmp_3 = 1; ms_3 = 1; mp_3 = 1; end ''') #model = te.loadSBMLModel("modular_EGFR_current_128.xml") fitter = ModelFitter(model, "StoatSynC.exp", [ "v_0", "ra_0", "kf_0", "kr_0", "Kma_0", "Kms_0", "Kmp_0", "wa_0", "ms_0", "mp_0", "v_1", "ri_1", "kf_1", "kr_1", "Kmi_1", "Kms_1", "Kmp_1", "wi_1", "ms_1", "mp_1", "v_2", "ri1_2", "ri2_2", "ri3_2", "kf_2", "kr_2", "Kmi1_2", "Kmi2_2", "Kmi3_2", "Kms_2", "Kmp_2", "wi1_2", "wi2_2", "wi3_2", "ms_2", "mp_2", "v_3", "kf_3", "kr_3", "Kms_3", "Kmp_3", "ms_3", "mp_3" ]) fitter.fitModel() print(fitter.reportFit())
def __init__(self, modelSpecification, dataSources, dirStudyPath=None, instanceNames=None, logger=Logger(), useSerialized=True, doSerialize=True, isPlot=True, **kwargs): """ Parameters --------- modelSpecification: ExtendedRoadRunner/str roadrunner model or antimony model dataSources: list-NamedTimeseries/list-str or dict of either str: path to CSV file dirStudyPath: str Path to the output directory containing the serialized fitters for the study. instanceNames: list-str Names of study instances corresponds to the list of dataSources useSerialized: bool Use the serialization of each ModelFitter, if it exists doSerialized: bool Serialize each ModelFitter isPlot: bool Do plots kwargs: dict arguments passed to ModelFitter """ self.dirStudyPath = dirStudyPath # Path to the directory serialized ModelFitter if self.dirStudyPath is None: length = len(inspect.stack()) absPath = os.path.abspath((inspect.stack()[length - 1])[1]) dirCaller = os.path.dirname(absPath) self.dirStudyPath = os.path.join(dirCaller, DIR_NAME) self.isPlot = isPlot self.doSerialize = doSerialize self.useSerialized = useSerialized self.instanceNames, self.dataSourceDct = self._mkInstanceData( instanceNames, dataSources) self.fitterPathDct = { } # Path to serialized fitters; key is instanceName self.fitterDct = {} # Fitters: key is instanceName self.logger = logger # Ensure that the directory exists if not os.path.isdir(self.dirStudyPath): os.makedirs(self.dirStudyPath) # Construct the fitters for name, dataSource in self.dataSourceDct.items(): filePath = self._getSerializePath(name) self.fitterPathDct[name] = filePath if os.path.isfile(filePath) and useSerialized: self.fitterDct[name] = ModelFitter.deserialize(filePath) else: self.fitterDct[name] = ModelFitter(modelSpecification, dataSource, logger=self.logger, isPlot=self.isPlot, **kwargs) self._serializeFitter(name)
@author: hsauro @author: joseph-hellerstein """ import SBstoat from SBstoat.modelFitter import ModelFitter from tests import _testHelpers as th import matplotlib import os import unittest IGNORE_TEST = False IS_PLOT = False TIMESERIES = th.getTimeseries() optimizerMethod = ModelFitter.OptimizerMethod(SBstoat.METHOD_LEASTSQ, kwargs={"max_nfev": 100}) FITTER = th.getFitter( cls=ModelFitter, isPlot=IS_PLOT, fitterMethods=[optimizerMethod], bootstrapMethods=[optimizerMethod], ) FITTER.fitModel() FITTER.bootstrap(numIteration=10) ANTIMONY_MODEL_BENCHMARK = """ # Reactions J1: S1 -> S2; k1*S1 J2: S2 -> S3; k2*S2 # Species initializations S1 = 10; S2 = 0; k1 = 1; k2 = 2
def _makeMikeModel(self, **kwargs): """Makes a model from Mike's data.""" model = te.loada(''' function Fi(v, ri, kf, kr, i, s, p, Kmi, Kms, Kmp, wi, ms, mp) ((ri+(1-ri)*(1/(1+i/Kmi)))^wi)*(kf*(s/Kms)^ms-kr*(p/Kmp)^mp)/((1+(s/Kms))^ms+(1+(p/Kmp))^mp-1) end function F0(v, kf, kr, s, p, Kms, Kmp, ms, mp) (kf*(s/Kms)^ms-kr*(p/Kmp)^mp)/((1+(s/Kms))^ms+(1+(p/Kmp))^mp-1) end function Fa(v, ra, kf, kr, a, s, p, Kma, Kms, Kmp, wa, ms, mp) ((ra+(1-ra)*((a/Kma)/(1+a/Kma)))^wa)*(kf*(s/Kms)^ms-kr*(p/Kmp)^mp)/((1+(s/Kms))^ms+(1+(p/Kmp))^mp-1) end function Fiii(v, ri1, ri2, ri3, kf, kr, i1, i2, i3, s, p, Kmi1, Kmi2, Kmi3, Kms, Kmp, wi1, wi2, wi3, ms, mp) ((ri1+(1-ri1)*(1/(1+i1/Kmi1)))^wi1) * ((ri2+(1-ri2)*(1/(1+i2/Kmi2)))^wi2) * ((ri3+(1-ri3)*(1/(1+i3/Kmi3)))^wi3) * (kf*(s/Kms)^ms-kr*(p/Kmp)^mp)/((1+(s/Kms))^ms+(1+(p/Kmp))^mp-1) end model modular_EGFR_current_128() // Reactions FreeLigand: -> L; Fa(v_0, ra_0, kf_0, kr_0, Lp, E, L, Kma_0, Kms_0, Kmp_0, wa_0, ms_0, mp_0); Phosphotyrosine: -> P; Fi(v_1, ri_1, kf_1, kr_1, Mig6, L, P, Kmi_1, Kms_1, Kmp_1, wi_1, ms_1, mp_1); Ras: -> R; Fiii(v_2, ri1_2, ri2_2, ri3_2, kf_2, kr_2, Spry2, P, E, P, R, Kmi1_2, Kmi2_2, Kmi3_2, Kms_2, Kmp_2, wi1_2, wi2_2, wi3_2, ms_2, mp_2); Erk: -> E; F0(v_3, kf_3, kr_3, R, E, Kms_3, Kmp_3, ms_3, mp_3); // Species IVs Lp = 100; E = 0; L = 1000; Mig6 = 100; P = 0; Spry2 = 10000; R = 0; // Parameter values v_0 = 1; ra_0 = 1; kf_0 = 1; kr_0 = 1; Kma_0 = 1; Kms_0 = 1; Kmp_0 = 1; wa_0 = 1; ms_0 = 1; mp_0 = 1; v_1 = 1; ri_1 = 1; kf_1 = 1; kr_1 = 1; Kmi_1 = 1; Kms_1 = 1; Kmp_1 = 1; wi_1 = 1; ms_1 = 1; mp_1 = 1; v_2 = 1; ri1_2 = 1; ri2_2 = 1; ri3_2 = 1; kf_2 = 1; kr_2 = 1; Kmi1_2 = 1; Kmi2_2 = 1; Kmi3_2 = 1; Kms_2 = 1; Kmp_2 = 1; wi1_2 = 1; wi2_2 = 1; wi3_2 = 1; ms_2 = 1; mp_2 = 1; v_3 = 1; kf_3 = 1; kr_3 = 1; Kms_3 = 1; Kmp_3 = 1; ms_3 = 1; mp_3 = 1; end ''') observedPath = os.path.join(DIR, "mike_bug.csv") fitter = ModelFitter(model, observedPath, [ #"v_0", "ra_0", "kf_0", "kr_0", "Kma_0", "Kms_0", "Kmp_0", "wa_0", "ms_0", #"mp_0", "v_1", "ri_1", "kf_1", "kr_1", "Kmi_1", "Kms_1", "Kmp_1", "wi_1", #"ms_1", "mp_1", "v_2", "ri1_2", "ri2_2", "ri3_2", "kf_2", "kr_2", "Kmi1_2", "Kmi2_2", "Kmi3_2", "Kms_2", "Kmp_2", "wi1_2", "wi2_2", "wi3_2", "ms_2", "mp_2", "v_3", "kf_3", "kr_3", "Kms_3", "Kmp_3", "ms_3", "mp_3"], **kwargs) fitter.fitModel() return fitter