Example #1
0
def applyPlotOptions(fig, ax, options):
  if options.xlim: xlim(float(options.xlim.split(",")[0]), float(options.xlim.split(",")[1]))
  if options.xticks:
    vals = options.xticks.split(",")
    if len(vals)==1: ax.tick_params(axis='x', which='major', labelsize=float(vals[0]))
    elif len(vals)==4: xticks(arange(float(vals[0]), float(vals[1]), float(vals[2])), size=float(vals[3]))
    else: 
      print "Error: ticks must be given as one float (<SIZE>) or four floats (<MIN>,<MAX>,<STEP>,<SIZE>)"
      sys.exit()
  if options.xtime1: ax.xaxis.set_major_formatter(ff(m2hm1))
  if options.xtime2: ax.xaxis.set_major_formatter(ff(m2hm2))
  if options.xgrid: ax.xaxis.grid(True)
  if options.xlabel: xlabel(options.xlabel, size=options.xlabelsize)

  if options.ylim: ylim(float(options.ylim.split(",")[0]), float(options.ylim.split(",")[1]))
  if options.yticks:
    vals = options.yticks.split(",")
    if len(vals)==1: ax.tick_params(axis='y', which='major', labelsize=float(vals[0]))
    elif len(vals)==4: yticks(arange(float(vals[0]), float(vals[1]), float(vals[2])), size=float(vals[3]))
    else: 
      print "Error: ticks must be given as one float (<SIZE>) or four floats (<MIN>,<MAX>,<STEP>,<SIZE>)"
      sys.exit()
  if options.ytime1: ax.yaxis.set_major_formatter(ff(m2hm1))
  if options.ytime2: ax.yaxis.set_major_formatter(ff(m2hm2))
  if options.ygrid: ax.yaxis.grid(True)
  if options.ylabel: ylabel(options.ylabel, size=options.ylabelsize)

  if options.title: title(options.title, size=options.titlesize)
  if options.adjust:
    vals = options.adjust.split(",")
    if len(vals)==2: fig.subplots_adjust(left=float(vals[0]), bottom=float(vals[1]))
    elif len(vals)==4: fig.subplots_adjust(left=float(vals[0]), bottom=float(vals[1]), right=float(vals[2]), top=float(vals[3]))
    else: 
      print "Error: adjust must be given as two floats (<LEFT>,<BOTTOM>) or four floats (<LEFT>,<BOTTOM>,<RIGHT>,<TOP>)"
      sys.exit()
Example #2
0
    def show_figure(self):
        # some cosmetics on the figure
        current_axes = self.fig.gca()
        current_axes.xaxis.set_minor_locator(matplotlib.dates.HourLocator())
        current_axes.xaxis.set_major_locator(matplotlib.dates.DayLocator())
        current_axes.xaxis.set_major_formatter(ff(m2yyyymmdd))
        current_axes.xaxis.set_minor_formatter(ff(m2hm))
        current_axes.set_xlabel("UTC Time")
        current_axes.set_ylabel("Signal Strength")

        for label in current_axes.xaxis.get_majorticklabels():
            label.set_fontsize(8)
            label.set_rotation(30)  # 'vertical')
            # label.set_horizontalalignment='left'

        for label in current_axes.xaxis.get_minorticklabels():
            label.set_fontsize(12 if len(self.daysList.keys()) == 1 else 8)

        # specific drawings for linked to each sid_file: flares and sunrise/sunset
        bottom_max, top_max = current_axes.get_ylim()
        for sid_file in self.sid_files:
            # for each flare from NOAA, draw the lines and box with flares intensity
            for eventName, BeginTime, MaxTime, EndTime, Particulars in sid_file.XRAlist:
                self.graph.vlines([BeginTime, MaxTime, EndTime],
                                  0,
                                  self.max_data,
                                  color=['g', 'r', 'y'],
                                  linestyles='dotted')
                self.graph.text(MaxTime,
                                self.max_data +
                                (top_max - self.max_data) / 4.0,
                                Particulars,
                                horizontalalignment='center',
                                bbox={
                                    'facecolor': 'w',
                                    'alpha': 0.5,
                                    'fill': True
                                })
            # draw the rectangles for rising and setting of the sun with astronomical twilight
            if sid_file.rising < sid_file.setting:
                self.graph.axvspan(sid_file.startTime,
                                   sid_file.rising.datetime(),
                                   facecolor='blue',
                                   alpha=0.1)
                self.graph.axvspan(sid_file.setting.datetime(),
                                   max(sid_file.timestamp),
                                   facecolor='blue',
                                   alpha=0.1)
            else:
                self.graph.axvspan(sid_file.setting.datetime(),
                                   sid_file.rising.datetime(),
                                   facecolor='blue',
                                   alpha=0.1)

        self.canvas.show()
Example #3
0
    def show_figure(self):
        # some cosmetics on the figure
        current_axes = self.fig.gca()
        current_axes.xaxis.set_minor_locator(matplotlib.dates.HourLocator())
        current_axes.xaxis.set_major_locator(matplotlib.dates.DayLocator())
        current_axes.xaxis.set_major_formatter(ff(m2yyyymmdd))
        current_axes.xaxis.set_minor_formatter(ff(m2hm))
        current_axes.set_xlabel("UTC Time")
        current_axes.set_ylabel("Signal Strength")

        for label in current_axes.xaxis.get_majorticklabels():
            label.set_fontsize(8)
            label.set_rotation(30)  # 'vertical')
            # label.set_horizontalalignment='left'

        for label in current_axes.xaxis.get_minorticklabels():
            label.set_fontsize(12 if len(self.daysList.keys()) == 1 else 8)

        # specific drawings for linked to each sid_file: flares and sunrise/sunset
        bottom_max, top_max = current_axes.get_ylim()
        for sid_file in self.sid_files:
            # for each flare from NOAA, draw the lines and box with flares intensity
            for eventName, BeginTime, MaxTime, EndTime, Particulars in sid_file.XRAlist:
                self.graph.vlines([BeginTime, MaxTime, EndTime], 0, self.max_data,
                           color=['g', 'r', 'y'], linestyles='dotted')
                self.graph.text(MaxTime, self.max_data + (top_max - self.max_data) / 4.0,
                                Particulars, horizontalalignment='center',
                                bbox={'facecolor': 'w', 'alpha': 0.5, 'fill': True})
            # draw the rectangles for rising and setting of the sun with astronomical twilight
            if sid_file.rising < sid_file.setting:
                self.graph.axvspan(sid_file.startTime, sid_file.rising.datetime(),
                           facecolor='blue', alpha=0.1)
                self.graph.axvspan(sid_file.setting.datetime(), max(sid_file.timestamp),
                           facecolor='blue', alpha=0.1)
            else:
                self.graph.axvspan(sid_file.setting.datetime(), sid_file.rising.datetime(),
                           facecolor='blue', alpha=0.1)

        self.canvas.show()
