Bug 3098 - mettre à jour les graphiques montrant l'évolution du cluster

- improved the handling of colors. As a result, the number of owners is no longer restricted, as the color palette is now no longer restricted in size
- improved readability by putting the legend on the upper left part of the graphs, where it no longer hides the upper right part of the graph
- fixed clutter of years on the x axis which made it difficult to read the years. Now, there is a limit in the number of years displayed on the x axis
- improved the legend showng the owners, which now displays the lab in addition to the department
This commit is contained in:
Guillaume Raffy 2021-02-23 15:40:01 +00:00
parent 14e3e12571
commit faf6cd5d2a
1 changed files with 27 additions and 9 deletions

View File

@ -4,6 +4,7 @@ import os
import re import re
import datetime import datetime
import numpy as np import numpy as np
import colorsys
# fix to prevent the following error when run from www-data # fix to prevent the following error when run from www-data
# Failed to create /var/www/.matplotlib; consider setting MPLCONFIGDIR to a writable directory for matplotlib configuration data # Failed to create /var/www/.matplotlib; consider setting MPLCONFIGDIR to a writable directory for matplotlib configuration data
# root@intranet:~# echo ~www-data # root@intranet:~# echo ~www-data
@ -116,18 +117,26 @@ def get_computer_value_over_time(inventory, computer_id, time_value, flops_price
# plt.legend() # plt.legend()
def stackplot(ax, x_signal, y_signals): def get_rgb_palette(num_colors, saturation=0.5, value=0.5):
hsv_tuples = [(x * 1.0 / num_colors, saturation, value) for x in range(num_colors)]
rgb_tuples = map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)
return rgb_tuples
def stackplot(ax, x_signal, y_signals, legend_location='best'):
""" """
:param matplotlib.Axes ax: :param matplotlib.Axes ax:
:param numpy.array x_signal: :param numpy.array x_signal:
:param dict(str,numpy.array) y_signals: :param dict(str,numpy.array) y_signals:
:param str legend_location: one of the values allowed in loc argument of matplotlib's plt.legend() function, or:
'outside right': outside the graph, at its right
""" """
if 'stackplot' in dir(ax): if 'stackplot' in dir(ax):
ax.stackplot(x_signal, list(y_signals.values())) ax.stackplot(x_signal, list(y_signals.values()))
plt.legend(list(y_signals.keys())) plt.legend(list(y_signals.keys()))
else: else:
# emulating missing Axes.stackplot method # emulating missing Axes.stackplot method
colors = ['blue', 'orange', 'green', 'purple', 'yellow'] colors = get_rgb_palette(num_colors=len(y_signals), saturation=1.0, value=0.8) # ['blue', 'orange', 'green', 'purple', 'yellow', 'cyan']
y = np.row_stack(list(y_signals.itervalues())) y = np.row_stack(list(y_signals.itervalues()))
# this call to 'cumsum' (cumulative sum), passing in your y data, # this call to 'cumsum' (cumulative sum), passing in your y data,
# is necessary to avoid having to manually order the datasets # is necessary to avoid having to manually order the datasets
@ -140,7 +149,11 @@ def stackplot(ax, x_signal, y_signals):
ax.fill_between(x_signal, from_signal, y_stack[series_index, :], color=colors[series_index], lw=0.0) ax.fill_between(x_signal, from_signal, y_stack[series_index, :], color=colors[series_index], lw=0.0)
p = plt.Rectangle((0, 0), 0, 0, color=colors[series_index]) p = plt.Rectangle((0, 0), 0, 0, color=colors[series_index])
ax.add_patch(p) ax.add_patch(p)
plt.legend(list(y_signals.keys()))
if legend_location == 'outside right':
plt.legend(list(y_signals.keys()), bbox_to_anchor=(1.10, 1.00), loc='upper left') # force the legend into the bounding box
else:
plt.legend(list(y_signals.keys()), loc=legend_location)
def draw_cluster_value_over_time_graph(inventory, from_date, to_date, graph_type): def draw_cluster_value_over_time_graph(inventory, from_date, to_date, graph_type):
@ -166,7 +179,7 @@ def draw_cluster_value_over_time_graph(inventory, from_date, to_date, graph_type
# print(ownership) # print(ownership)
# print(ownership['owner'], ownership['owner_ratio']) # print(ownership['owner'], ownership['owner_ratio'])
owner = ownership['owner'] owner = ownership['owner']
owner_dept = owner.split('.')[1] owner_dept = '.'.join(owner.split('.')[0:2])
# if owner_dept == 'matnano': # if owner_dept == 'matnano':
# print(name, owner, purchase_date, price_ex_vat) # print(name, owner, purchase_date, price_ex_vat)
if owner_dept in cluster_value.keys(): if owner_dept in cluster_value.keys():
@ -185,7 +198,7 @@ def draw_cluster_value_over_time_graph(inventory, from_date, to_date, graph_type
# for dept, cluster_value_for_dept in cluster_value.iteritems(): # for dept, cluster_value_for_dept in cluster_value.iteritems():
# ax.plot(time_value, cluster_value_for_dept) # ax.plot(time_value, cluster_value_for_dept)
stackplot(ax, time_value, cluster_value) stackplot(ax, time_value, cluster_value, legend_location='upper left')
plt.xlabel('time') plt.xlabel('time')
plt.ylabel({ plt.ylabel({
@ -193,7 +206,15 @@ def draw_cluster_value_over_time_graph(inventory, from_date, to_date, graph_type
'cluster_value_over_time': u'cluster value (€)', 'cluster_value_over_time': u'cluster value (€)',
'cluster_dp_gflops_over_time': u'double prec gflops'}[graph_type]) 'cluster_dp_gflops_over_time': u'double prec gflops'}[graph_type])
years = matplotlib.dates.YearLocator() # every year datemin = datetime.date(from_date.year, 1, 1)
datemax = datetime.date(to_date.year + 1, 1, 1)
ax.set_xlim(datemin, datemax)
max_num_years = 8
num_years = (datemax - datemin).days // 365
year_step = num_years / max_num_years
years = matplotlib.dates.YearLocator(year_step) # every year_step year
months = matplotlib.dates.MonthLocator() # every month months = matplotlib.dates.MonthLocator() # every month
yearsFmt = matplotlib.dates.DateFormatter('%Y') yearsFmt = matplotlib.dates.DateFormatter('%Y')
@ -202,9 +223,6 @@ def draw_cluster_value_over_time_graph(inventory, from_date, to_date, graph_type
ax.xaxis.set_major_formatter(yearsFmt) ax.xaxis.set_major_formatter(yearsFmt)
ax.xaxis.set_minor_locator(months) ax.xaxis.set_minor_locator(months)
datemin = datetime.date(from_date.year, 1, 1)
datemax = datetime.date(to_date.year + 1, 1, 1)
ax.set_xlim(datemin, datemax)
# rotates and right aligns the x labels, and moves the bottom of the # rotates and right aligns the x labels, and moves the bottom of the
# axes up to make room for them # axes up to make room for them