def test_RRuleLocator(): import matplotlib.testing.jpl_units as units units.register() # This will cause the RRuleLocator to go out of bounds when it tries # to add padding to the limits, so we make sure it caps at the correct # boundary values. t0 = datetime.datetime(1000, 1, 1) tf = datetime.datetime(6000, 1, 1) fig = plt.figure() ax = plt.subplot(111) ax.set_autoscale_on(True) ax.plot([t0, tf], [0.0, 1.0], marker='o') rrule = mdates.rrulewrapper(dateutil.rrule.YEARLY, interval=500) locator = mdates.RRuleLocator(rrule) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) ax.autoscale_view() fig.autofmt_xdate()
def xLabelDateFormat(self, DateFormatter=None): import datetime import numpy as np import matplotlib.pyplot as plt import matplotlib.dates as mdates import matplotlib.cbook as cbook years = mdates.YearLocator() # every year months = mdates.MonthLocator() # every month yearsFmt = mdates.AutoDateFormatter(mdates.AutoDateLocator()) if DateFormatter is not None: yearsFmt = mdates.DateFormatter(DateFormatter) # format the ticks self.ax.xaxis.set_major_locator(mdates.AutoDateLocator()) self.ax.xaxis.set_major_formatter(yearsFmt) self.ax.xaxis.set_minor_locator(months) # rotates and right aligns the x labels, and moves the bottom of the # axes up to make room for them self.fig.autofmt_xdate() pass
def make_ax_timespan(ax, datetimes, resolution=None): """ Make `ax` X-axis a time-axis. In order to function properly `ax.figure.autofmt_xdate` must be called after plot is finished. Parameters ---------- ax : matplotlib.pyplot.Axes Axis-instance to adjust. datetimes : list[datetime.DateTime] Datetime-index used. resolution : str {'month', 'week', 'day', 'hour'}, optional Specified resolution. If None, automatic formatting is used. Returns ------- np.ndarray `datetimes` converted to equispaced numeric array. """ times = dates.date2num(datetimes) if resolution == 'month': locator = dates.MonthLocator() elif resolution == 'week': locator = dates.WeekdayLocator() elif resolution == 'day': locator = dates.DayLocator() elif resolution == 'hour': locator = dates.HourLocator() elif isinstance(resolution, dates.DateLocator): locator = resolution elif resolution is None: locator = dates.AutoDateLocator() ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(dates.AutoDateFormatter(locator)) ax.set_xlim([times[0], times[-1]]) return times
def regime_plot(vix, lower=16.5, upper=19.5, ylabel='VIX', figsize=(10, 6)): # Each term inside parentheses is [False, True, ...] # Both terms must be True element-wise for a trigger to occur blue = (vix < upper) & (vix.shift() >= upper) yellow = (vix < lower) & (vix.shift() >= lower) green = (vix > upper) & (vix.shift() <= upper) red = (vix > lower) & (vix.shift() <= lower) mapping = {1: 'blue', 2: 'yellow', 3: 'green', 4: 'red'} indicator = pd.Series(np.where( blue, 1., np.where(yellow, 2., np.where(green, 3., np.where(red, 4., np.nan)))), index=vix.index).ffill().map(mapping).dropna() vix = vix.reindex(indicator.index) import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=figsize) plt.scatter(vix.index, vix, c=indicator, marker='.') plt.title(ylabel + ' regime') plt.ylabel(ylabel) # x_ticks=f_xticks(vix) # setting labels for ticks # ax.set_xticklabels(x_ticks) import matplotlib.dates as mdates # all your fancy plotting code locator = mdates.AutoDateLocator() ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) # Positioning ticks fig.autofmt_xdate(bottom=0.2, rotation=0, ha='center', which=None) # Sizing and coloring ticks ax.xaxis.set_tick_params(labelsize=8, color=dicclrs['dates']) plt.show() return
def showSingleData(CSC, deathsData, data_date, data_secs): deathsDailyData = getSlopeData(deathsData, False, 1) (labeledMajors, shownMajors) = getLabeledShown(deathsDailyData) fig, axs = plt.subplots(1, 1) max_length = 0 for major in shownMajors: max_length = max(max_length, len(deathsData[major])) base = datetime.datetime.today() date_list = [ base - datetime.timedelta(days=max_length - x) for x in range(max_length) ] max_val = 0 for major in shownMajors: max_val = max(max_val, np.max(deathsDailyData[major])) for major in shownMajors: smoothPlot(axs, date_list, deathsDailyData[major], major, major in labeledMajors, False, False) locator = mdates.AutoDateLocator() formatter = mdates.AutoDateFormatter(locator) axs.xaxis.set_major_locator(locator) axs.xaxis.set_major_formatter(formatter) axs.set_ylim(0, max_val) axs.set_title("Daily deaths") plt.suptitle(CSC + " COVID-19 stats, Date:" + data_date) fig.tight_layout(pad=1.0) fig.autofmt_xdate() plt.grid() plt.subplots_adjust(top=0.85) plt.savefig("/var/www/html/" + CSC + "_" + data_secs + ".png") plt.close() print("Image saved.")
def make_double_plot(timestamp, j, title, k1, k2, xlabel='Time'): fig, ax1 = plt.subplots() points = 500 x_max = max(len(j[k1]), len(j[k2])) sample = int(ceil(1.0 * x_max / points)) y1 = average(j[k1], sample) x1 = np.linspace(0, x_max, num=len(y1)) x1_time = map(lambda x: to_time(x, x1[-1] - x1[0]), x1) dl = mdates.AutoDateLocator() plt.gca().xaxis.set_major_formatter(mdates.AutoDateFormatter(dl)) plt.gca().xaxis.set_major_locator(dl) ax1.plot(x1_time, y1, 'r-') plt.gcf().autofmt_xdate() ax1.set_xlabel(xlabel) ax1.set_ylabel(k1, color='r') ax1.margins(0, 0.1) ax1.tick_params('y', colors='r') ax2 = ax1.twinx() y2 = average(j[k2], sample) x2 = np.linspace(0, x_max, num=len(y2)) x2_time = map(lambda x: to_time(x, x2[-1] - x2[0]), x2) ax2.plot(x2_time, y2, 'b-') ax2.set_ylabel(k2, color='b') ax2.margins(0, 0.1) ax2.tick_params('y', colors='b') plt.title(title) # fig.tight_layout() # plt.show() plt.savefig(os.path.join( figs_path, '{}_{}_{}_{}.png'.format(timestamp, j['args'], k1, k2)), dpi=300) plt.close('all')
def set_time_ticks(ax, time_zone=None, with_date=False, minticks=5, maxticks=None, axis='x'): try: tz = tz_dict[time_zone] except KeyError: tz = None locator = mdates.AutoDateLocator(tz=tz, minticks=minticks, maxticks=maxticks) formatter = mdates.AutoDateFormatter(locator, tz=tz) if with_date: fmt_min = '%H:%M\n%d/%m' fmt_hour = '%Hh\n%d/%m' else: fmt_min = '%H:%M' fmt_hour = '%Hh' fmt_day = '%d/%m' formatter.scaled[1 / (24. * 60.)] = fmt_min formatter.scaled[1. / 24.] = fmt_hour formatter.scaled[1.] = fmt_day if axis == 'x': ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) elif axis == 'y': ax.yaxis.set_major_locator(locator) ax.yaxis.set_major_formatter(formatter) else: raise ValueError('Unexpected agrument axis: {}'.format(axis))
color='k', alpha=0.1, \ label='Uncertainty in {0}'.format(YS_obs_nam_uq)) if os.path.isfile(rrr_mod_uq_csv): plt.fill_between(ZV_time, \ [x-y for x,y in zip(ZV_Qmod,ZV_Qmod_uq)], \ [x+y for x,y in zip(ZV_Qmod,ZV_Qmod_uq)], \ color='b', alpha=0.1, \ label='Uncertainty in {0}'.format(YS_mod_nam_uq)) #-------------------------------------------------------------------------- #Format x axis #-------------------------------------------------------------------------- plt.axes().xaxis.set_minor_locator(mdates.AutoDateLocator()) locator = mdates.AutoDateLocator(minticks=6, maxticks=8) plt.axes().xaxis.set_major_locator(locator) plt.axes().xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) plt.xlim(ZV_time[0], ZV_time[IS_time - 1]) #-------------------------------------------------------------------------- #Format y axis #-------------------------------------------------------------------------- plt.ylim(0, ZS_max_val) #-------------------------------------------------------------------------- #Format title, labels, and legend #-------------------------------------------------------------------------- plt.title(YV_obs_tot_nm[JS_obs_tot]) plt.xlabel('Time') plt.ylabel('Discharge (' + r'$m^3 s^{-1}$' + ')') plt.legend(loc='upper right')
figure = pyplot.figure() min_firstedit = min(dates.date2num(wikibios.columns['firstedit'])) max_firstedit = max(dates.date2num(wikibios.columns['firstedit'])) firstedits_male = dates.date2num(wikibios.columns_male['firstedit']) birth_years_male = wikibios.columns_male['birth_year'] axes1 = figure.add_subplot(1, 2, 1) h1 = axes1.hist2d(firstedits_male, birth_years_male, range=[[min_firstedit, max_firstedit], [1750, 2014]], bins=50) figure.colorbar(h1[3]) axes1.xaxis.set_major_formatter( dates.AutoDateFormatter(dates.AutoDateLocator())) axes1.set_title('Male') firstedits_female = dates.date2num(wikibios.columns_female['firstedit']) birth_years_female = wikibios.columns_female['birth_year'] axes2 = figure.add_subplot(1, 2, 2) h2 = axes2.hist2d(firstedits_female, birth_years_female, range=[[min_firstedit, max_firstedit], [1750, 2014]], bins=50) figure.colorbar(h2[3]) axes2.xaxis.set_major_formatter( dates.AutoDateFormatter(dates.AutoDateLocator())) axes2.set_title('Female')
def show_coherence(self, ax=None, cax=None, path_figure=None, **kwargs): """ Calculate covariance matrix from the stream.spectra. Arguments: ---------- ax (matplotlib.pyplot.Axes, optional) the axes for the coherence. Default to None, and some axes are created. cax (matplotlib.pyplot.Axes, optional) the axes for the colorbar. Default to None, and the axes are created. These axes should be given if ax is not None. path_figure (str, optional): if set, then save the figure to the path. Default to None, then return fig, ax and cax. **kwargs (dict): other keyword arguments passed to matplotlib.pyplot.pcolormesh. Return: ------ If the path_figure kwargs is set to None (default), the following objects are returned: fig (matplotlib.pyplot.Figure) the figure instance. ax (matplotlib.pyplot.Axes) axes of the spectrogram. cax (matplotlib.pyplot.Axes) axes of the colorbar. """ # If axes are not given if ax is None: gs = dict(width_ratios=[50, 1], wspace=0.1) fig, (ax, cax) = plt.subplots(1, 2, figsize=(7, 3), gridspec_kw=gs) else: fig = ax.figure # Default options kwargs.setdefault('rasterized', True) time = self.times time = np.hstack((time, self.time_end)) img = ax.pcolormesh(time, self.frequencies, self.coherence.T, **kwargs) # Time limits ax.set_xlim(self.times[0], self.time_end) xticks = md.AutoDateLocator() ax.xaxis.set_major_locator(xticks) ax.xaxis.set_major_formatter(md.AutoDateFormatter(xticks)) # Frequency limits ax.set_ylim(self.frequencies[[0, -1]]) ax.set_yscale('log') ax.set_ylabel('Frequency (Hz)') # Colorbar plt.colorbar(img, cax=cax) cax.set_ylabel('Spectral width') # Save if path_figure is not None: fig.savefig(path_figure, dpi=300, bbox_inches='tight') else: return fig, ax, cax
def axisinfo(unit, axis): # docstring inherited majloc = date_ticker.AutoDateLocator() majfmt = date_ticker.AutoDateFormatter(majloc) return units.AxisInfo(majloc=majloc, majfmt=majfmt, label=unit)
etime=etime, method=1) out = array_processing(st, **kwargs) print 'End fk analysis' # Plot # Plot labels = ['rel.power', 'abs.power', 'baz', 'slow'] xlocator = mdates.AutoDateLocator() fig = plt.figure() for i, lab in enumerate(labels): ax = fig.add_subplot(4, 1, i + 1) ax.scatter(out[:, 0], out[:, i + 1], c=out[:, 1], alpha=0.6, edgecolors='none', cmap=obspy_sequential) ax.set_ylabel(lab) ax.set_xlim(out[0, 0], out[-1, 0]) ax.set_ylim(out[:, i + 1].min(), out[:, i + 1].max()) ax.xaxis.set_major_locator(xlocator) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(xlocator)) fig.suptitle('AGFA skyscraper blasting in Munich %s' % (stime.strftime('%Y-%m-%d'), )) fig.autofmt_xdate() fig.subplots_adjust(left=0.15, top=0.95, right=0.95, bottom=0.2, hspace=0) plt.show()
def plotVisitPeriods(md, window=60, ax=None, cages=None, start=None, end=None, tzone=None, label=False, color='b', linestyle='-', **kwargs): visits = md.getVisits(start=start, end=end) if len(visits) == 0: return byCages = groupBy(visits, operator.attrgetter('Cage')) if cages is None: cages = set(byCages) elif isString(cages): cages = {int(cages)} else: try: cages = set(cages) except: cages = {int(cages)} cages = sorted(set(byCages) & cages) if len(cages) == 0: return fig = None if ax is None: fig = plt.figure() fig.suptitle('Visits detected') width = int(ceil(sqrt(len(cages)))) height = int(ceil(float(len(cages)) / width)) for i, cage in enumerate(cages, 1): ax = fig.add_subplot(height, width, i) ax.set_title("cage %d" % cage) locator = mpd.AutoDateLocator(tz=tzone) formatter = mpd.AutoDateFormatter(locator, tz=tzone) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) xmin, xmax = _plotVisitPeriods(ax, byCages[cage], start, end, 0.9, 0.1, window, color, linestyle, **kwargs) ax.set_xlim(xmin, xmax) ax.set_ylim(0, 1) plt.xticks(rotation=30) # -_- ax.autoscale_view() #fig.autofmt_xdate() fig.tight_layout() fig.canvas.draw() return fig for i, cage in enumerate(sorted(cages)): if label: _plotVisitPeriods(ax, byCages[cage], start, end, i + 0.9, i + 0.1, window, color, linestyle, label='cage %d' % cage, **kwargs) else: _plotVisitPeriods(ax, byCages[cage], start, end, i + 0.9, i + 0.1, window, color, linestyle, **kwargs)
def plot_errors_DL(stats_res, series_labels, timestamps, sampling_time, gaps, idle_periods, samples_idleness=[], ts_noIdle=[], ts_idle=[], test_idx=-1, freqGov="conservative", title="Error"): if len(ts_noIdle) > 0: plot_errors_DL_fixIdle(stats_res, series_labels, timestamps, sampling_time, gaps, idle_periods, ts_noIdle, ts_idle, test_idx, freqGov, title) return cumul_errors = [] time_idxs = [] for i in range(len(stats_res["ABS_ERRORS"][0])): cumul_errors.append(0) time_idxs.append(i) for j in stats_res["ABS_ERRORS"].keys(): for i in range(len(stats_res["ABS_ERRORS"][j])): cumul_errors[i] += stats_res["ABS_ERRORS"][j][i] # 'normalize' cumulated errors cumul_errors_norm = [] for ce in cumul_errors: cumul_errors_norm.append(ce / len(stats_res["ABS_ERRORS"])) if len(samples_idleness) > 0: for i in range(len(cumul_errors_norm)): print("Error norm: %s; Idle: %s" % (cumul_errors_norm[i], samples_idleness[i])) fig = plt.figure() if len(timestamps) != len(cumul_errors_norm): if len(timestamps) > len(cumul_errors_norm): dif = len(timestamps) - len(cumul_errors_norm) timestamps = timestamps[dif:] else: dif = len(cumul_errors_norm) - len(timestamps) cumul_errors_norm = cumul_errors_norm[dif:] plt.plot(timestamps, cumul_errors_norm) if test_idx != -1: test_timestamp = ts_noIdle[test_idx] plt.axvline(x=test_timestamp, linewidth=2, linestyle='--', color='k') ax = fig.add_subplot(111) for st, et in gaps: start = mdates.date2num(st) end = mdates.date2num(et) dif = end - start rect = patches.Rectangle((start, 0), dif, 1, fill=False, hatch='/', color='grey') ax.add_patch(rect) for st, et in idle_periods: start = mdates.date2num(st) end = mdates.date2num(et) dif = end - start rect = patches.Rectangle((start, 0), dif, 1, fill=False, hatch='//', color='yellow') ax.add_patch(rect) add_freq_govs_to_plot(freqGov, ax) locator = mdates.AutoDateLocator(minticks=3) formatter = mdates.AutoDateFormatter(locator) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) plt.title(title) plt.show()
def format_ax(ax, ylabel=None): ''' Format an axes object, *ax*, to quickly add labels, change time ticks to sensible values, turn off xtick labels unless we're on the bottom row of plots, and set the y-axis label to kwarg *ylabel* Example usage: format_ax(axis, ylabel='some label string') ''' import matplotlib.dates as mdt # Better tick spacing: This looks pedantic, but is very, very powerful. # Use locator objects (special objects that find where to put ticks) to # set tick locations. Use formatter objects to set the format of the # tick labels. Because we don't know how long our file is, let's use # some "if" statements to keep things from blowing up. # Start by calculating the time spanned by the x-axis (in days): span = ax.get_xlim()[-1] - ax.get_xlim()[0] # Apply different cases based on typical scenarios: if span < 5: # less than five days? Go by hour: Mtick = mdt.HourLocator(byhour=[0, 6, 12, 18]) mtick = mdt.HourLocator(byhour=range(24)) fmt = mdt.DateFormatter('%H:%M UT') else: # Default to AutoDateFormatter. Mtick = mdt.AutoDateLocator() mtick = mdt.AutoDateLocator() fmt = mdt.AutoDateFormatter(Mtick) # Apply those to our axes. Note that the axes objects contain # axis objects for the x axis and y axis. We can edit single # axes so they look different! ax.xaxis.set_major_locator(Mtick) ax.xaxis.set_minor_locator(mtick) ax.xaxis.set_major_formatter(fmt) # Turn on the grid: ax.grid() # Set ylabel, if set: if ylabel: ax.set_ylabel(ylabel, size=16) # Kill some labels. Get the list of label objects and turn some off. labels = ax.get_yticklabels() # Get the labels... labels[-1].set_visible(False) # Turn off the first. labels[0].set_visible(False) # Turn off the 2nd. # Determine the axes' geometry. Use this to determine if we're in the # bottom row of plots. The geometry is returned as (nrows, ncols, iplot). geom = ax.get_geometry() # We're in the bottom row if the number of the current plot we're on is # greater than the number of plots in all rows above the last. is_bottom = geom[-1] > (geom[0] - 1) * geom[1] # If we're in the bottom row, label the axes with the date and time. if is_bottom: # Get time limits, as floating point numbers, from our axes object: tStart, tEnd = ax.get_xlim() # returns range of x-axes. # Convert tStart into a datetime: tStart = mdt.num2date(tStart) # Note how Datetime objects have methods to pretty-print the time! ax.set_xlabel(f'Time from {tStart.isoformat()}', size=18) else: # No labels on any axis except the bottom plot. Set the list of # labels to an empty list for no labels (but keep ticks!) ax.xaxis.set_ticklabels([])
def main(): ipshell = IPShellEmbed() if len(sys.argv) < 2: logfilename = 'log.csv' # use default filename print 'No input filename specified: using %s' % logfilename else: logfilename = sys.argv[1] if not os.path.exists(logfilename): print '%s does not exist!' % logfilename sys.exit() else: print 'Reading file %s' % logfilename if len(sys.argv) < 3: pngfilename = None print 'No output filename specified: will not write output file for plot' else: pngfilename = sys.argv[2] print 'Plot will be saved as %s' % pngfilename data = np.genfromtxt(logfilename, delimiter=',', skip_header=6, usecols=(0, 1, 3, 4, 5, 6, 7, 8, 9)) t = data[:, 0] stamp = data[:, 1] lm61temp = data[:, 2] #therm1 = data[:,3] therm1 = np.ma.masked_where(np.isnan(data[:, 3]), data[:, 3]) therm2 = data[:, 4] temp0 = data[:, 5] #temp1 = data[:,6] # use masked array rather than nan for bad values data[np.where(data[:, 6] > MAXTEMP), 6] = np.nan data[np.where(data[:, 7] > MAXTEMP), 7] = np.nan data[np.where(data[:, 8] > MAXTEMP), 8] = np.nan temp1 = np.ma.masked_where(np.isnan(data[:, 6]), data[:, 6]) temp2 = np.ma.masked_where(np.isnan(data[:, 7]), data[:, 7]) temp3 = np.ma.masked_where(np.isnan(data[:, 8]), data[:, 8]) offset = stamp[1] - t[1] / 1000 print offset maxstamp = t[len(t) - 1] / 1000 + offset + MAXSEC print maxstamp stamp[stamp < offset] = np.nan stamp[stamp > maxstamp] = np.nan stamp[abs(stamp - t / 1000 - offset) > MAXSEC] = np.nan nancount = np.sum(np.isnan(stamp)) print '%d bad time stamps to interpolate' % nancount # extrapolate - see # http://stackoverflow.com/questions/1599754/is-there-easy-way-in-python-to-extrapolate-data-points-to-the-future extrapolator = UnivariateSpline(t[np.isfinite(stamp)], stamp[np.isfinite(stamp)], k=1) utime = extrapolator(t) # plot 6 columns pyplot.plot(dates.epoch2num(utime), lm61temp, '.', dates.epoch2num(utime), therm1, '.', dates.epoch2num(utime), therm2, '.', dates.epoch2num(utime), temp1, '.', dates.epoch2num(utime), temp2, '.', dates.epoch2num(utime), temp3, '.') ax = pyplot.gca() ax.legend(('LM61', 'Thermistor 1', 'Thermistor 2', 'digital 1', 'digital 2', 'digital 3'), loc=0) ax.set_xlabel('Time') ax.set_ylabel(u'Temp (°C)') ax2 = ax.twinx() clim = pyplot.get(ax, 'ylim') ax2.set_ylim(c2f(clim[0]), c2f(clim[1])) ax2.set_ylabel(u'Temp (°F)') xlocator = dates.AutoDateLocator() xformatter = dates.AutoDateFormatter(xlocator) pyplot.gca().xaxis.set_major_locator(xlocator) pyplot.gca().xaxis.set_major_formatter(dates.DateFormatter('%H:%M')) # generate a PNG file if pngfilename: pyplot.savefig(pngfilename) # show the plot pyplot.show() # open interactive shell ipshell()
def _colormap_plot_beamforming_time(cmaps): """ Plot for illustrating colormaps: beamforming. :param cmaps: list of :class:`~matplotlib.colors.Colormap` :rtype: None """ import matplotlib.pyplot as plt import matplotlib.dates as mdates from obspy import UTCDateTime from obspy.signal.array_analysis import array_processing # Execute array_processing stime = UTCDateTime("20080217110515") etime = UTCDateTime("20080217110545") kwargs = dict( # slowness grid: X min, X max, Y min, Y max, Slow Step sll_x=-3.0, slm_x=3.0, sll_y=-3.0, slm_y=3.0, sl_s=0.03, # sliding window properties win_len=1.0, win_frac=0.05, # frequency properties frqlow=1.0, frqhigh=8.0, prewhiten=0, # restrict output semb_thres=-1e9, vel_thres=-1e9, timestamp='mlabday', stime=stime, etime=etime) st = _get_beamforming_example_stream() out = array_processing(st, **kwargs) # Plot labels = ['rel.power', 'abs.power', 'baz', 'slow'] xlocator = mdates.AutoDateLocator() for cmap in cmaps: fig = plt.figure() for i, lab in enumerate(labels): ax = fig.add_subplot(4, 1, i + 1) ax.scatter(out[:, 0], out[:, i + 1], c=out[:, 1], alpha=0.6, edgecolors='none', cmap=cmap) ax.set_ylabel(lab) ax.set_xlim(out[0, 0], out[-1, 0]) ax.set_ylim(out[:, i + 1].min(), out[:, i + 1].max()) ax.xaxis.set_major_locator(xlocator) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(xlocator)) fig.suptitle('AGFA skyscraper blasting in Munich %s' % (stime.strftime('%Y-%m-%d'), )) fig.autofmt_xdate() fig.subplots_adjust(left=0.15, top=0.95, right=0.95, bottom=0.2, hspace=0) plt.show()
def removepicosecs(axis, **datelocatorargs): locator = pltdates.AutoDateLocator(**datelocatorargs) formatter = pltdates.AutoDateFormatter(locator) formatter.scaled[1 / (24. * 60.)] = pltticker.FuncFormatter(threetruncate) axis.xaxis.set_major_locator(locator) axis.xaxis.set_major_formatter(formatter)
def plotEnv(md, env='Illumination', ax=None, cages=None, start=None, end=None, label=False, tzone=None, **kwargs): envData = md.getEnvironment(start=start, end=end) if len(envData) == 0: return byCages = groupBy(envData, operator.attrgetter('Cage')) if cages is None: cages = set(byCages) elif isString(cages): cages = {int(cages)} else: try: cages = set(cages) except: cages = {int(cages)} cages = sorted(set(byCages) & cages) if len(cages) == 0: return fig = None if ax is None: fig = plt.figure() fig.suptitle(env) width = int(ceil(sqrt(len(cages)))) height = int(ceil(float(len(cages)) / width)) for i, cage in enumerate(cages, 1): ax = fig.add_subplot(height, width, i) ax.set_title("cage %d" % cage) locator = mpd.AutoDateLocator(tz=tzone) formatter = mpd.AutoDateFormatter(locator, tz=tzone) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter) xmin, xmax, ymin, ymax = _plotEnv(byCages[cage], ax, env, **kwargs) ax.set_xlim(xmin, xmax) ax.set_ylim(ymin - 1, ymax + 1) plt.xticks(rotation=30) # -_- ax.autoscale_view() #fig.autofmt_xdate() fig.tight_layout() fig.canvas.draw() return fig for cage in sorted(cages): if label: _plotEnv(byCages[cage], ax, env, label="cage %d" % cage, **kwargs) else: _plotEnv(byCages[cage], ax, env, **kwargs)
def make_figure(in_frame, split_at=None, title='Article View Trends'): """ Takes the input data and creates a plot similar to figure 3 in the paper :param dataframe: A pandas data frame with the dates (dtype=PeriodIndex) as index and views as its only column :param split_at: The date at which the data shall be split :param title: Figure title :return: Plots the figure """ # Prepare the dataframe for seaborn (https://stackoverflow.com/questions/52112979/having-xticks-to-display-months-in-a-seaborn-regplot-with-pandas) dataframe = in_frame.copy() dataframe.index = dataframe.index.to_timestamp() dataframe['date_ordinal'] = mdates.date2num(dataframe.index) colors = {'Monthly Page Views': 'blue', 'trend': 'darkgrey'} # The actual plot fig, ax = plt.subplots(figsize=[18, 6]) if split_at is None: sns.regplot(x='date_ordinal', y='views', data=dataframe, ax=ax, color=colors['Monthly Page Views']) else: colors['Prism Disclosure, 6/6/2013'] = 'red' df1 = dataframe.loc[dataframe.index < split_at] df2 = dataframe.loc[dataframe.index >= split_at] sns.regplot(x='date_ordinal', y='views', data=df1, ax=ax, color=colors['Monthly Page Views'], scatter_kws={ 'color': colors['Monthly Page Views'], 's': 30 }, line_kws={'color': colors['trend']}) sns.regplot(x='date_ordinal', y='views', data=df2, ax=ax, color=colors['Monthly Page Views'], scatter_kws={ 'color': colors['Monthly Page Views'], 's': 30 }, line_kws={'color': colors['trend']}) ax.vlines(mdates.date2num(split_at), 0, 1, color=colors['Prism Disclosure, 6/6/2013'], transform=ax.get_xaxis_transform(), label=split_at) print("debug") # Formatting and Visualization fig.patch.set_facecolor('lightgrey') fig.suptitle(title) ax.set_xlabel('Month / Year') ax.set_ylabel('Monthly Page Views') ax.set_xlim(dataframe['date_ordinal'].min() - 15, dataframe['date_ordinal'].max() + 15) # Seaborn has problems handling datetime objects for labeling, adjusting the x-Axis to display them as desired loc = mdates.MonthLocator() ax.xaxis.set_major_locator(loc) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc)) # Add a custom legend legend_patches = [] for entry, c in colors.items(): legend_patches.append(mpatches.Patch(color=c, label=entry)) font = FontProperties() font.set_size('large') fig.autofmt_xdate() plt.legend(handles=legend_patches, title='Legend', bbox_to_anchor=(0, 0), loc='lower left', prop=font, ncol=len(legend_patches), fancybox=True, shadow=True)
def state_stats(state, long_min, long_max, lat_min, lat_max): """ This displays a pandas dataframe. 1. Import credentials 2. connect to postgresql API 3. Create pandas df 4. Save as html """ credentials = yaml.load( open(os.path.expanduser('/vagrant/credentials.yml'))) engine = create_engine( 'postgresql://{user}:{password}@{host}:{port}/{dbname}'.format( **credentials['rds'])) california_recent = pd.read_sql( "SELECT isotime, magnitude FROM quakes WHERE (longitude >= {} and longitude <= {}) and (latitude >= {} and latitude <= {}) ORDER BY isotime DESC LIMIT 100" .format(long_min, long_max, lat_min, lat_max), engine) ca_recent = california_recent.head(10).to_html() tbl = california_recent.dropna() tbl['magnitude'] = tbl['magnitude'].apply(lambda x: mag_category(x)) tbl.isotime = tbl.isotime.dt.date tbl = tbl.groupby(['isotime', 'magnitude' ])['isotime'].count().unstack('magnitude').fillna(0) ax = tbl.plot(kind='bar', stacked=True, figsize=(12, 8)) ax.set_title("100 most recent instances for {}".format(state), fontsize=25) ax.legend(fontsize=20) ax.legend_.set_title("Magnitude Range", prop={'size': 20}) ax.set_ylabel("Count", fontsize=20) ax.xaxis_date() ax.set_xlabel("Counts per day (if occured)", fontsize=20) ax.grid(True) fig = ax.get_figure() fig.tight_layout() state_fig_name_stacked = '{}_recent_quakes_stacked.png'.format(state) fig.savefig(state_fig_name_stacked) tbl2 = pd.read_sql( "SELECT isotime FROM quakes WHERE (longitude >= {} and longitude <= {}) and (latitude >= {} and latitude <= {})" .format(long_min, long_max, lat_min, lat_max), engine) locator = mdates.AutoDateLocator() years = mdates.YearLocator() fig, ax = plt.subplots(figsize=(12, 8)) data = tbl2.isotime.dt.date mpl_data = mdates.date2num(data) ax.hist(mpl_data, bins=len(data.unique())) ax.set_title("{} Earthquake counts per day (if occurred)".format(state), fontsize=25) ax.set_ylabel("Count", fontsize=15) ax.set_xlabel("Time", fontsize=15) ax.xaxis.set_major_locator(years) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) datemin = datetime.date(tbl2.isotime.min().year, 1, 1) datemax = datetime.date(tbl2.isotime.max().year + 1, 1, 1) ax.set_xlim(datemin, datemax) ax.set_ylim(0, 45) ax.grid(True) fig.tight_layout() state_quakes = "{}_quakes.png".format(state) fig.savefig(state_quakes) aws_cred = credentials['aws'] conn = S3Connection(aws_access_key_id=aws_cred['access_key_id'], aws_secret_access_key=aws_cred['secret_access_key']) bucket = conn.get_bucket("nobucketforyou") stacked_plot_key = bucket.new_key(state_fig_name_stacked) stacked_plot_key.content_type = 'image/png' stacked_plot_key.set_contents_from_filename(state_fig_name_stacked, policy='public-read') ok_all_key = bucket.new_key(state_quakes) ok_all_key.content_type = 'image/png' ok_all_key.set_contents_from_filename(state_quakes, policy='public-read') return (ca_recent)
fig = plt.figure(figsize=(12, 4)) ax = fig.add_subplot(1, 1, 1) mpl_finance.candlestick_ohlc(ax, data, width=2, alpha=0.5, colorup='r', colordown='b') ax.grid() locator = mdates.AutoDateLocator() ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) plt.savefig('data/dst/candlestick_day.png') plt.close() # ![](data/dst/candlestick_day.png) fig = plt.figure(figsize=(12, 4)) ax = fig.add_subplot(1, 1, 1) mpl_finance.candlestick_ohlc(ax, data, width=2, alpha=0.5, colorup='r',
def process_axis(axis, data: Union[list, np.ndarray, pd.Series, pd.DataFrame], x: Union[list, np.ndarray] = None, # array to plot as x marker='', fillstyle=None, linestyle='-', c=None, ms=6.0, # markersize label=None, # legend leg_pos="best", bbox_to_anchor=None, # will take priority over leg_pos leg_fs=12, leg_ms=1, # legend scale ylim=None, # limit for y axis x_label=None, xl_fs=None, y_label=None, yl_fs=12, # ylabel font size yl_c='k', # y label color, if 'same', c will be used else black xtp_ls=None, # x tick_params labelsize ytp_ls=None, # x tick_params labelsize xtp_c='k', # x tick colors if 'same' c will be used else black ytp_c='k', # y tick colors, if 'same', c will be used else else black log=False, show_xaxis=True, top_spine=True, bottom_spine=True, invert_yaxis=False, max_xticks=None, min_xticks=None, title=None, title_fs=None, # title fontszie log_nz=False, ): """Purpose to act as a middle man between axis.plot/plt.plot. Returns: axis """ # TODO # default fontsizes should be same as used by matplotlib # should not complicate plt.plot or axis.plto # allow multiple plots on same axis if log and log_nz: raise ValueError use_third = False if x is not None: if isinstance(x, str): # the user has not specified x so x is currently plot style. style = x x = None if marker == '.': use_third= True if log_nz: data = deepcopy(data) _data = data.values d_nz_idx = np.where(_data > 0.0) data_nz = _data[d_nz_idx] d_nz_log = np.log(data_nz) _data[d_nz_idx] = d_nz_log _data = np.where(_data < 0.0, 0.0, _data) data = pd.Series(_data, index=data.index) if log: data = deepcopy(data) _data = np.where(data.values < 0.0, 0.0, data.values) print(len(_data[np.where(_data < 0.0)])) data = pd.Series(_data, index=data.index) if x is not None: axis.plot(x, data, fillstyle=fillstyle, color=c, marker=marker, linestyle=linestyle, ms=ms, label=label) elif use_third: axis.plot(data, style, color=c, ms=ms, label=label) else: axis.plot(data, fillstyle=fillstyle, color=c, marker=marker, linestyle=linestyle, ms=ms, label=label) ylc = c if yl_c != 'same': ylc = 'k' _kwargs = {} if label is not None: if label != "__nolabel__": if leg_fs is not None: _kwargs.update({'fontsize': leg_fs}) if leg_ms is not None: _kwargs.update({'markerscale': leg_ms}) if bbox_to_anchor is not None: _kwargs['bbox_to_anchor'] = bbox_to_anchor else: _kwargs['loc'] = leg_pos axis.legend(**_kwargs) if y_label is not None: axis.set_ylabel(y_label, fontsize=yl_fs, color=ylc) if log: axis.set_yscale('log') if invert_yaxis: axis.set_ylim(axis.get_ylim()[::-1]) if ylim is not None: if not isinstance(ylim, tuple): raise TypeError("ylim must be tuple {} provided".format(ylim)) axis.set_ylim(ylim) xtpc = c if xtp_c != 'same': xtpc = 'k' ytpc = c if ytp_c != 'same': ytpc = 'k' _kwargs = {'colors': xtpc} if x_label is not None or xtp_ls is not None: # better not change these paras if user has not defined any x_label if xtp_ls is not None: _kwargs.update({'labelsize': xtp_ls}) axis.tick_params(axis="x", which='major', **_kwargs) _kwargs = {'colors': ytpc} if y_label is not None or ytp_ls is not None: if ytp_ls is not None: _kwargs.update({'labelsize': ytp_ls}) axis.tick_params(axis="y", which='major', **_kwargs) axis.get_xaxis().set_visible(show_xaxis) _kwargs = {} if x_label is not None: if xl_fs is not None: _kwargs.update({'fontsize': xl_fs}) axis.set_xlabel(x_label, **_kwargs) axis.spines['top'].set_visible(top_spine) axis.spines['bottom'].set_visible(bottom_spine) if min_xticks is not None: assert isinstance(min_xticks, int) assert isinstance(max_xticks, int) loc = mdates.AutoDateLocator(minticks=min_xticks, maxticks=max_xticks) axis.xaxis.set_major_locator(loc) fmt = mdates.AutoDateFormatter(loc) axis.xaxis.set_major_formatter(fmt) if title_fs is None: title_fs = plt.rcParams['axes.titlesize'] if title is not None: axis.set_title(title, fontsize=title_fs) return axis
def make_history_graph(txn): # Graph since first record txn.execute( database.translate_query(""" SELECT date FROM history ORDER BY date ASC LIMIT 1 """)) first_time = txn.fetchall() if first_time is not None and len( first_time) > 0 and first_time[0][0] is not None: dt_first = first_time[0][0] else: dt_first = datetime.date.today() num_days = (datetime.date.today() - dt_first).days #logging.debug("First day in data set: {}".format(dt_first)) #logging.debug("Number of days in data set: {}".format(num_days)) no_data = False if num_days == 0: no_data = True x = [ dt_first, ] y = [ 0, ] else: txn.execute( database.translate_query(""" SELECT date, num_reports FROM history ORDER BY date ASC """)) rows = txn.fetchall() (x, y) = zip(*rows) # calc the trendline x_num = mdates.date2num(x) if not no_data: z = numpy.polyfit(x_num, y, 1) p = numpy.poly1d(z) xx = numpy.linspace(x_num.min(), x_num.max(), 100) dd = mdates.num2date(xx) fig = plt.figure() ax = fig.gca() locator = mdates.AutoDateLocator(interval_multiples=False) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) ax.yaxis.set_major_formatter( matplotlib.ticker.FuncFormatter(humanize_number)) ax.set_title("Reports per day") if (num_days < 100): ax.plot(x, y, linestyle='solid', marker='o', markerfacecolor='blue') else: ax.plot(x, y, linestyle='solid', marker='') if not no_data: ax.plot(dd, p(xx), "b--") ax.set_ybound(lower=0) fig.autofmt_xdate() if num_days == 0: fig.text(0.50, 0.50, "Not enough data", size="x-large", ha="center", va="center") fig.savefig(os.path.join(config.graph_dir, 'history.svg')) fig.clf() plt.close(fig)
def __init__(self): self.spans = [] self.connections = [] self.loc = dates.AutoDateLocator() self.fmt = dates.AutoDateFormatter(self.loc) pass
def axisinfo(unit, axis): majloc = dates.AutoDateLocator() majfmt = dates.AutoDateFormatter(majloc) return units.AxisInfo(majloc=majloc, majfmt=majfmt)
for s in stations: d = dfc.xs(s, level="station") if "PM10" in d.index.get_level_values("analysis"): df.loc[s, "name"] = s df.loc[s, "OP"] = pd.np.sum(pd.notnull(d["PO_DTT_m3"])) df.loc[s, "chem"] = pd.np.sum(pd.notnull(d["OC"])) df.loc[s, "datemin"] = d.index.get_level_values("date").min() df.loc[s, "datemax"] = d.index.get_level_values("date").max() ax = plt.subplot() for i, s in enumerate(df.sort_values("datemin")["name"]): start = mdates.date2num(df.loc[s, "datemin"].to_pydatetime()) end = mdates.date2num(df.loc[s, "datemax"].to_pydatetime()) width = end - start mean = (end + start) / 2 rect = Rectangle((start, i + 0.1), width, 0.8, color='blue') ax.add_patch(rect) plt.text(mean, i + 0.4, s, horizontalalignment="center") ax.set_xlim((mdates.date2num(df.loc[:, "datemin"].min().to_pydatetime()) - 30, mdates.date2num(df.loc[:, "datemax"].max().to_pydatetime()) + 30)) ax.set_ylim(0, i + 1) # assign date locator / formatter to the x-axis to get proper labels locator = mdates.AutoDateLocator(minticks=3) formatter = mdates.AutoDateFormatter(locator) ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(formatter)
cats = {"sleep" : 1, "eat" : 2, "work" : 3} colormapping = {"sleep" : "C0", "eat" : "C1", "work" : "C2"} verts = [] colors = [] for d in data: v = [(mdates.date2num(d[0]), cats[d[2]]-.4), (mdates.date2num(d[0]), cats[d[2]]+.4), (mdates.date2num(d[1]), cats[d[2]]+.4), (mdates.date2num(d[1]), cats[d[2]]-.4), (mdates.date2num(d[0]), cats[d[2]]-.4)] verts.append(v) colors.append(colormapping[d[2]]) bars = PolyCollection(verts, facecolors=colors) fig, ax = plt.subplots() ax.add_collection(bars) ax.autoscale() loc = mdates.MinuteLocator(byminute=[0,15,30,45]) ax.xaxis.set_major_locator(loc) ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc)) ax.set_yticks([1,2,3]) ax.set_yticklabels(["sleep", "eat", "work"]) ### display the plot plt.show()
async def hist(self, ctx, *args: str): """Shows the histogram of problems solved on Codeforces over time for the handles provided""" filt = cf_common.SubFilter() args = filt.parse(args) phase_days = 1 handles = [] for arg in args: if arg[0:11] == 'phase_days=': phase_days = int(arg[11:]) else: handles.append(arg) if phase_days < 1: raise GraphCogError('Invalid parameters') phase_time = dt.timedelta(days=phase_days) handles = handles or ['!' + str(ctx.author)] handles = await cf_common.resolve_handles(ctx, self.converter, handles) resp = [await cf.user.status(handle=handle) for handle in handles] all_solved_subs = [filt.filter_subs(submissions) for submissions in resp] if not any(all_solved_subs): raise GraphCogError(f'There are no problems within the specified parameters.') plt.clf() plt.xlabel('Time') plt.ylabel('Number solved') if len(handles) == 1: handle, solved_by_type = handles[0], _classify_submissions(all_solved_subs[0]) all_times = [[dt.datetime.fromtimestamp(sub.creationTimeSeconds) for sub in solved_by_type[sub_type]] for sub_type in filt.types] nice_names = nice_sub_type(filt.types) labels = [name.format(len(times)) for name, times in zip(nice_names, all_times)] dlo = min(itertools.chain.from_iterable(all_times)).date() dhi = min(dt.datetime.today() + dt.timedelta(days=1), dt.datetime.fromtimestamp(filt.dhi)).date() phase_cnt = math.ceil((dhi - dlo) / phase_time) plt.hist( all_times, stacked=True, label=labels, range=(dhi - phase_cnt * phase_time, dhi), bins=min(40, phase_cnt)) total = sum(map(len, all_times)) plt.legend(title=f'{handle}: {total}', title_fontsize=plt.rcParams['legend.fontsize']) else: all_times = [[dt.datetime.fromtimestamp(sub.creationTimeSeconds) for sub in solved_subs] for solved_subs in all_solved_subs] # NOTE: matplotlib ignores labels that begin with _ # https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend # Add zero-width space to work around this labels = [gc.StrWrap(f'{handle}: {len(times)}') for handle, times in zip(handles, all_times)] dlo = min(itertools.chain.from_iterable(all_times)).date() dhi = min(dt.datetime.today() + dt.timedelta(days=1), dt.datetime.fromtimestamp(filt.dhi)).date() phase_cnt = math.ceil((dhi - dlo) / phase_time) plt.hist( all_times, range=(dhi - phase_cnt * phase_time, dhi), bins=min(40 // len(handles), phase_cnt)) plt.legend(labels) # NOTE: In case of nested list, matplotlib decides type using 1st sublist, # it assumes float when 1st sublist is empty. # Hence explicitly assigning locator and formatter is must here. locator = mdates.AutoDateLocator() plt.gca().xaxis.set_major_locator(locator) plt.gca().xaxis.set_major_formatter(mdates.AutoDateFormatter(locator)) plt.gcf().autofmt_xdate() discord_file = gc.get_current_figure_as_file() embed = discord_common.cf_color_embed(title='Histogram of number of solved problems over time') discord_common.attach_image(embed, discord_file) discord_common.set_author_footer(embed, ctx.author) await ctx.send(embed=embed, file=discord_file)
def run_repetitions(semester, parameters, save=None): # Code to run the simulations... print('Running', parameters.repetitions, 'repetitions.') start_time = datetime.now() Ss = defaultdict(list) Es = defaultdict(list) Is = defaultdict(list) Rs = defaultdict(list) Qs = defaultdict(list) if parameters.verbose: print('Repetition:', end=" ") for i in range(parameters.repetitions): if parameters.verbose: print(i + 1, end=" ") this_semester = parameters.preprocess(semester) simulation = Simulation(this_semester, parameters) if type(parameters.initial_exposure) == int: parameters.initial_exposure = np.random.choice( list(this_semester.students), replace=False, size=parameters.initial_exposure) for s in parameters.initial_exposure: simulation.infect(s, parameters.start_date) simulation.run(verbose=parameters.repetitions == 1) T, S, E, I, R, Q = simulation.get_statistics() for t, s, e, i, r, q in zip(T, S, E, I, R, Q): Ss[t].append(s) Es[t].append(e) Is[t].append(i) Rs[t].append(r) Qs[t].append(q) # Print text summary of the results. if parameters.verbose: print() print('Initial exposed:', len(parameters.initial_exposure)) print('Average final exposure count is', np.mean(Rs[max(Rs)])) if (len(Rs[max(Rs)]) > 1): print('Sample Standard deviation is:', np.std(Rs[max(Rs)], ddof=1)) comp_time = datetime.now() - start_time if parameters.verbose: print('Total compuation time:', comp_time) print('Average computation time:', comp_time / parameters.repetitions) quarantines = np.array([np.mean(Qs[t]) for t in T]) print('Quarantine: max', max(quarantines), ', avg', np.mean(quarantines)) # Plot mean values. locator = mdates.AutoDateLocator(interval_multiples=False) formatter = mdates.AutoDateFormatter(locator) fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(16, 4.5)) ax1.plot(T, [np.mean(Ss[t]) for t in T]) ax1.plot(T, [np.mean(Es[t]) for t in T]) ax1.plot(T, [np.mean(Is[t]) for t in T]) ax1.plot(T, [np.mean(Rs[t]) for t in T]) ax1.plot(T, [np.mean(Qs[t]) for t in T]) ax1.legend(['S', 'E', 'I', 'R', 'Q']) ax1.set_title('Epidemic Progression') ax1.set_xlabel('Day of Year') ax1.set_ylabel('Number of Students') ax1.xaxis.set_major_locator(locator) # Annoying code to make dates work! ax1.xaxis.set_major_formatter(formatter) # Plot percentiles for total exposed. ps = [1, 5, 25, 50, 75, 95, 100] ps.sort(reverse=True) Ep = {p: [np.percentile(Es[t], p) for t in T] for p in ps} for p in ps: ax2.plot(T, Ep[p]) ax2.legend(list(map(lambda x: str(x) + '%', ps))) ax2.set_title('Percentiles of Exposed Students') ax2.set_xlabel('Day of Year') ax2.set_ylabel('Number of Students') ax2.xaxis.set_major_locator(locator) ax2.xaxis.set_major_formatter(formatter) # Plot percentiles for number infectious. Ip = {p: [np.percentile(Is[t], p) for t in T] for p in ps} for p in ps: ax3.plot(T, Ip[p]) ax3.legend(list(map(lambda x: str(x) + '%', ps))) ax3.set_title('Percentiles of Infectious Students') ax3.set_xlabel('Day of Year') ax3.set_ylabel('Number of Students') ax3.xaxis.set_major_locator(locator) ax3.xaxis.set_major_formatter(formatter) fig.autofmt_xdate() plt.tight_layout() if save is not None: plt.savefig(save) else: plt.show()