Example #4
0
def plot_probability(times, smoothfit=True):
    # dates is a list of strings where each element takes form "mm yy"
    times = [roundval(x) for x in times]

    # Convert to unique list
    time_count = Counter(times)
    time_count = sorted(time_count.items())

    times = [x[0] for x in time_count]
    quantity = np.array([float(x[1]) for x in time_count])
    quantity = quantity / sum(quantity)

    if smoothfit:
        times_new = np.linspace(min(times), max(times), 300)
        quantity = spline(times, quantity, times_new)
        times = times_new.tolist()

    fig, ax = plt.subplots()
    plt.plot(
        times,
        quantity,
        'b',
        linewidth=2.0,
    )

    # Remove some x-labels to reduce clutter in the plot
    label_spacing = 60  # 1 label per hour
    for ndx, item in enumerate(times):
        if ndx % label_spacing != 0:
            times[ndx] = ''

    ax.set_xlabel('Time')
    ax.set_xticklabels(times)
    # Rotate x axis labels slightly
    labels = ax.get_xticklabels()
    for label in labels:
        label.set_rotation(30)
    ax.set_xlim(0, 24 * 60)  # 0 to 24 hours
    ax.xaxis.set_major_locator(pylab.MultipleLocator(60))
    ax.xaxis.set_major_formatter(ff(min_to_hourmin))

    ax.set_ylabel('Probability')
    ax.set_ylim(0, max(quantity))

    titlestr = 'Probability Over Time of ' + config.MAIL_TO_ANALYSE + ' Mail'
    plt.title(titlestr)
    plt.draw()
Example #5
0
def plot_dates_sent(dates, times):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot_date(dates, times)

    # Rotate x axis labels slightly
    labels = ax.get_xticklabels()
    for label in labels:
        label.set_rotation(30)
    ax.set_ylim(0, 24 * 60)  # 0 to 24 hours
    ax.yaxis.set_major_locator(pylab.MultipleLocator(60))
    ax.yaxis.set_major_formatter(ff(min_to_hourmin))

    plt.title('Times of Message Deliveries')
    plt.xlabel('Date')
    plt.ylabel('Delivery Time (24hr)')
    plt.draw()
Example #6
0
def plot_dates_sent(dates, times):
	fig = plt.figure()
	ax = fig.add_subplot(111)
	ax.plot_date(dates, times)

	# Rotate x axis labels slightly
	labels = ax.get_xticklabels()
	for label in labels:
	    label.set_rotation(30)
	ax.set_ylim(0,24*60) # 0 to 24 hours
	ax.yaxis.set_major_locator(pylab.MultipleLocator(60))
	ax.yaxis.set_major_formatter(ff(min_to_hourmin))

	plt.title('Times of Message Deliveries')
	plt.xlabel('Date')
	plt.ylabel('Delivery Time (24hr)')
	plt.draw()
Example #7
0
def plot_timestamps(timestamps: pd.Series, user: GHUser, timezone=None):
    """Plot datetimes with matplotlib."""

    if timezone is not None and timestamps is not None:
        timestamps = timestamps.dt.tz_convert(timezone)

    # color points distant from midday (1pm)
    dist_from_13h = abs(timestamps.dt.hour - 13)

    times = [dt2m(x) for x in timestamps]
    times = [x + 1440 if x < 240 else x for x in times]  # Looping

    dates = [x.date() for x in timestamps.dt.to_pydatetime()]

    fig, ax = plt.subplots(figsize=(8, 6))

    ax.set_ylim(240, 1440 + 240)  # 4am
    ax.set_ylabel(timezone or 'UTC' + f' ({user.location})')
    ax.yaxis.set_major_locator(ticker.MultipleLocator(60))
    # ax.yaxis.set_minor_locator(ticker.MultipleLocator(15))
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.get_xaxis().tick_bottom()
    ax.get_yaxis().tick_left()
    ax.yaxis.set_major_formatter(ff(m2hm))

    ax.yaxis.grid(color='k', linestyle='--', linewidth=0.5, alpha=.3)
    ax.set_title(user.username)
    ax.set_xlim([min(dates)-timedelta(days=1), max(dates) + timedelta(days=1)])

    # ax.scatter(dates, times, c=dist_from_13h, cmap=discrete_cmap(24, 'autumn_r'))
    # sns.lineplot(date2num(dates), times, ci=99, alpha =0.3)
    sns.scatterplot(date2num(dates), times, alpha=0.7)
    weekends = get_weekends(dates)
    for start, end in weekends:
        ax.axvspan(start - timedelta(hours=12), end + timedelta(hours=12), alpha=0.05, color='gray')

    plt.autoscale(True, axis='x', tight=True)
    plt.gcf().autofmt_xdate()

    plot_filename = create_plot_filename(user.username)
    fig.savefig(to_local_path(plot_filename))
    add_plot(user, plot_filename)
    return plot_filename
Example #8
0
def plot_probability(times, smoothfit=True):
	# dates is a list of strings where each element takes form "mm yy"
	times = [roundval(x) for x in times]

	# Convert to unique list
	time_count = Counter(times)
	time_count = sorted(time_count.items())

	times = [x[0] for x in time_count]
	quantity = np.array([float(x[1]) for x in time_count])
	quantity = quantity/sum(quantity)

	if smoothfit:
		times_new = np.linspace(min(times), max(times), 300)
		quantity = spline(times,quantity,times_new)
		times = times_new.tolist()

	fig, ax = plt.subplots()
	plt.plot(times, quantity, 'b', linewidth=2.0, )

	# Remove some x-labels to reduce clutter in the plot
	label_spacing = 60 # 1 label per hour
	for ndx, item in enumerate(times):
	 	if ndx%label_spacing != 0:
				times[ndx] = ''

	ax.set_xlabel('Time')
	ax.set_xticklabels(times)
	# Rotate x axis labels slightly
	labels = ax.get_xticklabels()
	for label in labels:
	    label.set_rotation(30)
	ax.set_xlim(0,24*60) # 0 to 24 hours
	ax.xaxis.set_major_locator(pylab.MultipleLocator(60))
	ax.xaxis.set_major_formatter(ff(min_to_hourmin))

	ax.set_ylabel('Probability')
	ax.set_ylim(0, max(quantity))

	titlestr = 'Probability Over Time of ' + config.MAIL_TO_ANALYSE + ' Mail'
	plt.title(titlestr)
	plt.draw()
