def __init__(self, prototypeTS: NamedTimeseries, percentiles: list = None): """ Parameters ---------- prototypeTS: same length and columns as desired percentiles: percentiles to calculate for accumulated Timeseries """ # Statistics if prototypeTS is not None: self.count = 0 # Count of timeseries accumulated self.prototypeTS = prototypeTS self.colnames = self.prototypeTS.colnames self.sumTS = self.prototypeTS.copy(isInitialize=True) self.ssqTS = self.prototypeTS.copy(isInitialize=True) if percentiles is None: percentiles = PERCENTILES self.percentiles = percentiles self._timeseries_list = [] # List of timeseries accumulated # Means self.meanTS = prototypeTS.copy(isInitialize=True) # means # Standard deviations self.stdTS = prototypeTS.copy( isInitialize=True) # standard deviations # Percentiles self.percentileDct = {} # Key: percentile; Value: Timeseries else: # rpConstruct initializations. pass
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 __init__(self, observedTS:NamedTimeseries, fittedTS:NamedTimeseries, residualsTS:NamedTimeseries=None, meanFittedTS=None, stdFittedTS=None, bandLowTS:NamedTimeseries=None, bandHighTS:NamedTimeseries=None, isPlot:bool=True): """ Parameters ---------- observedTS: Observed values residualsTS: same time values as observedTS fittedTS: fitted values may have different times than observedTS meanFittedTS: fitted values with same times as observedTS stdFittedTS: fitted values with same times as observedTS bandLowTS: timeseries that describes the lower band for timeseries1 bandhighTS: timeseries that describes the higher band for timeseries1 """ self.observedTS = observedTS self.fittedTS = fittedTS self.meanFittedTS = meanFittedTS self.stdFittedTS = stdFittedTS self.bandLowTS = bandLowTS self.bandHighTS = bandHighTS if residualsTS is None: self.residualsTS = self.observedTS.copy() cols = self.residualsTS.colnames self.residualsTS[cols] -= self.fittedTS[cols] self.residualsTS[cols] \ = np.nan_to_num(self.residualsTS[cols], nan=0.0) else: self.residualsTS = residualsTS.copy() ### Plotter self._plotter = tp.TimeseriesPlotter(isPlot=isPlot)
def _adjustNames(self, antimonyModel:str, observedTS:NamedTimeseries) \ ->typing.Tuple[NamedTimeseries, list]: """ Antimony exports can change the names of floating species by adding a "_" at the end. Check for this and adjust the names in observedTS. Return ------ NamedTimeseries: newObservedTS list: newSelectedColumns """ rr = te.loada(antimonyModel) dataNames = rr.simulate().colnames names = ["[%s]" % n for n in observedTS.colnames] missingNames = [n[1:-1] for n in set(names).difference(dataNames)] newSelectedColumns = list(self.selectedColumns) if len(missingNames) > 0: newObservedTS = observedTS.copy() self.logger.exception("Missing names in antimony export: %s" % str(missingNames)) for name in observedTS.colnames: missingName = "%s_" % name if name in missingNames: newObservedTS = newObservedTS.rename(name, missingName) newSelectedColumns.remove(name) newSelectedColumns.append(missingName) else: newObservedTS = observedTS return newObservedTS, newSelectedColumns
def _mkTimeseries(numRow=NUM_ROW, numCol=NUM_COL, std=STD): colnames = ["V%d" % d for d in range(NUM_COL)] allColnames = list(colnames) allColnames.insert(0, TIME) timeArr = np.array(range(NUM_ROW)) timeArr = np.reshape(timeArr, (NUM_ROW, 1)) # def addTime(arr): newArr = np.concatenate([timeArr, arr], axis=1) return newArr # residualsTS = NamedTimeseries(array=addTime( np.random.normal(0, std, (numRow, numCol))), colnames=allColnames) fittedTS = NamedTimeseries(array=addTime( np.random.normal(MEAN, 10 * std, (numRow, numCol))), colnames=allColnames) fittedTS[colnames] = np.floor(fittedTS[colnames]) observedTS = fittedTS.copy() observedTS[colnames] += residualsTS[colnames] return observedTS, fittedTS, residualsTS
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))
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 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()