def proj_hse_totals(daily): if daily: hse_query = HseWeather.objects.filter( daily__production_date__lte=daily.production_date, daily__project=daily.project, ).order_by('daily__production_date') else: hse_query = None if not hse_query: return {f'proj_{key}': '' for key in hse_weather_schema}, None hse_series = { f'{key}_series': nan_array([val[key] for val in hse_query.values()]) for key in (*hse_weather_schema[:12], *hse_weather_schema[14:]) } hse_series['date_series'] = np.array( [val.daily.production_date for val in hse_query]) p_hse = { f'proj_{key}': sum(nan_array([val[key] for val in hse_query.values()])) for key in (*hse_weather_schema[:12], *hse_weather_schema[14:]) } return p_hse, hse_series
def month_receiver_total(daily, receivertype): if daily: rcvr_query = ReceiverProduction.objects.filter( Q(daily__production_date__year=daily.production_date.year) & Q(daily__production_date__month=daily.production_date.month) & Q(daily__production_date__day__lte=daily.production_date.day), receivertype=receivertype, ) else: rcvr_query = None if not rcvr_query: m_rcvr = {f'month_{key}': 0 for key in receiver_prod_schema} return m_rcvr m_rcvr = { f'month_{key}': sum(nan_array([val[key] for val in rcvr_query.values()])) for key in receiver_prod_schema[0:7] } m_rcvr['month_qc_field'] = nan_avg_array( [val['qc_field'] for val in rcvr_query.values()]) m_rcvr['month_qc_teams'] = nan_avg_array( [val['qc_teams'] for val in rcvr_query.values()]) m_rcvr['month_fc_teams'] = nan_avg_array( [val['fc_teams'] for val in rcvr_query.values()]) m_rcvr['month_bc_teams'] = nan_avg_array( [val['bc_teams'] for val in rcvr_query.values()]) m_rcvr['month_perc_node_skips'] = calc_ratio( m_rcvr['month_node_skips'], daily.project.planned_receivers) return m_rcvr
def week_receiver_total(daily, receivertype): if daily: end_date = daily.production_date start_date = end_date - timedelta(days=WEEKDAYS - 1) rcvr_query = ReceiverProduction.objects.filter( Q(daily__production_date__gte=start_date), Q(daily__production_date__lte=end_date), receivertype=receivertype, ) else: rcvr_query = None if not rcvr_query: w_rcvr = {f'week_{key}': 0 for key in receiver_prod_schema} return w_rcvr w_rcvr = { f'week_{key}': sum(nan_array([val[key] for val in rcvr_query.values()])) for key in receiver_prod_schema[0:7] } w_rcvr['week_qc_field'] = nan_avg_array( [val['qc_field'] for val in rcvr_query.values()]) w_rcvr['week_qc_teams'] = nan_avg_array( [val['qc_teams'] for val in rcvr_query.values()]) w_rcvr['week_fc_teams'] = nan_avg_array( [val['fc_teams'] for val in rcvr_query.values()]) w_rcvr['week_bc_teams'] = nan_avg_array( [val['bc_teams'] for val in rcvr_query.values()]) w_rcvr['week_perc_node_skips'] = calc_ratio( w_rcvr['week_node_skips'], daily.project.planned_receivers) return w_rcvr
def calc_proj_time_totals(self, daily): if daily: tb_query = TimeBreakdown.objects.filter( daily__production_date__lte=daily.production_date, daily__project=daily.project, ).order_by('daily__production_date') else: tb_query = None if not tb_query: pt = {f'proj_{key}': np.nan for key in time_breakdown_schema} pt['proj_rec_time'] = np.nan pt['proj_ops_time'] = np.nan pt['proj_standby'] = np.nan pt['proj_downtime'] = np.nan pt['proj_total_time'] = np.nan return pt, {} ts = { f'{key}_series': nan_array([val[key] for val in tb_query.values()]) for key in time_breakdown_schema } ts['ops_series'] = sum(ts[f'{key}_series'] for key in ops_time_keys) ts['standby_series'] = sum(ts[f'{key}_series'] for key in standby_keys) ts['downtime_series'] = sum(ts[f'{key}_series'] for key in downtime_keys) ts['total_time_series'] = (ts['ops_series'] + ts['standby_series'] + ts['downtime_series']) ts['date_series'] = np.array( [val.daily.production_date for val in tb_query]) pt = { f'proj_{key}': np.nansum(ts[f'{key}_series']) for key in time_breakdown_schema } pt['proj_rec_time'] = pt['proj_rec_hours'] pt['proj_ops_time'] = np.nansum( [pt[f'proj_{key}'] for key in ops_time_keys]) pt['proj_standby'] = np.nansum( [pt[f'proj_{key}'] for key in standby_keys]) pt['proj_downtime'] = np.nansum( [pt[f'proj_{key}'] for key in downtime_keys]) pt['proj_total_time'] = np.nansum([ pt['proj_ops_time'], pt['proj_standby'], pt['proj_downtime'], ]) return pt, ts
def calc_proj_prod_totals(self, daily, sourcetype): # filter for all days in the project up to and including the production date if daily: sp_query = SourceProduction.objects.filter( daily__production_date__lte=daily.production_date, sourcetype=sourcetype, ).order_by('daily__production_date') else: sp_query = None if not sp_query: pp = {f'proj_{key[:5]}': np.nan for key in source_prod_schema[0:6]} pp[f'proj_{source_prod_schema[6]}'] = np.nan pp['proj_total'] = np.nan return pp, {} p_series = { f'{key[:5]}_series': nan_array([val[key] for val in sp_query.values()]) for key in source_prod_schema[0:6] } p_series = self.calc_ctm_series(p_series, sourcetype) p_series[f'{source_prod_schema[6]}_series'] = np.array( [val.avg_sources for val in sp_query]) p_series['date_series'] = np.array( [val.daily.production_date for val in sp_query]) # only include sources and skips pp = { f'proj_{key[:5]}': np.nansum(p_series[f'{key[:5]}_series']) for key in source_prod_schema[0:6] } # get average of number of sources pp[f'proj_{source_prod_schema[6]}'] = nan_avg_array( p_series[f'{source_prod_schema[6]}_series']) # only include sources from terrain types pp['proj_total'] = np.sum(pp[f'proj_{key[:5]}'] for key in source_prod_schema[0:5]) return pp, p_series
def month_hse_totals(daily): if daily: hse_query = HseWeather.objects.filter( Q(daily__production_date__year=daily.production_date.year) & Q(daily__production_date__month=daily.production_date.month) & Q(daily__production_date__day__lte=daily.production_date.day), daily__project=daily.project, ) else: hse_query = None if not hse_query: return {f'month_{key}': '' for key in hse_weather_schema} m_hse = { f'month_{key}': sum(nan_array([val[key] for val in hse_query.values()])) for key in (*hse_weather_schema[:12], *hse_weather_schema[14:]) } return m_hse
def week_hse_totals(daily): if daily: end_date = daily.production_date start_date = end_date - timedelta(days=WEEKDAYS - 1) hse_query = HseWeather.objects.filter( Q(daily__production_date__gte=start_date), Q(daily__production_date__lte=end_date), daily__project=daily.project, ) else: return {f'week_{key}': '' for key in hse_weather_schema} if not hse_query: return {f'week_{key}': '' for key in hse_weather_schema} w_hse = { f'week_{key}': sum(nan_array([val[key] for val in hse_query.values()])) for key in (*hse_weather_schema[:12], *hse_weather_schema[14:]) } return w_hse
def project_receiver_total(daily, receivertype): if daily: rcvr_query = ReceiverProduction.objects.filter( daily__production_date__lte=daily.production_date, receivertype=receivertype, ).order_by('daily__production_date') else: rcvr_query = None if not rcvr_query: p_rcvr = {f'proj_{key}': 0 for key in receiver_prod_schema} return p_rcvr, {} rcvr_series = { f'{key}_series': [val[key] for val in rcvr_query.values()] for key in receiver_prod_schema } p_rcvr = { f'proj_{key}': sum(nan_array([val[key] for val in rcvr_query.values()])) for key in receiver_prod_schema[0:7] } p_rcvr['proj_qc_field'] = nan_avg_array( [val['qc_field'] for val in rcvr_query.values()]) p_rcvr['proj_qc_teams'] = nan_avg_array( [val['qc_teams'] for val in rcvr_query.values()]) p_rcvr['proj_fc_teams'] = nan_avg_array( [val['fc_teams'] for val in rcvr_query.values()]) p_rcvr['proj_bc_teams'] = nan_avg_array( [val['bc_teams'] for val in rcvr_query.values()]) p_rcvr['proj_perc_node_skips'] = calc_ratio( p_rcvr['proj_node_skips'], daily.project.planned_receivers) return p_rcvr, rcvr_series
def create_tab_production(self): ''' method to create excel weekly tab for production ''' set_column_widths(self.wsp, 'A', [ 0.94, 23.50, 12.33, 12.33, 12.33, 12.33, 12.33, 12.33, 12.33, 12.33, 12.33, ]) # set day production self.wsp.merge_cells('B1:K1') set_vertical_cells(self.wsp, 'B1', ['Daily production'], font_bold, Alignment(horizontal='center')) set_horizontal_cells( self.wsp, 'B2', self.days_prod['header'], font_bold, Alignment( horizontal='center', vertical='top', wrap_text=True, )) row, col = get_row_column('B3') weeks_total = np.zeros(len(self.days_prod[0]) - 2) for key in range(0, 7): vals = self.days_prod[key] loc = col + str(row + key) set_horizontal_cells(self.wsp, loc, vals, font_normal, Alignment(horizontal='right')) self.wsp[f'B{row + key}'].alignment = Alignment( horizontal='center') format_range = f'C{row + key}:C{row + key}' format_horizontal(self.wsp, format_range, int_hide_zero) format_range = f'D{row + key}:D{row + key}' format_horizontal(self.wsp, format_range, float_hide_zero) format_range = f'E{row + key}:L{row + key}' format_horizontal(self.wsp, format_range, int_hide_zero) format_range = f'M{row + key}:M{row + key}' format_horizontal(self.wsp, format_range, '0.000;-0;;@') # sum for indexes 1..10, skip index 0 date and 11 qc_field weeks_total += nan_array(vals[1:-1]).astype(np.float) # skip the 3rd and 6th elements vals = [*weeks_total[0:2], '', *weeks_total[3:]] set_vertical_cells(self.wsp, 'B10', ['Weeks total'], font_bold, Alignment(horizontal='center')) set_horizontal_cells(self.wsp, 'C10', vals, font_bold, Alignment(horizontal='right')) # average vp/ hr set_horizontal_cells(self.wsp, 'E10', [self.weeks_prod[5][3]], font_bold, Alignment(horizontal='right')) # average qc_field set_horizontal_cells(self.wsp, 'M10', [self.weeks_prod[5][11]], font_bold, Alignment(horizontal='right')) format_horizontal(self.wsp, 'C10:C10', '#,##0') format_horizontal(self.wsp, 'D10:D10', '0.00') format_horizontal(self.wsp, 'E10:K10', '#,##0') format_horizontal(self.wsp, 'M10:M10', '0.000') # set borders set_border(self.wsp, 'B2:M10') # set week production self.wsp.merge_cells('B13:K13') set_vertical_cells(self.wsp, 'B13', ['Weekly production'], font_bold, Alignment(horizontal='center')) set_horizontal_cells( self.wsp, 'B14', self.weeks_prod['header'], font_bold, Alignment( horizontal='center', vertical='top', wrap_text=True, )) row, col = get_row_column('B15') for key in range(0, 6): vals = self.weeks_prod[key] loc = col + str(row + key) set_horizontal_cells(self.wsp, loc, vals, font_normal, Alignment(horizontal='right')) self.wsp[f'B{row + key}'].alignment = Alignment( horizontal='center') format_range = f'C{row + key}:C{row + key}' format_horizontal(self.wsp, format_range, int_hide_zero) format_range = f'D{row + key}:D{row + key}' format_horizontal(self.wsp, format_range, float_hide_zero) format_range = f'E{row + key}:L{row + key}' format_horizontal(self.wsp, format_range, int_hide_zero) format_range = f'M{row + key}:M{row + key}' format_horizontal(self.wsp, format_range, '0.000;-0;;@') # set borders set_border(self.wsp, 'B14:M20') set_color(self.wsp, 'B20:M20', color=lightblue) # set terrain types for week self.wsp.merge_cells('C22:E22') set_vertical_cells(self.wsp, 'C22', ['Week terrain'], font_bold, Alignment(horizontal='center')) set_horizontal_cells(self.wsp, 'D23', ['VPs', 'Percentage'], font_bold, Alignment(horizontal='center')) set_vertical_cells(self.wsp, 'C24', [key for key in self.week_terrain], font_normal, Alignment(horizontal='left')) vals = [] percs = [] for val in self.week_terrain.values(): vals.append(val) if self.week_terrain['total'] > 0: perc = val / self.week_terrain['total'] else: perc = np.nan percs.append(perc) set_vertical_cells(self.wsp, 'D24', vals, font_normal, Alignment(horizontal='right')) set_vertical_cells(self.wsp, 'E24', percs, font_normal, Alignment(horizontal='right')) format_vertical(self.wsp, 'D24:D30', '#,##0') format_vertical(self.wsp, 'E24:E30', '0.00%') set_border(self.wsp, 'D23:E23') set_border(self.wsp, 'C24:E30') # set terrain types for project self.wsp.merge_cells('G22:I22') set_vertical_cells(self.wsp, 'G22', ['Project terrain'], font_bold, Alignment(horizontal='center')) set_horizontal_cells(self.wsp, 'H23', ['VPs', 'Percentage'], font_bold, Alignment(horizontal='center')) set_vertical_cells(self.wsp, 'G24', [key for key in self.proj_terrain], font_normal, Alignment(horizontal='left')) vals = [] percs = [] for val in self.proj_terrain.values(): vals.append(val) if self.proj_terrain['total'] > 0: perc = val / self.proj_terrain['total'] else: perc = np.nan percs.append(perc) set_vertical_cells(self.wsp, 'H24', vals, font_normal, Alignment(horizontal='right')) set_vertical_cells(self.wsp, 'I24', percs, font_normal, Alignment(horizontal='right')) format_vertical(self.wsp, 'H24:H30', '#,##0') format_vertical(self.wsp, 'I24:I30', '0.00%') set_border(self.wsp, 'H23:I23') set_border(self.wsp, 'G24:I30')
def create_tab_times(self): ''' method to create excel weekly tab for times ''' set_column_widths(self.wst, 'A', [ 0.94, 21.56, 9.50, 8.33, 8.33, 8.33, 8.33, 8.33, 10.11, 12.33, 9.89, 8.33, 8.33, 8.33, 8.80, 8.33, 10.00, 10.00, 8.50, 8.33, 8.33, 9.80, ]) # set day times self.wst.merge_cells('B1:V1') set_vertical_cells(self.wst, 'B1', ['Daily times'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('C2:H2') set_vertical_cells(self.wst, 'C2', ['Operational time'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('I2:L2') set_vertical_cells(self.wst, 'I2', ['Standby time'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('M2:S2') set_vertical_cells(self.wst, 'M2', ['Downtime'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('T2:V2') set_vertical_cells(self.wst, 'T2', ['Totals'], font_bold, Alignment(horizontal='center')) set_horizontal_cells( self.wst, 'B3', self.days_times['header'], font_bold, Alignment( horizontal='center', vertical='top', wrap_text=True, )) row, col = get_row_column('B4') weeks_total = np.zeros(len(self.days_times[0]) - 1) for key in range(0, 7): vals = self.days_times[key] loc = col + str(row + key) set_horizontal_cells(self.wst, loc, vals, font_normal, Alignment(horizontal='right')) self.wst[f'B{row + key}'].alignment = Alignment( horizontal='center') format_range = f'C{row + key}:V{row + key}' format_horizontal(self.wst, format_range, float_hide_zero) weeks_total += nan_array(vals[1:]).astype(np.float) set_vertical_cells(self.wst, 'B11', ['Weeks total'], font_bold, Alignment(horizontal='center')) set_horizontal_cells(self.wst, 'C11', weeks_total, font_bold, Alignment(horizontal='right')) format_horizontal(self.wst, 'C11:V11', '0.00') # set borders day times set_outer_border(self.wst, 'C2:H2') set_outer_border(self.wst, 'I2:L2') set_outer_border(self.wst, 'M2:S2') set_outer_border(self.wst, 'T2:V2') set_border(self.wst, 'B3:v11') # set week times self.wst.merge_cells('B13:V13') set_vertical_cells(self.wst, 'B13', ['Weekly times'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('C14:H14') set_vertical_cells(self.wst, 'C14', ['Operational time'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('I14:L14') set_vertical_cells(self.wst, 'I14', ['Standby time'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('M14:S14') set_vertical_cells(self.wst, 'M14', ['Downtime'], font_bold, Alignment(horizontal='center')) self.wst.merge_cells('T14:V14') set_vertical_cells(self.wst, 'T14', ['Totals'], font_bold, Alignment(horizontal='center')) set_horizontal_cells( self.wst, 'B15', self.weeks_times['header'], font_bold, Alignment( horizontal='center', vertical='top', wrap_text=True, )) row, col = get_row_column('B16') for key in range(0, 6): vals = self.weeks_times[key] loc = col + str(row + key) set_horizontal_cells(self.wst, loc, vals, font_normal, Alignment(horizontal='right')) self.wst[f'B{row + key}'].alignment = Alignment( horizontal='center') format_range = f'C{row + key}:V{row + key}' format_horizontal(self.wst, format_range, float_hide_zero) # set borders week times set_outer_border(self.wst, 'C14:H14') set_outer_border(self.wst, 'I14:L14') set_outer_border(self.wst, 'M14:S14') set_outer_border(self.wst, 'T14:V14') set_border(self.wst, 'B15:v21') set_color(self.wst, 'B21:V21', color=lightblue)
def create_weekly_graphs(self): date_series = self.proj_df['date'].to_list() app_series = self.proj_df['total_sp'].to_list() # line plot CTM and app plot_filename = self.media_dir / 'images/app_ctm.png' ctm_series = self.proj_df['ctm'].to_list() plt.plot(date_series, ctm_series, label="CTM", zorder=2) plt.plot(date_series, app_series, label="APP", zorder=3) plt.gca().xaxis.set_major_formatter(TICK_DATE_FORMAT) plt.gca().yaxis.grid(zorder=1) plt.tick_params(axis='both', labelsize=7) plt.xticks(rotation=70) plt.legend() plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # line plot of cumulative APP & CTM plot_filename = self.media_dir / 'images/cumul_app_ctm.png' app_cum_series = np.cumsum(app_series) * 0.001 ctm_cum_series = np.cumsum(nan_array(ctm_series)) * 0.001 plt.plot(date_series, ctm_cum_series, label="CTM", zorder=2) plt.plot(date_series, app_cum_series, label="APP", zorder=3) plt.gca().xaxis.set_major_formatter(TICK_DATE_FORMAT) plt.gca().yaxis.grid(zorder=1) plt.xticks(rotation=70) plt.tick_params(axis='both', labelsize=7) plt.legend() plt.gca().yaxis.set_major_formatter( mtick.StrMethodFormatter('{x:,.0f}k')) plt.gca().yaxis.set_major_locator( mtick.MultipleLocator(TICK_SPACING_CUMUL)) plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # pie chart of terrain distribution week - ignore last 2 (skips, avg sources) plot_filename = self.media_dir / 'images/pie_week_terrain.png' week_terrain = list( zip(*[(key, val) for key, val in self.week_terrain.items() if val > 0][:-2])) if week_terrain: terrain_labels, terrain_vals = week_terrain else: terrain_labels, terrain_vals = [], [] plt.title('Terrain - week') plt.pie(terrain_vals, labels=terrain_labels, autopct='%1.2f%%') plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # pie chart of terrain distribution project - ignore last 2 (skips, avg sources)s plot_filename = self.media_dir / 'images/pie_proj_terrain.png' proj_terrain = list( zip(*[(key, val) for key, val in self.proj_terrain.items() if val > 0][:-2])) if proj_terrain: terrain_labels, terrain_vals = proj_terrain else: terrain_labels, terrain_vals = [], [] plt.title('Terrain - project') plt.pie(terrain_vals, labels=terrain_labels, autopct='%1.2f%%') plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # pie chart of recording times plot_filename = self.media_dir / 'images/pie_week_times.png' # plot weekly times tl_ = ['recording', 'logistics', 'standby', 'downtime'] tv_ = [ self.weeks_times[5][1], self.weeks_times[5][18] - self.weeks_times[5][1], self.weeks_times[5][19], self.weeks_times[5][20], ] week_times = list( zip(*[(key, val) for key, val in zip(tl_, tv_) if val > 0])) if week_times: time_labels, time_vals = week_times else: time_labels, time_vals = [], [] plt.title('Weekly time breakdown') plt.pie(time_vals, labels=time_labels, autopct='%1.2f%%') plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # bar chart of weekly production plot_filename = self.media_dir / 'images/bar_week_production.png' date_series = [ val[0].replace(' ', '\n') for val in self.weeks_prod.values() if val[0] != 'Week' ] prod_series = nan_array([ val[1] / 1000 for val in self.weeks_prod.values() if not isinstance(val[1], str) ]) plt.bar(date_series, prod_series, zorder=2) for i, val in enumerate(prod_series): plt.annotate(f'{str(round(val))}k', xy=(date_series[i], prod_series[i]), ha='center', va='bottom') plt.grid(axis='y', zorder=1) plt.title('Weekly production') plt.tick_params(axis='both', labelsize=7) plt.gca().yaxis.set_major_formatter( mtick.StrMethodFormatter('{x:,.0f}k')) plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # bar chart of daily production plot_filename = self.media_dir / 'images/bar_day_production.png' date_series = [ val[0] for val in self.days_prod.values() if val[0] != 'Day' ] prod_series = nan_array([ val[1] for val in self.days_prod.values() if not isinstance(val[1], str) ]) plt.bar(date_series, prod_series, zorder=2) for i, val in enumerate(prod_series): plt.annotate(f'{val:,}', xy=(date_series[i], prod_series[i]), ha='center', va='bottom') plt.gca().yaxis.set_major_formatter( mtick.StrMethodFormatter('{x:,.0f}k')) plt.gca().yaxis.grid(zorder=1) plt.title('Daily production') plt.tick_params(axis='both', labelsize=7) plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # bar chart daily recording hours plot_filename = self.media_dir / 'images/bar_day_rechours.png' rec_series = nan_array([ val[2] for val in self.days_prod.values() if not isinstance(val[2], str) ]) plt.bar(date_series, rec_series, zorder=2) for i, val in enumerate(rec_series): plt.annotate(f'{val:.2f}', xy=(date_series[i], rec_series[i]), ha='center', va='bottom') ax = plt.gca() if all(v > RECHRS_LIMITS[0] * 1.1 for v in rec_series): ax.set_ylim(RECHRS_LIMITS[0], RECHRS_LIMITS[1]) else: ax.set_ylim(0, RECHRS_LIMITS[1]) ax.yaxis.set_major_formatter(mtick.StrMethodFormatter('{x:,.0f}')) ax.yaxis.grid(zorder=1) plt.title('Daily recording hours') plt.tick_params(axis='both', labelsize=7) plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close() # bar chart daily VPs per hour plot_filename = self.media_dir / 'images/bar_day_vphr.png' vphr_series = nan_array([ val[3] for val in self.days_prod.values() if not isinstance(val[3], str) ]) plt.bar(date_series, vphr_series, zorder=2) for i, val in enumerate(vphr_series): plt.annotate(f'{val:.0f}', xy=(date_series[i], vphr_series[i]), ha='center', va='bottom') ax = plt.gca() if all(v > VPHR_LIMITS[0] * 1.1 for v in vphr_series): ax.set_ylim(VPHR_LIMITS[0], VPHR_LIMITS[1]) else: ax.set_ylim(0, VPHR_LIMITS[1]) ax.yaxis.set_major_formatter(mtick.StrMethodFormatter('{x:,.0f}')) ax.yaxis.grid(zorder=1) plt.title('Daily VP per hour') plt.tick_params(axis='both', labelsize=7) plt.tight_layout() plt.savefig(plot_filename, format='png') plt.close()