def f(activity, vehicle, dropoff, dw, dw_start, dw_end, tw, tw_start, tw_end,
      far_dc, personel_daily_cost, cargo_daily_cost, lcv_daily_cost,
      truck_daily_cost, cargo_emission, lcv_emission, truck_emission):

    #first_leg_time = math.ceil(b.avg_first_leg*60/50000)
    first_leg_time = 6000 * 60 / 20000

    #tour_time = math.ceil(b.avg_tour*60/20000)*6
    tour_time = time_sim_results[vehicle][activity] * (
        200 / vehicle_sim_results[vehicle][activity])

    time_dropoff = dropoff * (200 / vehicle_sim_results[vehicle][activity])

    #return_leg_time = math.ceil(b.avg_return_leg*60/50000)
    return_leg_time = 6000 * 60 / 20000

    time_rungis = 30000 * 60 / 70000

    # Print the type of vehicle

    print('The fleet is composed of ' +
          str(vehicle_sim_results[vehicle][activity]) + ' ' +
          list_vehicle[vehicle] + ".")
    print('The vehicles have a capacity of ' +
          str(vehicle_capacity[vehicle][activity]) +
          ' client(s), each vehicle delivers in average ' +
          str(round(200 / vehicle_sim_results[vehicle][activity], 1)) +
          " client(s), each tour has an average length of " +
          str(distance_sim_results[vehicle][activity]) + " km.")
    print('The average driving time between two deliveries is ' +
          str(time_sim_results[vehicle][activity]) + " min.")
    #print('Each vehicle delivers in average ' + str(round(hot_fix_clients[clients]/vehicle_sim_results[clients][capacity])) + " clients.")

    #print("Therefore, average total driving time is " + str(tour_time) + " min." )

    city_line_width = 3
    line_width = 3

    if far_dc:

        fig2, ax2 = plt.subplots()
        """ax2.bar(0, 30, bottom=b.avg_first_leg, color = r_color)
        ax2.bar(1, 0, bottom=b.avg_tour, color = r_color)
        ax2.bar(2, 30, bottom=b.avg_return_leg+b.avg_first_leg + b.avg_tour, color = r_color)"""

        ax2.bar(0, first_leg_time, bottom=dw_start, color=driving_color)
        ax2.bar(0,
                time_rungis,
                bottom=dw_start + first_leg_time,
                color=rungis_color,
                label="Rungis")

        ax2.axhline(y=dw_start + first_leg_time + time_rungis,
                    linewidth=city_line_width,
                    color='#CDC7C6',
                    linestyle='-',
                    label="In city",
                    zorder=2)

        ax2.bar(1,
                tour_time,
                bottom=dw_start + first_leg_time + time_rungis,
                color=driving_color,
                label="Driving")
        ax2.bar(1,
                time_dropoff,
                bottom=dw_start + first_leg_time + time_rungis + tour_time,
                color=delivering_color,
                label="Delivering       ")

        ax2.axhline(y=dw_start + first_leg_time + time_rungis + tour_time +
                    time_dropoff,
                    color='#CDC7C6',
                    linestyle='-',
                    linewidth=city_line_width,
                    zorder=2)

        ax2.bar(2,
                return_leg_time,
                bottom=dw_start + first_leg_time + time_rungis + tour_time +
                time_dropoff,
                color=driving_color)
        ax2.bar(2,
                time_rungis,
                bottom=dw_start + first_leg_time + time_rungis + tour_time +
                time_dropoff + return_leg_time,
                color=rungis_color)

        #ax2.set_ylim(dw_start-100, dw_start + first_leg_time + time_rungis + tour_time + time_dropoff + return_leg_time + time_rungis + 100)
        ax2.set_ylim(dw_start - 100, dw_end + 100)

    else:
        fig2, ax2 = plt.subplots()
        ax2.bar(0, first_leg_time, bottom=dw_start, color=driving_color)

        ax2.axhline(y=dw_start + first_leg_time,
                    color='#CDC7C6',
                    linestyle='-',
                    linewidth=city_line_width,
                    zorder=2)

        ax2.bar(1,
                tour_time,
                bottom=first_leg_time + dw_start,
                color=driving_color,
                label="Driving")
        ax2.bar(1,
                time_dropoff,
                bottom=first_leg_time + tour_time + dw_start,
                color=delivering_color,
                label="Delivering       ")

        ax2.axhline(y=dw_start + first_leg_time + tour_time + time_dropoff,
                    color='#CDC7C6',
                    linestyle='-',
                    label="Within city",
                    linewidth=city_line_width,
                    zorder=2)

        ax2.bar(2,
                return_leg_time,
                bottom=first_leg_time + tour_time + dw_start + time_dropoff,
                color=driving_color)

        #ax2.set_ylim(dw_start-100, dw_start + first_leg_time + time_rungis + tour_time + time_dropoff + return_leg_time + time_rungis + 100)

    if dw_start + first_leg_time + time_rungis + tour_time + time_dropoff + return_leg_time + time_rungis + 100 > dw_end + 100:
        ax2.set_ylim(
            dw_start - 100, dw_start + first_leg_time + time_rungis +
            tour_time + time_dropoff + return_leg_time + time_rungis + 100)

    else:
        ax2.set_ylim(dw_start - 100, dw_end + 100)

    ax2.yaxis.set_major_formatter(ff(m2hm))

    # Working day
    dw_color = "#008240"
    if dw:
        ax2.axhline(y=dw_start,
                    color=dw_color,
                    linestyle='-',
                    label="Time shift",
                    linewidth=line_width,
                    zorder=2)
        ax2.axhline(y=dw_end,
                    color=dw_color,
                    linestyle='-',
                    linewidth=line_width,
                    zorder=2)

    # Time window from clients or city
    tw_color = "#A0211B"

    if tw:
        ax2.axhline(y=tw_start,
                    color=tw_color,
                    linestyle='--',
                    label="Time Window",
                    linewidth=line_width,
                    zorder=2)
        ax2.axhline(y=tw_end,
                    color=tw_color,
                    linestyle='--',
                    linewidth=line_width,
                    zorder=2)

    ax2.set_title("Average working shift of one " + list_vehicle[vehicle] +
                  " delivering " + list_activity[activity])
    ax2.set_xticklabels(["", "", "First leg", "", "Tour", "", "Return leg"])
    ax2.tick_params(bottom=False)
    ax2.legend(bbox_to_anchor=(1.05, 1), loc=2)

    fig2.set_size_inches(15.5, 9.5)

    # Plot cost per delivery

    cargo_cost = vehicle_sim_results[0][activity] * (personel_daily_cost +
                                                     cargo_daily_cost)
    lcv_cost = vehicle_sim_results[1][activity] * (personel_daily_cost +
                                                   lcv_daily_cost)
    truck_cost = vehicle_sim_results[2][activity] * (personel_daily_cost +
                                                     truck_daily_cost)

    fig3, ax3 = plt.subplots()

    ax3.bar(0, cargo_cost, color=driving_color)
    ax3.bar(1, lcv_cost, color=driving_color)
    ax3.bar(2, truck_cost, color=driving_color)

    ax3.set_title("Total cost of delivery for " + list_activity[activity] +
                  " (in €)")
    ax3.set_xticklabels([
        "", "",
        str(vehicle_sim_results[0][activity]) + " cargo bikes", "",
        str(vehicle_sim_results[1][activity]) + " LCVs", "",
        str(vehicle_sim_results[2][activity]) + " trucks"
    ])
    ax3.yaxis.set_major_formatter(
        matplotlib.ticker.FormatStrFormatter('€%1.2f'))
    fig3.set_size_inches(13.55, 8)

    # Plot C02 emissions
    if far_dc:
        fig4, ax4 = plt.subplots()
        ax4.bar(0,
                cargo_emission * (distance_sim_results[0][activity] *
                                  vehicle_sim_results[0][activity]),
                color=driving_color,
                label="Tour")
        ax4.bar(0,
                cargo_emission * 15 * vehicle_sim_results[0][activity],
                bottom=cargo_emission * (distance_sim_results[0][activity] *
                                         vehicle_sim_results[0][activity]),
                color=rungis_color,
                label="Rungis")

        ax4.bar(1,
                lcv_emission * (distance_sim_results[1][activity] *
                                vehicle_sim_results[1][activity]),
                color=driving_color)
        ax4.bar(1,
                lcv_emission * 15 * vehicle_sim_results[1][activity],
                bottom=lcv_emission * (distance_sim_results[1][activity] *
                                       vehicle_sim_results[1][activity]),
                color=rungis_color)

        ax4.bar(2,
                truck_emission * (distance_sim_results[2][activity] *
                                  vehicle_sim_results[2][activity]),
                color=driving_color)
        ax4.bar(2,
                truck_emission * 15 * vehicle_sim_results[2][activity],
                bottom=truck_emission * (distance_sim_results[2][activity] *
                                         vehicle_sim_results[2][activity]),
                color=rungis_color)

    else:
        fig4, ax4 = plt.subplots()

        ax4.bar(0,
                cargo_emission * (distance_sim_results[0][activity] *
                                  vehicle_sim_results[0][activity]),
                color=driving_color,
                label="Tour")
        ax4.bar(1,
                lcv_emission * (distance_sim_results[1][activity] *
                                vehicle_sim_results[1][activity]),
                color=driving_color)
        ax4.bar(2,
                truck_emission * (distance_sim_results[2][activity] *
                                  vehicle_sim_results[2][activity]),
                color=driving_color)

    ax4.set_title("Total amount of C02 emissions to deliver " +
                  list_activity[activity] + " (in g of CO2)")
    ax4.set_xticklabels([
        "", "",
        str(vehicle_sim_results[0][activity]) + " cargo bikes", "",
        str(vehicle_sim_results[1][activity]) + " LCVs", "",
        str(vehicle_sim_results[2][activity]) + " trucks"
    ])
    ax4.legend(bbox_to_anchor=(1.05, 1), loc=2)

    fig4.set_size_inches(13.95, 8)
