def setUp(self): self.timeseries = NamedTimeseries(csvPath=TEST_DATA_PATH) self.model = te.loada(ANTIMONY_MODEL)
def testMissingData(self): if IGNORE_TEST: return with self.assertRaises(ValueError): timeseries = NamedTimeseries(csvPath=TEST_BAD_DATA_PATH)
class TestNamedTimeseries(unittest.TestCase): def setUp(self): self.timeseries = NamedTimeseries(csvPath=TEST_DATA_PATH) self.model = te.loada(ANTIMONY_MODEL) def tearDown(self): if os.path.isfile(TEMP_FILE): os.remove(TEMP_FILE) def testConstructor1(self): if IGNORE_TEST: return self.assertGreater(len(self.timeseries.values), 0) # colnames doesn't include TIME self.assertEqual(len(self.timeseries.colnames), np.shape(self.timeseries.values)[1] - 1) # newTS = self.timeseries.copy(isInitialize=True) self.assertEqual(np.sum(newTS[self.timeseries.colnames[0]]), 0) def testConstructor2(self): if IGNORE_TEST: return COLNAMES = [TIME, "S1", "S2"] def test(timeseries, colnames=COLNAMES): for name in colnames: self.assertTrue( np.isclose(sum(timeseries[name] - self.timeseries[name]), 0)) # newTS = NamedTimeseries(colnames=COLNAMES, array=self.timeseries[COLNAMES]) test(newTS) # Check can use different cases for TIME newTS = NamedTimeseries(colnames=["Time", "S1", "S2"], array=self.timeseries[COLNAMES]) test(newTS) def testConstructorNamedArray(self): if IGNORE_TEST: return namedArray = self.model.simulate(0, 100, 30) ts = NamedTimeseries(namedArray=namedArray) self.assertTrue( namedTimeseries.arrayEquals(namedArray.flatten(), ts.values.flatten())) def testSizeof(self): if IGNORE_TEST: return self.assertEqual(len(self.timeseries), LENGTH) def testGetitem(self): if IGNORE_TEST: return times = self.timeseries[TIME] # Access time column with different case refs = ["TiMe", "S1"] self.assertTrue( namedTimeseries.arrayEquals(self.timeseries[refs], self.timeseries[refs])) self.assertTrue( namedTimeseries.arrayEquals(self.timeseries[TIME], self.timeseries["TimE"])) self.assertTrue( namedTimeseries.arrayEquals(self.timeseries[TIME], self.timeseries["TimE"])) self.assertEqual(len(times), len(self.timeseries)) self.assertEqual(min(times), self.timeseries.start) self.assertEqual(max(times), self.timeseries.end) # Get multiple values at once values = self.timeseries[self.timeseries.colnames] trues = np.array([ v1 == v2 for v1, v2 in zip(values, self.timeseries.values[:, 1:]) ]) self.assertTrue(all(trues.flatten())) def testMissingData(self): if IGNORE_TEST: return with self.assertRaises(ValueError): timeseries = NamedTimeseries(csvPath=TEST_BAD_DATA_PATH) def testCopyExisting(self): if IGNORE_TEST: return timeseries = NamedTimeseries(timeseries=self.timeseries) # def checkVector(attribute): length = len(self.timeseries.__getattribute__(attribute)) trues = [ timeseries.__getattribute__(attribute)[k] == self.timeseries.__getattribute__(attribute)[k] for k in range(length) ] self.assertTrue(all(trues)) def checkMatrix(attribute): trues = [] for rowIdx, row in enumerate( timeseries.__getattribute__(attribute)): for colIdx, val in enumerate(row): trues.append(val == self.timeseries.__getattribute__( attribute)[rowIdx, colIdx]) self.assertTrue(all(trues)) # for variable in ["start", "end"]: self.assertEqual(timeseries.__getattribute__(variable), self.timeseries.__getattribute__(variable)) for variable in ["colnames"]: checkVector(variable) for variable in ["values"]: checkMatrix(variable) def testFlattenValues(self): if IGNORE_TEST: return values = self.timeseries.flatten() self.assertTrue( np.isclose(sum(values - self.timeseries.values[:, 1:].flatten()), 0)) def testSelectTimes(self): if IGNORE_TEST: return selectorFunction = lambda t: t > 2 array = self.timeseries.selectTimes(selectorFunction) self.assertLess(len(array), len(self.timeseries)) def testMkNamedTimeseries(self): if IGNORE_TEST: return # Create a new time series that subsets the old one colnames = ["time", "S1", "S2"] newTS = namedTimeseries.mkNamedTimeseries(colnames, self.timeseries[colnames]) self.assertEqual(len(self.timeseries), len(newTS)) # Create a new timeseries with a subset of times array = self.timeseries.selectTimes(lambda t: t > 2) newTS = namedTimeseries.mkNamedTimeseries(self.timeseries.allColnames, array) self.assertGreater(len(self.timeseries), len(newTS)) # ts = mkNamedTimeseries(self.timeseries) self.assertTrue(self.timeseries.equals(ts)) # ts = mkNamedTimeseries(TEST_DATA_PATH) self.assertTrue(self.timeseries.equals(ts)) # with self.assertRaises(ValueError): ts = mkNamedTimeseries(3) def testToPandas(self): if IGNORE_TEST: return df = self.timeseries.to_dataframe() timeseries = NamedTimeseries(dataframe=df) diff = set(df.columns).symmetric_difference(timeseries.colnames) self.assertEqual(len(diff), 0) total = sum(timeseries.values.flatten() - self.timeseries.values.flatten()) self.assertTrue(np.isclose(total, 0)) def testArrayEquals(self): if IGNORE_TEST: return arr1 = np.array([1, 2, 3, 4]) arr1 = np.reshape(arr1, (2, 2)) self.assertTrue(namedTimeseries.arrayEquals(arr1, arr1)) arr2 = 1.0001 * arr1 self.assertFalse(namedTimeseries.arrayEquals(arr1, arr2)) def testEquals(self): if IGNORE_TEST: return self.assertTrue(self.timeseries.equals(self.timeseries)) newTS = self.timeseries.copy() newTS["S1"] = -1 self.assertFalse(self.timeseries.equals(newTS)) def testCopy(self): if IGNORE_TEST: return ts2 = self.timeseries.copy() self.assertTrue(self.timeseries.equals(ts2)) def testSetitem(self): if IGNORE_TEST: return self.timeseries["S1"] = self.timeseries["S2"] self.assertTrue( namedTimeseries.arrayEquals(self.timeseries["S1"], self.timeseries["S2"])) value = -20 self.timeseries["S19"] = value self.assertEqual(self.timeseries["S19"].sum(), len(self.timeseries) * value) def testGetitemRows(self): if IGNORE_TEST: return start = 1 stop = 3 ts1 = self.timeseries[start:stop] self.assertTrue(isinstance(ts1, NamedTimeseries)) self.assertEqual(len(ts1), stop - start) # ts2 = self.timeseries[[1, 2]] self.assertTrue(ts1.equals(ts2)) # ts3 = self.timeseries[1] self.assertEqual(np.shape(ts3.values), (1, len(ts2.allColnames))) def testExamples(self): if IGNORE_TEST: return # Create from file timeseries = NamedTimeseries(csvPath=TEST_DATA_PATH) # NamedTimeseries can use len function length = len(timeseries) # number of rows # Extract the numpy array values using indexing timeValues = timeseries["time"] s1Values = timeseries["S1"] # Get the start and end times startTime = timeseries.start endTime = timeseries.end # Create a new time series that subsets the variables of the old one colnames = ["time", "S1", "S2"] newTS = mkNamedTimeseries(colnames, timeseries[colnames]) # Create a new timeseries that excludes time 0 ts2 = timeseries[1:] # Create a new column variable timeseries["S8"] = timeseries["time"]**2 + 3 * timeseries["S1"] timeseries["S9"] = 10 # Assign a constant to all rows def testDelitem(self): if IGNORE_TEST: return ts1 = self.timeseries.copy() del ts1["S1"] stg = str(ts1) self.assertEqual(len(ts1), len(self.timeseries)) self.assertEqual(len(ts1.colnames) + 1, len(self.timeseries.colnames)) def testToCsv(self): if IGNORE_TEST: return self.timeseries.to_csv(TEMP_FILE) self.assertTrue(os.path.isfile(TEMP_FILE)) def testConcatenateColumns(self): if IGNORE_TEST: return ts = self.timeseries.concatenateColumns(self.timeseries) newNames = ["%s_" % c for c in self.timeseries.colnames] self.assertTrue( namedTimeseries.arrayEquals( ts[newNames], self.timeseries[self.timeseries.colnames])) self.assertEqual(len(ts), len(self.timeseries)) self.assertTrue( namedTimeseries.arrayEquals(ts[TIME], self.timeseries[TIME])) # ts = self.timeseries.concatenateColumns( [self.timeseries, self.timeseries]) self.assertEqual(3 * len(self.timeseries.colnames), len(ts.colnames)) def testConcatenateRows(self): if IGNORE_TEST: return ts = self.timeseries.concatenateRows(self.timeseries) diff = set(ts.colnames).symmetric_difference(self.timeseries.colnames) self.assertEqual(len(diff), 0) length = len(self.timeseries) ts1 = ts[length:] self.assertTrue(self.timeseries.equals(ts1)) # ts = self.timeseries.concatenateRows( [self.timeseries, self.timeseries]) self.assertEqual(3 * len(self.timeseries), len(ts)) def testSubsetColumns(self): if IGNORE_TEST: return ts = self.timeseries.concatenateColumns(self.timeseries) ts1 = ts.subsetColumns(self.timeseries.colnames) self.assertTrue(self.timeseries.equals(ts1)) def testGetTimes(self): if IGNORE_TEST: return SIZE = 10 VALUE = "values" TIMES = np.array(range(SIZE)) def test(values, reference): df = pd.DataFrame({TIME: TIMES, VALUE: values}) ts = NamedTimeseries(dataframe=df) results = ts.getTimesForValue(VALUE, reference) for time in results: idx1 = int(time) idx2 = idx1 + 1 small = min(ts[VALUE][idx1], ts[VALUE][idx2]) large = max(ts[VALUE][idx1], ts[VALUE][idx2]) self.assertLessEqual(small, reference) self.assertGreaterEqual(large, reference) # values = (TIMES - 5)**2 test(values, 10) # 2 times test(-values, 5) # Single maxk def testRpickleInterface(self): if IGNORE_TEST: return serialization = rpickle.Serialization(self.timeseries) timeseries = serialization.deserialize() self.assertTrue(timeseries.equals(self.timeseries)) def testRename(self): if IGNORE_TEST: return NEW_NAME = "T1" OLD_NAME = "S1" newTimeseries = self.timeseries.rename(OLD_NAME, NEW_NAME) self.assertTrue(NEW_NAME in newTimeseries.colnames) self.assertFalse(OLD_NAME in newTimeseries.colnames) del newTimeseries[NEW_NAME] del self.timeseries[OLD_NAME] self.assertTrue(newTimeseries.equals(self.timeseries))
def setUp(self): self.timeseries = NamedTimeseries(csvPath=TEST_DATA_PATH) self.plotter = TimeseriesPlotter(isPlot=IS_PLOT)
def getTS(data): if isinstance(data, pd.DataFrame): return NamedTimeseries(dataframe=data) return data
def plotTimeSingle(self, timeseries1:NamedTimeseries, meanTS:NamedTimeseries=None, stdTS:NamedTimeseries=None, bandLowTS:NamedTimeseries=None, bandHighTS:NamedTimeseries=None, ax_spec=None, position=None, **kwargs): """ Constructs plots of single columns, possibly with a second timeseries. Parameters --------- timeseries1: timeseries to plot meanTS: mean values of timeseries to plot stdTS: standard deviations of meanTS (same times) bandLowTS: timeseries that describes the lower band for timeseries1 bandhighTS: timeseries that describes the higher band for timeseries1 ax_spec: Optionally specified axis for all lines position: (int, int) - position of ax_spec #@expand Example ------- plotter = TimeseriesPlotter() plotter.plotTimeSingle(timeseries) """ options = self._mkPlotOptionsMatrix(timeseries1, **kwargs) # Adjust rows and columns numPlot = len(options.columns) # Number of plots if po.NUM_COL in kwargs.keys(): options.numRow = int(np.ceil(numPlot/options.numCol)) else: options.numCol = int(np.ceil(numPlot/options.numRow)) options.set(po.XLABEL, TIME) # Create the LayoutManager if ax_spec is None: layout = self._mkManager(options, numPlot) else: layout = None # def mkStatement(ax, statement:StatementManager, timeseries:NamedTimeseries, variable:str): """ Creates a plotting statement. Parameters ---------- ax: plotting axes initialStatement: statement if initialized timeseries: what to plot variable: variable to plot Returns ------- StatementManager """ times, values = self._adjustSeriesForNan( timeseries[TIME], timeseries[variable]) statement.addPosarg(times) statement.addPosarg(values) return statement # def isFirstColumn(plotIdx): if layout is not None: return layout.isFirstColumn(plotIdx) else: if position is not None: return position[1] == 0 else: return True # def isLastRow(plotIdx): if layout is not None: return layout.isLastRow(plotIdx) else: if po.NUM_ROW in kwargs.keys(): numRow = kwargs[po.NUM_ROW] else: return True if position is None: return True return position[0] + 1 == numRow # def mkBand(ts, variable, plotIdx, lineIdx): initialStatement = StatementManager(ax.fill_between) statement = mkStatement(ax, initialStatement, timeseries1, variable) statement.addPosarg(ts[variable]) statement.addKwargs(alpha=0.2) options.do(ax, statement=statement, plotIdx=plotIdx, lineIdx=lineIdx) # # Construct the plots baseOptions = copy.deepcopy(options) for plotIdx, variable in enumerate(options.columns): if ax_spec is None: ax = layout.getAxis(plotIdx) else: ax = ax_spec options = copy.deepcopy(baseOptions) #ax = axes[row, col] options.set(po.YLABEL, "concentration") options.set(po.TITLE, variable) if not isFirstColumn(plotIdx): options.ylabel = NULL_STR options.set(po.YLABEL, "", isOverride=True) if not isLastRow(plotIdx): options.set(po.XLABEL, "", isOverride=True) # Construct the plot lineIdx = 0 initialStatement = StatementManager(ax.plot) statement = mkStatement(ax, initialStatement, timeseries1, variable) options.do(ax, statement=statement, plotIdx=plotIdx, lineIdx=lineIdx) legends = [] if options.timeseries2 is not None: lineIdx = 1 initialStatement = StatementManager(ax.plot) if options.marker is not None: if len(options.marker) > 1: if options.marker[lineIdx] is not None: initialStatement = StatementManager(ax.scatter) elif options.marker is not None: initialStatement = StatementManager(ax.scatter) statement = mkStatement(ax, initialStatement, options.timeseries2, variable) legends = [LABEL1, LABEL2] options.lengends = legends options.do(ax, statement=statement, plotIdx=plotIdx, lineIdx=lineIdx) if meanTS is not None: if stdTS is None: stdTS = meanTS.copy(isInitialize=True) lineIdx = 2 initialStatement = StatementManager(ax.scatter) statement = mkStatement(ax, initialStatement, meanTS, variable) options.marker = "^" statement.addKwargs(facecolors="none") options.do(ax, statement=statement, plotIdx=plotIdx, lineIdx=lineIdx) # initialStatement = StatementManager(ax.errorbar) statement = mkStatement(ax, initialStatement, meanTS, variable) statement.addKwargs(yerr=stdTS[variable]) statement.addKwargs(linestyle="none") legends.append("Bootstrap mean") options.lengends = legends options.do(ax, statement=statement, plotIdx=plotIdx, lineIdx=lineIdx) if bandLowTS is not None: lineIdx = 0 mkBand(bandLowTS, variable, plotIdx, lineIdx) if bandHighTS is not None: lineIdx = 0 mkBand(bandHighTS, variable, plotIdx, lineIdx) if self.isPlot: plt.show()
class TestTimeseriesPlotter(unittest.TestCase): def setUp(self): self.timeseries = NamedTimeseries(csvPath=TEST_DATA_PATH) self.plotter = TimeseriesPlotter(isPlot=IS_PLOT) def testConstructor1(self): if IGNORE_TEST: return self.assertTrue(isinstance(self.plotter.isPlot, bool)) def testInitializeRowColumn(self): if IGNORE_TEST: return def test(maxCol, **kwargs): options = self.plotter._mkPlotOptionsMatrix(self.timeseries, maxCol=maxCol, **kwargs) if po.NUM_ROW in kwargs: self.assertGreaterEqual(options.numRow, kwargs[po.NUM_ROW]) if po.NUM_COL in kwargs: self.assertEqual(options.numCol, kwargs[po.NUM_COL]) # test(3, **{}) test(3, **{po.NUM_COL: 3}) test(4, **{po.NUM_ROW: 2}) test(5, **{po.NUM_ROW: 2}) def testPlotSingle1(self): if IGNORE_TEST: return self.plotter.plotTimeSingle(self.timeseries, timeseries2=self.timeseries, numCol=4, marker=[None, '*'], alpha=[0.1, 0.8], color=["red", "g"], titlePosition=[0.8, 0.5], titleFontsize=10) self.plotter.plotTimeSingle(self.timeseries, numCol=4, marker=[None, '*']) self.plotter.plotTimeSingle(self.timeseries, numCol=4, subplotWidthSpace=0.2, yticklabels=[]) self.plotter.plotTimeSingle(self.timeseries, columns=["S1", "S2", "S3"], numRow=2) self.plotter.plotTimeSingle(self.timeseries, numCol=4) self.plotter.plotTimeSingle(self.timeseries, numCol=2) self.plotter.plotTimeSingle(self.timeseries, numRow=2, numCol=3, ylabel="xxx") self.plotter.plotTimeSingle(self.timeseries, columns=["S1", "S2"]) def testPlotSingle5(self): if IGNORE_TEST: return timeseries = self.timeseries.subsetColumns(["S1"]) dct = {} indices = [i for i in range(len(timeseries)) if i % 4 == 0] for col in timeseries.allColnames: dct[col] = timeseries[col][indices] df = pd.DataFrame(dct) meanTS = NamedTimeseries(dataframe=df) meanTS[meanTS.colnames] = 1.1 * meanTS[meanTS.colnames] stdTS = meanTS.copy() for col in meanTS.colnames: stdTS[col] = 1 # self.plotter.plotTimeSingle(timeseries, timeseries2=self.timeseries, meanTS=meanTS, stdTS=stdTS, marker=[None, 'o', "^"], color=["b", "r", "g"]) # self.plotter.plotTimeSingle(timeseries, meanTS=meanTS, stdTS=stdTS) # self.plotter.plotTimeSingle(timeseries, timeseries2=self.timeseries, marker='*') def testPlotSingle6(self): if IGNORE_TEST: return numCol = 3 numRow = 2 fig, axes = plt.subplots(numRow, numCol) self.plotter.isPlot = False for idx in range(numCol * numRow): if idx < numCol: row = 0 col = idx else: row = 1 col = idx - numCol position = [row, col] ax = axes[row, col] ts = self.timeseries.subsetColumns(self.timeseries.colnames[idx]) self.plotter.plotTimeSingle(ts, ax_spec=ax, position=position, numRow=2) if IS_PLOT: plt.show() def testPlotSingle7(self): if IGNORE_TEST: return def setTS(ts, frac): ts = self.timeseries.copy() for col in ts.colnames: ts[col] = frac * ts[col] return ts # numCol = 3 numRow = 2 fig, axes = plt.subplots(numRow, numCol) self.plotter.isPlot = False tsLower = setTS(self.timeseries, 0.7) tsUpper = setTS(self.timeseries, 1.5) for idx in range(numCol * numRow): if idx < numCol: row = 0 col = idx else: row = 1 col = idx - numCol position = [row, col] ax = axes[row, col] ts = self.timeseries.subsetColumns(self.timeseries.colnames[idx]) self.plotter.plotTimeSingle(ts, ax_spec=ax, position=position, bandLowTS=tsLower, bandHighTS=tsUpper, numRow=2) if IS_PLOT: plt.show() def testPlotSingle8(self): # Plot with nan values if IGNORE_TEST: return def setTS(ts, mult, numNan): ts = self.timeseries.copy() for col in ts.colnames: ts[col] = mult * ts[col] ts[col][:numNan] = np.nan return ts # numCol = 3 numRow = 2 timeseries2 = setTS(self.timeseries, 2, 3) self.plotter.plotTimeSingle(self.timeseries, timeseries2=timeseries2, columns=["S1"], numRow=numRow, numCol=numCol) if IS_PLOT: plt.show() def mkTimeseries(self): ts2 = self.timeseries.copy() ts2[ts2.colnames] = ts2[ts2.colnames] + np.multiply( ts2[ts2.colnames], ts2[ts2.colnames]) return ts2 def testPlotSingle2(self): if IGNORE_TEST: return ts2 = self.mkTimeseries() self.plotter.plotTimeSingle(self.timeseries, timeseries2=ts2, columns=["S1", "S2"]) self.plotter.plotTimeSingle(self.timeseries, timeseries2=ts2) self.plotter.plotTimeSingle(self.timeseries, timeseries2=ts2, numRow=2, numCol=3) def testPlotSingle3(self): if IGNORE_TEST: return self.plotter.plotTimeSingle(self.timeseries, ylabel="MISSING") def testPlotSingle4(self): if IGNORE_TEST: return ts2 = self.mkTimeseries() self.plotter.plotTimeSingle(self.timeseries, markersize=[2, 5], timeseries2=ts2, numRow=2, numCol=3, marker=[None, "o"]) self.plotter.plotTimeSingle(self.timeseries, timeseries2=ts2, numRow=2, numCol=3, marker=[None, "o"], alpha=0.1) def testPlotMultiple1(self): if IGNORE_TEST: return ts2 = self.mkTimeseries() self.plotter.plotTimeMultiple( self.timeseries, timeseries2=ts2, suptitle="Testing", marker=[None, 'o', None, None, None, None], color=['r', 'g', 'b', 'brown', 'g', 'pink'], alpha=0.3) self.plotter.plotTimeMultiple(self.timeseries, timeseries2=ts2, suptitle="Testing", numRow=1, numCol=1, marker="o") self.plotter.plotTimeMultiple(self.timeseries, timeseries2=ts2, suptitle="Testing", numRow=2, marker="o") self.plotter.plotTimeMultiple(self.timeseries, suptitle="Testing") def testValuePairs(self): if IGNORE_TEST: return ts2 = self.mkTimeseries() self.plotter.plotValuePairs(self.timeseries, [("S1", "S2"), ("S2", "S3"), ("S4", "S5")], numCol=2, numRow=2, alpha=0.3) self.plotter.plotValuePairs(self.timeseries, [("S1", "S2"), ("S2", "S3")], numRow=2) self.plotter.plotValuePairs(self.timeseries, [("S1", "S2")]) def testPlotHistograms(self): if IGNORE_TEST: return self.plotter.plotHistograms(self.timeseries, numCol=2, alpha=0.3) self.plotter.plotHistograms(self.timeseries, numCol=2, alpha=0.3, bins=100) def testPlotValuePairsBug(self): if IGNORE_TEST: return self.plotter.plotValuePairs(self.timeseries, pairs=[("S1", "S2"), ("S1", "S6"), ("S2", "S3")], numCol=3) def testPlotCompare(self): if IGNORE_TEST: return self.plotter.plotCompare(self.timeseries, self.timeseries, numCol=3) def testPlotAutoCorrelations(self): if IGNORE_TEST: return self.plotter.plotAutoCorrelations(self.timeseries, numCol=3, color=["black", "grey", "grey"], linestyle=[None, "dashed", "dashed"], alpha=[None, 0.5, 0.5]) def testPlotCrossCorrelations(self): if IGNORE_TEST: return self.plotter.plotCrossCorrelations(self.timeseries, titleFontsize=8, titlePosition=(0.8, 0.8), suptitle="Cross Correlations", color=["black", "g", "g"], figsize=(12, 10))
def _mkParameterDF(self, parameters=None): df = pd.DataFrame(self.bootstrapResult.parameterDct) if parameters is not None: df = df[parameters] df.index.name = TIME return NamedTimeseries(dataframe=df)
def mkTimeSeries(self, values, name): numPoint = len(values) arr = np.array([range(numPoint), values]) arr = np.resize(arr, (2, numPoint)) arr = arr.transpose() return NamedTimeseries(array=arr, colnames=["time", name])
def copy(self, isKeepLogger=False, isKeepOptimizer=False, **kwargs): """ Creates a copy of the model fitter, overridding any argument that is not None. Preserves the user-specified settings and the results of bootstrapping. Parameters ---------- isKeepLogger: bool isKeepOptimizer: bool kwargs: dict arguments to override in copy Returns ------- ModelFitter """ def setValues(names): """ Sets the value for a list of names. Parameters ---------- names: list-str Returns ------- list-object """ results = [] for name in names: altName = "_%s" % name if name in kwargs.keys(): results.append(kwargs[name]) elif name in self.__dict__.keys(): results.append(self.__dict__[name]) elif altName in self.__dict__.keys(): results.append(self.__dict__[altName]) else: raise RuntimeError("%s: not found" % name) return results # # Get the positional and keyword arguments inspectResult = inspect.getfullargspec(ModelFitterCore.__init__) allArgNames = inspectResult.args[1:] # Ignore 'self' if inspectResult.defaults is None: numKwarg = 0 else: numKwarg = len(inspectResult.defaults) numParg = len(allArgNames) - numKwarg # positional arguments pargNames = allArgNames[:numParg] kwargNames = allArgNames[numParg:] # Construct the arguments callPargs = setValues(pargNames) callKwargValues = setValues(kwargNames) callKwargs = {n: v for n, v in zip(kwargNames, callKwargValues)} if numKwarg > 0: # Adjust model specification modelSpecificationIdx = pargNames.index("modelSpecification") observedDataIdx = pargNames.index("observedData") modelSpecification = callPargs[modelSpecificationIdx] observedTS = NamedTimeseries(callPargs[observedDataIdx]) selectedColumns = callKwargs["selectedColumns"] if not isinstance(modelSpecification, str): try: modelSpecification = self.modelSpecification.getAntimony() callPargs[modelSpecificationIdx] = modelSpecification observedTS, selectedColumns = self._adjustNames( modelSpecification, observedTS) callPargs[observedDataIdx] = observedTS callKwargs["selectedColumns"] = selectedColumns except Exception as err: self.logger.error( "Problem wth conversion to Antimony. Details:", err) raise ValueError("Cannot proceed.") # if isKeepLogger: callKwargs["logger"] = self.logger if numParg < 2: callPargs = [None, None] newModelFitter = self.__class__(*callPargs, **callKwargs) if self.optimizer is not None: if isKeepOptimizer: newModelFitter.optimizer = self.optimizer.copyResults() if self.bootstrapResult is not None: newModelFitter.bootstrapResult = self.bootstrapResult.copy() return newModelFitter
def simulate(self, params=None, startTime=None, endTime=None, numPoint=None): """ Runs a simulation. Defaults to parameter values in the simulation. Parameters ---------- params: lmfit.Parameters startTime: float endTime: float numPoint: int Return ------ NamedTimeseries """ def set(default, parameter): # Sets to default if parameter unspecified if parameter is None: return default else: return parameter ##V block = Logger.join(self._loggerPrefix, "fitModel.simulate") guid = self.logger.startBlock(block) ## V sub1Block = Logger.join(block, "sub1") sub1Guid = self.logger.startBlock(sub1Block) startTime = set(self.observedTS.start, startTime) endTime = set(self.observedTS.end, endTime) numPoint = set(len(self.observedTS), numPoint) ## V sub1aBlock = Logger.join(sub1Block, "sub1a") sub1aGuid = self.logger.startBlock(sub1aBlock) if self.roadrunnerModel is None: self._initializeRoadrunnerModel() self.roadrunnerModel.reset() ## ^ self.logger.endBlock(sub1aGuid) ## V sub1bBlock = Logger.join(sub1Block, "sub1b") sub1bGuid = self.logger.startBlock(sub1bBlock) if params is not None: # Parameters have been specified self._setupModel(params) ## ^ self.logger.endBlock(sub1bGuid) # Do the simulation selectedColumns = list(self.selectedColumns) if not TIME in selectedColumns: selectedColumns.insert(0, TIME) ## ^ self.logger.endBlock(sub1Guid) ## V roadrunnerBlock = Logger.join(block, "roadrunner") roadrunnerGuid = self.logger.startBlock(roadrunnerBlock) data = self.roadrunnerModel.simulate(startTime, endTime, numPoint, selectedColumns) self.logger.endBlock(roadrunnerGuid) ## ^ # Select the required columns ## V sub2Block = Logger.join(block, "sub2") sub2Guid = self.logger.startBlock(sub2Block) fittedTS = NamedTimeseries(namedArray=data) self.logger.endBlock(sub2Guid) ## ^ self.logger.endBlock(guid) ##^ return fittedTS
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 TIME not 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 parametersToFit = [] for name in self.parameterValueDct.keys(): lower = self.parameterValueDct[name] * (1 - fractionParameterDeviation) upper = self.parameterValueDct[name] * (1 + fractionParameterDeviation) value = np.random.uniform(lower, upper) parametersToFit.append( SBstoat.Parameter(name, lower=lower, upper=upper, value=value)) # Create the fitter fitter = ModelFitter(self.roadRunner, observedTS, selectedColumns=self.selectedColumns, parametersToFit=parametersToFit, **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 runSimulation( cls, parameters=None, roadrunner=None, startTime=0, endTime=5, numPoint=30, selectedColumns=None, returnDataFrame=True, _logger=Logger(), _loggerPrefix="", ): """ Runs a simulation. Defaults to parameter values in the simulation. Parameters ---------- roadrunner: ExtendedRoadRunner/str Roadrunner model parameters: lmfit.Parameters lmfit parameters startTime: float start time for the simulation endTime: float end time for the simulation numPoint: int number of points in the simulation selectedColumns: list-str output columns in simulation returnDataFrame: bool return a DataFrame _logger: Logger _loggerPrefix: str Return ------ NamedTimeseries (or None if fail to converge) """ if isinstance(roadrunner, str): roadrunner = cls.initializeRoadrunnerModel(roadrunner) else: roadrunner.reset() if parameters is not None: # Parameters have been specified cls.setupModel(roadrunner, parameters, logger=_logger) # Do the simulation if selectedColumns is not None: newSelectedColumns = list(selectedColumns) if TIME not in newSelectedColumns: newSelectedColumns.insert(0, TIME) try: data = roadrunner.simulate(startTime, endTime, numPoint, newSelectedColumns) except Exception as err: _logger.error("Roadrunner exception: ", err) data = None else: try: data = roadrunner.simulate(startTime, endTime, numPoint) except Exception as err: _logger.exception("Roadrunner exception: %s", err) data = None if data is None: return data fittedTS = NamedTimeseries(namedArray=data) if returnDataFrame: result = fittedTS.to_dataframe() else: result = fittedTS return result
def getTimeseries(): return NamedTimeseries(csvPath=TEST_DATA_PATH)