Example #10
0
    h = int(x/60)
    m = int(x%60)
    return '%(h)02d:%(m)02d' % {'h':h,'m':m}


fig, ax = plt.subplots(figsize=(12,6))
dates = new_table.index
dates = dates.date
dates = dates.tolist()
wake_time_as_y = new_table['wake_time']
wake_time_as_y = map(lambda x:dt2m(x), wake_time_as_y)
ax.plot_date(dates, wake_time_as_y, color = 'red', label = 'wake_time')

ax.set_xlim([dates[0],dates[len(dates)-1]])
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
ax.xaxis.set_minor_locator(mdates.DayLocator())
fmt = mdates.DateFormatter('%Y/%m')
ax.xaxis.set_major_formatter(fmt)
ax.xaxis.grid(color='#ffcf06', linestyle=':', linewidth=0.5)

ax.set_ylim(180,900)
ax.yaxis.set_major_locator(MultipleLocator(30))
ax.yaxis.set_major_formatter(ff(m2hm))
ax.yaxis.grid(color='black', linestyle=':', linewidth=0.5)

plt.legend(loc='best')
plt.xlabel('Date' )
plt.ylabel('Hour (24hr)' )
plt.title('wake time figure')
plt.show()
Example #11
0
    def plot_filelist(self, filelist, showPlot = True, eMail=None, pdf=None, web=False, config=None):
        """Read the files in the filelist parameters.
           Each data are combine in one plot.
           That plot can be displayed or not (showPlot), sent by email (eMail provided), saved as pdf (pdf provided).
           Connection for the given days to NOAA website is possible (web) in order to draw vetical lines for XRA data."""
        emailText = []
        Tstamp = lambda HHMM: datetime.datetime(year=int(day[:4]), month=int(day[4:6]), day=int(day[6:8]),
                                                hour=int(HHMM[:2]), minute=int(HHMM[2:]))
        ## Sunrise and sunset shade
        #sun_rise = 6.0
        #sun_set  = 18.0
        #plt.axvspan(0.0, sun_rise, facecolor='blue', alpha=0.2)
        #plt.axvspan(sun_set, 24.0, facecolor='blue', alpha=0.2)

        if type(filelist) is str:
            if filelist.find(',') >= 0:  # file1,file2,...,fileN given as script argument
                filelist = filelist.split(",")
            else:
                filelist = (filelist, )
        filenames = []
        # use glob for one or more files
        filenames.extend([a for a in itertools.chain.from_iterable([glob.glob(f) for f in filelist])])
        #print (filenames)

        # plot's figure and axis
        fig = plt.figure()
        current_axes = fig.gca()
        current_axes.xaxis.set_minor_locator(matplotlib.dates.HourLocator())
        current_axes.xaxis.set_major_locator(matplotlib.dates.DayLocator())
        current_axes.xaxis.set_major_formatter(ff(self.m2yyyymmdd))
        current_axes.xaxis.set_minor_formatter(ff(self.m2hm))
        current_axes.set_xlabel("UTC Time")
        current_axes.set_ylabel("Signal Strength")

        ## Get data from files
        maxData, data_length = -1, -1; #  impossible values
        XRAlist = []      # flare list from NOAA
        daysList = set()  # date of NOAA's pages already retrieved, prevent multiple fetch
        figTitle = []     # list of file names (w/o path and extension) as figure's title
        # one color per station
        colorList = "brgcmy"
        colorStation = {}
        colorIdx = 0

        time.clock()
        for filename in sorted(filenames):
            figTitle.append(os.path.basename(filename)[:-4]) # extension .csv assumed
            sFile = SidFile(filename)
            for station in sFile.stations:
                # Does this station already have a color? if not, reserve one
                if station not in colorStation:
                    colorStation[station] = colorList[colorIdx % len(colorList)] + '-'  # format like 'b-'
                    colorIdx += 1
                # Add points to the plot
                plt.plot_date(sFile.timestamp, sFile.get_station_data(station), colorStation[station])
                # Extra housekeeping
                maxData = max(max(sFile.get_station_data(station)), maxData)  # maxData will be used later to put the XRA labels up
                #msg = str(len(sFile.get_station_data(station))) + " points plotted after reading " + os.path.basename(filename)
                msg = "[{}] {} points plotted after reading {}".format(station, len(sFile.get_station_data(station)), os.path.basename(filename))
                print (msg)
                emailText.append(msg)

                if web and sFile.startTime not in daysList:
                    # get the XRA data from NOAA website to draw corresponding lines on the plot
                    # fetch that day's flares on NOAA as not previously accessed
                    day = sFile.sid_params["utc_starttime"][:10].replace("-","")
                    #NOAA_URL = 'http://www.swpc.noaa.gov/ftpdir/warehouse/%s/%s_events/%sevents.txt' % (day[:4], day[:4], day)
                    #ftp://ftp.swpc.noaa.gov/pub/indices/events/20141030events.txt
                    NOAA_URL = 'ftp://ftp.swpc.noaa.gov/pub/indices/events/%sevents.txt' % (day)
                    response = None
                    if sys.version[0]<'3':  # python 2.7 vs. Python 3.3
                        try:
                            response = urllib2.urlopen(NOAA_URL)
                        except urllib2.HTTPError as err:                            
                            print (err,"\n",NOAA_URL)
                    else:
                        try:
                            response = urllib.request.urlopen(NOAA_URL)
                        except urllib.error.HTTPError as err:                            
                            print (err,"\n",NOAA_URL)
                    lastXRAlen = len(XRAlist) # save temporarly current number of XRA events in memory
                    if response:
                        for webline in response.read().splitlines():
                            if sys.version[0]>='3': webline = str(webline, 'utf-8') # Python 3: cast bytes to str
                            fields = webline.split()
                            if len(fields) >= 9 and not fields[0].startswith("#"):
                                if fields[1] == '+': fields.remove('+')
                                if fields[6] in ('XRA', ):  # maybe other event types could be of interrest
                                    #     eventName,    BeginTime,    MaxTime,      EndTime,      Particulars
                                    msg = fields[0]+" "+fields[1]+" "+fields[2]+" "+fields[3]+" "+fields[8]
                                    emailText.append(msg)
                                    print (msg)
                                    try:
                                        btime = Tstamp(fields[1])   # 'try' necessary as few occurences of --:-- instead of HH:MM exist
                                    except:
                                        pass
                                    try:
                                        mtime = Tstamp(fields[2])
                                    except:
                                        mtime = btime
                                    try:
                                        etime = Tstamp(fields[3])
                                    except:
                                        etime = mtime
                                    XRAlist.append( (fields[0], btime, mtime, etime, fields[8]) )  # as a tuple

                    msg = str(len(XRAlist) - lastXRAlen) + " XRA events recorded by NOAA on " + day
                    emailText.append(msg)
                    print (msg)
                # keep track of the days
                daysList.add(sFile.startTime)

        print ("All files read in", time.clock(), "sec.")

        if web: # add the lines marking the retrieved flares from NOAA
            alternate = 0
            for eventName, BeginTime, MaxTime, EndTime, Particulars in XRAlist:
                plt.vlines( [BeginTime, MaxTime, EndTime], 0, maxData,
                            color=['g','r','y'], linestyles='dotted')
                plt.text(MaxTime, alternate * maxData, Particulars, horizontalalignment='center',
                         bbox=dict(fill=True, alpha=0.5, facecolor='w'))
                alternate = 0 if alternate==1 else 1


        # plot/page size / figure size with on A4 paper
        if len(daysList) == 1:
            fig.set_size_inches(29.7 / 2.54, 21.0 / 2.54, forward=True)
        else:  # allow PDF poster for many days (monthly graph) --> use Adobe PDF Reader --> Print --> Poster mode
            fig.set_size_inches((29.7 / 2.54) * (len(daysList)/2.0), (21.0 / 2.54) / 2.0, forward=True)
        fig.subplots_adjust(bottom=0.08, left = 0.05, right = 0.98, top=0.95)

        # some cosmetics on the figure
        for label in current_axes.xaxis.get_majorticklabels():
            label.set_fontsize(8)
            label.set_rotation(30)  # 'vertical')
            #label.set_horizontalalignment='left'

        for label in current_axes.xaxis.get_minorticklabels():
            label.set_fontsize(12 if len(daysList) == 1 else 8)

        fig.suptitle(", ".join(figTitle))

        xLegend = 0.03
        for station, color in colorStation.items():
            fig.text(xLegend, 0.93, station, color=color[0], fontsize=12, bbox={'fc':"w", 'pad':10, 'ec':color[0]})
            xLegend += 0.05

        # actions requested by user
        if pdf or eMail:
            pp = PdfPages(pdf or 'Image.pdf')  # in case option eMail is given but not pdf
            plt.savefig(pp, format='pdf')
            pp.close()
        if showPlot: plt.show()
        if eMail: sendMail(config, eMail, "\n".join(emailText), pdf or 'Image.pdf')
Example #12
0
    datetime.datetime.strptime(foo, '%m/%d/%Y %H:%M:%S') for foo in elapsedtime
]


# [1] "Then format the Y axis as Hour:Minute using a custom formatter:"
def m2hm(x, i):
    h = int(x / 60)
    m = int(x % 60)
    return '%(h)02d:%(m)02d' % {'h': h, 'm': m}


inittime_mins = [dt2m(foo) for foo in inittime]
elaptime_mins = [dt2m(foo) for foo in elapsedtime]
#heights = [60,120,240]
print inittime_mins

fig = plt.figure(figsize=(12, 7))  #figsize in inches
ax = fig.add_subplot(1, 1, 1)
ax.bar(inittime, elaptime_mins, bottom=inittime_mins)

plt.xticks(rotation='vertical')

# matplotlib date format object
hfmt = dates.DateFormatter('%b %d')
ax.xaxis.set_major_formatter(hfmt)
ax.xaxis.set_major_locator(MultipleLocator(1.0))  #a tick mark a day

ax.set_ylim([0, 24 * 60])
ax.yaxis.set_major_formatter(ff(m2hm))
ax.yaxis.set_major_locator(pylab.MultipleLocator(60))  #a tick mark an hour
    times = races[race]

    winners.append(numpy.min(times))
    means.append(numpy.average(times))
    medians.append(numpy.median(times))
    spreads.append(numpy.std(times))
    dates.append(race.date())

x = mpl.dates.date2num(dates)
winners = numpy.array(winners)
medians = numpy.array(medians)
spreads = numpy.array(spreads)
 
fig = plt.figure()
ax = fig.add_subplot(111)
ax.yaxis.set_major_formatter(ff(sec2minsec))
plt.xlabel("Date of Parkrun")
plt.ylabel("Time (min:sec)")

ax.plot_date(x, winners, 'ro', label="Winning time")
ax.errorbar(x, medians, yerr=spreads, label="Median time (and spread)")

fig.autofmt_xdate()

legend = plt.legend()


format = "png"
imagedata = StringIO()
plt.savefig(imagedata, format=format, dpi=96)
utils.httpresponseheader("Content-Type", "image/%s" % format)
Example #14
0
    def plot_filelist(self, filelist, showPlot = True, eMail=None, pdf=None, web=False, config=None):
        """Read the files in the filelist parameters.
           Each data are combine in one plot.
           That plot can be displayed or not (showPlot), sent by email (eMail provided), saved as pdf (pdf provided).
           Connection for the given days to NOAA website is possible (web) in order to draw vetical lines for XRA data."""
        emailText = []
        Tstamp = lambda HHMM: datetime.datetime(year=int(day[:4]), month=int(day[4:6]), day=int(day[6:8]),
                                                hour=int(HHMM[:2]), minute=int(HHMM[2:]))
        ## Sunrise and sunset shade
        #sun_rise = 6.0
        #sun_set  = 18.0
        #plt.axvspan(0.0, sun_rise, facecolor='blue', alpha=0.2)
        #plt.axvspan(sun_set, 24.0, facecolor='blue', alpha=0.2)

        if type(filelist) is str:
            if filelist.find(',') >= 0:  # file1,file2,...,fileN given as script argument
                filelist = filelist.split(",")
            else:
                filelist = (filelist, )
        filenames = []
        # use glob for one or more files
        filenames.extend([a for a in itertools.chain.from_iterable(
                [glob.glob(os.path.expanduser(f)) for f in filelist])  ])
        #print (filenames)

        # plot's figure and axis
        fig = plt.figure()
        current_axes = fig.gca()
        current_axes.xaxis.set_minor_locator(matplotlib.dates.HourLocator())
        current_axes.xaxis.set_major_locator(matplotlib.dates.DayLocator())
        current_axes.xaxis.set_major_formatter(ff(self.m2yyyymmdd))
        current_axes.xaxis.set_minor_formatter(ff(self.m2hm))
        current_axes.set_xlabel("UTC Time")
        current_axes.set_ylabel("Signal Strength")

        ## Get data from files
        maxData, data_length = -1, -1; #  impossible values
        XRAlist = []      # flare list from NOAA
        daysList = set()  # date of NOAA's pages already retrieved, prevent multiple fetch
        figTitle = []     # list of file names (w/o path and extension) as figure's title
        # one color per station
        colorList = "brgcmy"
        colorStation = {}
        colorIdx = 0

        time.clock()
        for filename in sorted(filenames):
            figTitle.append(os.path.basename(filename)[:-4]) # extension .csv assumed
            sFile = SidFile(filename)
            for station in sFile.stations:
                # Does this station already have a color? if not, reserve one
                if station not in colorStation:
                    colorStation[station] = colorList[colorIdx % len(colorList)] + '-'  # format like 'b-'
                    colorIdx += 1
                # Add points to the plot
                plt.plot_date(sFile.timestamp, sFile.get_station_data(station), colorStation[station])
                # Extra housekeeping
                maxData = max(max(sFile.get_station_data(station)), maxData)  # maxData will be used later to put the XRA labels up
                #msg = str(len(sFile.get_station_data(station))) + " points plotted after reading " + os.path.basename(filename)
                msg = "[{}] {} points plotted after reading {}".format(station, len(sFile.get_station_data(station)), os.path.basename(filename))
                print (msg)
                emailText.append(msg)

                if web and sFile.startTime not in daysList:
                    # get the XRA data from NOAA website to draw corresponding lines on the plot
                    # fetch that day's flares on NOAA as not previously accessed
                    day = sFile.sid_params["utc_starttime"][:10].replace("-","")
                    #NOAA_URL = 'http://www.swpc.noaa.gov/ftpdir/warehouse/%s/%s_events/%sevents.txt' % (day[:4], day[:4], day)
                    #ftp://ftp.swpc.noaa.gov/pub/indices/events/20141030events.txt
                    NOAA_URL = 'ftp://ftp.swpc.noaa.gov/pub/indices/events/%sevents.txt' % (day)
                    response = None
                    if sys.version[0]<'3':  # python 2.7 vs. Python 3.3
                        try:
                            response = urllib2.urlopen(NOAA_URL)
                        except urllib2.HTTPError as err:                            
                            print (err,"\n",NOAA_URL)
                    else:
                        try:
                            response = urllib.request.urlopen(NOAA_URL)
                        except urllib.error.HTTPError as err:                            
                            print (err,"\n",NOAA_URL)
                    lastXRAlen = len(XRAlist) # save temporarly current number of XRA events in memory
                    if response:
                        for webline in response.read().splitlines():
                            if sys.version[0]>='3': webline = str(webline, 'utf-8') # Python 3: cast bytes to str
                            fields = webline.split()
                            if len(fields) >= 9 and not fields[0].startswith("#"):
                                if fields[1] == '+': fields.remove('+')
                                if fields[6] in ('XRA', ):  # maybe other event types could be of interrest
                                    #     eventName,    BeginTime,    MaxTime,      EndTime,      Particulars
                                    msg = fields[0]+" "+fields[1]+" "+fields[2]+" "+fields[3]+" "+fields[8]
                                    emailText.append(msg)
                                    print (msg)
                                    try:
                                        btime = Tstamp(fields[1])   # 'try' necessary as few occurences of --:-- instead of HH:MM exist
                                    except:
                                        pass
                                    try:
                                        mtime = Tstamp(fields[2])
                                    except:
                                        mtime = btime
                                    try:
                                        etime = Tstamp(fields[3])
                                    except:
                                        etime = mtime
                                    XRAlist.append( (fields[0], btime, mtime, etime, fields[8]) )  # as a tuple

                    msg = str(len(XRAlist) - lastXRAlen) + " XRA events recorded by NOAA on " + day
                    emailText.append(msg)
                    print (msg)
                # keep track of the days
                daysList.add(sFile.startTime)

        print ("All files read in", time.clock(), "sec.")

        if web: # add the lines marking the retrieved flares from NOAA
            alternate = 0
            for eventName, BeginTime, MaxTime, EndTime, Particulars in XRAlist:
                plt.vlines( [BeginTime, MaxTime, EndTime], 0, maxData,
                            color=['g','r','y'], linestyles='dotted')
                plt.text(MaxTime, alternate * maxData, Particulars, horizontalalignment='center',
                         bbox={'facecolor': 'w', 'alpha': 0.5, 'fill': True})
                alternate = 0 if alternate==1 else 1


        # plot/page size / figure size with on A4 paper
        if len(daysList) == 1:
            fig.set_size_inches(29.7 / 2.54, 21.0 / 2.54, forward=True)
        else:  # allow PDF poster for many days (monthly graph) --> use Adobe PDF Reader --> Print --> Poster mode
            fig.set_size_inches((29.7 / 2.54) * (len(daysList)/2.0), (21.0 / 2.54) / 2.0, forward=True)
        fig.subplots_adjust(bottom=0.08, left = 0.05, right = 0.98, top=0.95)

        # some cosmetics on the figure
        for label in current_axes.xaxis.get_majorticklabels():
            label.set_fontsize(8)
            label.set_rotation(30)  # 'vertical')
            #label.set_horizontalalignment='left'

        for label in current_axes.xaxis.get_minorticklabels():
            label.set_fontsize(12 if len(daysList) == 1 else 8)

        fig.suptitle(", ".join(figTitle))

        xLegend = 0.03
        for station, color in colorStation.items():
            fig.text(xLegend, 0.93, station, color=color[0], fontsize=12, bbox={'fc':"w", 'pad':10, 'ec':color[0]})
            xLegend += 0.05

        # actions requested by user
        if pdf or eMail:
            pp = PdfPages(pdf or 'Image.pdf')  # in case option eMail is given but not pdf
            plt.savefig(pp, format='pdf')
            pp.close()
        if showPlot: plt.show()
        if eMail: sendMail(config, eMail, "\n".join(emailText), pdf or 'Image.pdf')
Example #15
0
mn = [yy[:i].mean() for i in xrange(len(yy))]

x2 = [0, 0.3, 0.5, 0.75, 1, 1.25,1.5,1.75, 2]
y2 =[2.75, 2., 2.1,2.2,2.3,2.4,2.5, 2.6, 2.7]
s2 = UnivariateSpline(x2, y2, k=5)
yy2 = s2(t) 

mn2 = [yy2[:i].mean() for i in xrange(len(yy2))]

n = len(yy)
k=0
for i in xrange(1, n-1, 10):
    pylab.figure()
    pylab.plot(t[:i+1], yy[:i+1], 'g-', linewidth=4)
    pylab.plot(t[:i+1], mn[:i+1], 'g--', linewidth=4)


    pylab.plot(t[:i+1], yy2[:i+1], 'r-', linewidth=4)
    pylab.plot(t[:i+1], mn2[:i+1], 'r--', linewidth=4)

     
    pylab.gca().yaxis.set_major_formatter(ff(m2hm))
    pylab.ylabel("500m Split", fontsize=15, weight="bold")
    pylab.xlabel("Km", fontsize=15, weight="bold")
    pylab.xlim(0,2)
    pylab.ylim(1,3)

    pylab.gcf().savefig("plotframes/plot_%04d.png" % k)
    k+=1

# pylab.show()
def init():
    mpl_fig = plt.figure()
    ax = mpl_fig.add_subplot(111)
    ax.xaxis.set_major_formatter(ff(m2hm))
Example #17
0
def makeBarPlot(data,
                plotname="barplot.png",
                plot_size=(9, 7),
                invert_time=True):
    """
	data:	3-tuple of lists
			start_times:	list of datetime instances for event start
			end_times:		list of datetime instances for event end
			intervals:		list of timedelta instances for event duration

	Makes a bar plot, date vs. time of the computer activity.

	It's easy to put in the date data as datetime instances, but
	the time data needs a workaround. We turn the datetime intances
	into integers and then format the time axis accordingly.

	Places were there are a lot of lines as opposed to one block
	shows I was very attentive! [ironic]
	"""
    start_times, end_times, intervals = data  # we won't be using end_times

    ## x axis date data
    days = [dt.date() for dt in start_times]

    ## y axis workaround
    def dt2m(dt):
        return (dt.hour * 60) + dt.minute

    interval_mins = [i.seconds / 60 for i in intervals]  # height of the bars
    starttimes_mins = [dt2m(dt)
                       for dt in start_times]  # bottom point of the bars

    ## Set up the plot ##

    ## Decide colors
    bgcolor = "#DBFFFD"  #FDF6E3"
    plot_color = "#FDF6E3"
    label_color = "#D33582"
    spine_color = "#A0A1A1"
    bar_color = "#224596"  #279186"

    fig = plt.figure(figsize=plot_size, dpi=96)  # figsize in inches
    ax = fig.add_subplot(1, 1, 1)

    ## bar is (x, height of bar, bottom of bar)
    plt.bar(days,
            interval_mins,
            bottom=starttimes_mins,
            align="center",
            color=bar_color,
            alpha=0.8,
            edgecolor='none',
            linewidth=0)

    ## Customize the plot ##

    ax.spines['top'].set_position(('outward', 4))

    ## Show or hide the spines, ticks and labels
    # ax.axes.get_yaxis().set_visible(False)					# hides targeted axis labels & ticks
    plt.tick_params(
        size=0
    )  # affects only the major ticks, can add kwarg "axis=x" to affect only one axis
    for position, spine in ax.spines.iteritems(
    ):  # spines is a dict, position is the key
        # if position == 'top': continue						# doesn't affect top spine
        spine.set_visible(False)  # hides spine

    ## Customize the x axis
    # set limits for the x axis
    first_day = days[0]
    last_day = days[-1]
    # ax.set_xlim([first_day, last_day + datetime.timedelta(days=1)])
    ax.xaxis.set_major_locator(mdates.DayLocator(bymonthday=range(1, 32)))
    ax.xaxis.set_major_formatter(
        mdates.DateFormatter('%a %e'))  # format x axis tick labels as "mmm dd"
    ax.xaxis.tick_top()  # put the x axis date labels on top
    for label in ax.get_xticklabels():
        label.set_horizontalalignment('center')

    ## Customize the y axis
    ax.set_ylim([0, 24 * 60])
    if invert_time:
        ax.invert_yaxis(
        )  # time axis is from 00:00 (top) to 23:59 (bottom) like in iCal
    ax.yaxis.set_minor_locator(
        plt.MultipleLocator(60))  # a tick mark every hour
    ax.yaxis.set_major_locator(plt.MultipleLocator(
        4 * 60))  # a tick label every 4 hours

    # format y axis tick labels as Hour:Minute using a custom formatter
    def m2hm(x, i):
        h = int(x / 60)
        m = int(x % 60)
        return '%(h)2d:%(m)02d' % {
            'h': h,
            'm': m
        }  # hours don't show a leading 0 zero

    ax.yaxis.set_major_formatter(ff(m2hm))  # the custom formatter

    ## Set colors, sizes and transparency
    fig.patch.set_facecolor(bgcolor)
    fig.patch.set_alpha(0.5)
    ax.patch.set_facecolor(plot_color)
    ax.patch.set_alpha(0.0)
    ax.spines['top'].set_color(spine_color)
    ax.spines['top'].set_linewidth(1)
    ax.spines['top'].set_alpha(1.0)
    # set colors for the x axis date labels					# for some reason, this doesn't work if I put it above in the colour section
    for label in ax.get_xticklabels():
        label.set_color(label_color)
        label.set_fontsize(15)  # default is 12
        label.set_fontweight("1000")
    for label in ax.xaxis.get_majorticklabels():
        label.set_family("SimHei")  # Trebuchet MS works well enough too

    plt.savefig(plotname, dpi=96, bbox_inches="tight",
                transparent=False)  #, facecolor=fig.get_facecolor())
    # If we don't specify the edgecolor and facecolor for the figure when
    # saving with savefig, it will override the value we set earlier
    return
Example #18
0
def makeBarPlot(data, plotname="barplot.png", plot_size=(9,7), invert_time=True):
	"""
	data:	3-tuple of lists
			start_times:	list of datetime instances for event start
			end_times:		list of datetime instances for event end
			intervals:		list of timedelta instances for event duration

	Makes a bar plot, date vs. time of the computer activity.

	It's easy to put in the date data as datetime instances, but
	the time data needs a workaround. We turn the datetime intances
	into integers and then format the time axis accordingly.

	Places were there are a lot of lines as opposed to one block
	shows I was very attentive! [ironic]
	"""
	start_times, end_times, intervals = data				# we won't be using end_times

	## x axis date data
	days = [ dt.date() for dt in start_times ]

	## y axis workaround
	def dt2m(dt):
		return (dt.hour*60) + dt.minute
	interval_mins   = [ i.seconds/60 for i in intervals ]	# height of the bars
	starttimes_mins = [ dt2m(dt) for dt in start_times ]	# bottom point of the bars


	## Set up the plot ##


	## Decide colors
	bgcolor		= "#DBFFFD" #FDF6E3"
	plot_color 	= "#FDF6E3"
	label_color = "#D33582"
	spine_color = "#A0A1A1"
	bar_color	= "#224596"	#279186"

	fig = plt.figure(figsize=plot_size, dpi=96)				# figsize in inches
	ax = fig.add_subplot(1, 1, 1)

	## bar is (x, height of bar, bottom of bar)
	plt.bar(days, interval_mins, bottom=starttimes_mins,
			align="center", color=bar_color, alpha=0.8, edgecolor='none', linewidth=0)

	
	## Customize the plot ##

	ax.spines['top'].set_position(('outward', 4))

	## Show or hide the spines, ticks and labels
	# ax.axes.get_yaxis().set_visible(False)					# hides targeted axis labels & ticks
	plt.tick_params(size=0)									# affects only the major ticks, can add kwarg "axis=x" to affect only one axis
	for position, spine in ax.spines.iteritems():			# spines is a dict, position is the key
		# if position == 'top': continue						# doesn't affect top spine
		spine.set_visible(False)							# hides spine

	## Customize the x axis
	# set limits for the x axis
	first_day = days[0]
	last_day  = days[-1]
	# ax.set_xlim([first_day, last_day + datetime.timedelta(days=1)])
	ax.xaxis.set_major_locator(mdates.DayLocator(bymonthday=range(1,32)))
	ax.xaxis.set_major_formatter(mdates.DateFormatter('%a %e')) # format x axis tick labels as "mmm dd"
	ax.xaxis.tick_top()										# put the x axis date labels on top
	for label in ax.get_xticklabels():
		label.set_horizontalalignment('center')

	## Customize the y axis
	ax.set_ylim([0, 24*60])
	if invert_time:
		ax.invert_yaxis()									# time axis is from 00:00 (top) to 23:59 (bottom) like in iCal
	ax.yaxis.set_minor_locator(plt.MultipleLocator(60))		# a tick mark every hour
	ax.yaxis.set_major_locator(plt.MultipleLocator(4*60))	# a tick label every 4 hours
	# format y axis tick labels as Hour:Minute using a custom formatter
	def m2hm(x, i):
		h = int(x/60)
		m = int(x%60)
		return '%(h)2d:%(m)02d' % {'h':h,'m':m}				# hours don't show a leading 0 zero
	ax.yaxis.set_major_formatter(ff(m2hm))					# the custom formatter

	## Set colors, sizes and transparency
	fig.patch.set_facecolor(bgcolor)
	fig.patch.set_alpha(0.5)
	ax.patch.set_facecolor(plot_color)
	ax.patch.set_alpha(0.0)
	ax.spines['top'].set_color(spine_color)
	ax.spines['top'].set_linewidth(1)
	ax.spines['top'].set_alpha(1.0)
	# set colors for the x axis date labels					# for some reason, this doesn't work if I put it above in the colour section	
	for label in ax.get_xticklabels():
		label.set_color(label_color)
		label.set_fontsize(15)								# default is 12
		label.set_fontweight("1000")
	for label in ax.xaxis.get_majorticklabels():
		label.set_family("SimHei")							# Trebuchet MS works well enough too

	plt.savefig(plotname, dpi=96, bbox_inches="tight",
				transparent=False)#, facecolor=fig.get_facecolor())
				# If we don't specify the edgecolor and facecolor for the figure when
				# saving with savefig, it will override the value we set earlier
	return
    times = races[race]

    winners.append(numpy.min(times))
    means.append(numpy.average(times))
    medians.append(numpy.median(times))
    spreads.append(numpy.std(times))
    dates.append(race.date())

x = mpl.dates.date2num(dates)
winners = numpy.array(winners)
medians = numpy.array(medians)
spreads = numpy.array(spreads)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.yaxis.set_major_formatter(ff(sec2minsec))
plt.xlabel("Date of Parkrun")
plt.ylabel("Time (min:sec)")

ax.plot_date(x, winners, 'ro', label="Winning time")
ax.errorbar(x, medians, yerr=spreads, label="Median time (and spread)")

fig.autofmt_xdate()

legend = plt.legend()

format = "png"
imagedata = StringIO()
plt.savefig(imagedata, format=format, dpi=96)
utils.httpresponseheader("Content-Type", "image/%s" % format)
dumpMessage({