mirror of
https://github.com/Telecominfraproject/wlan-lanforge-scripts.git
synced 2025-11-02 03:37:55 +00:00
UPDATE report & graph libraries for standalone test-report generation
Signed-off-by: anil-tegala <anil.tegala@candelatech.com>
This commit is contained in:
@@ -24,10 +24,26 @@ import matplotlib.pyplot as plt
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pdfkit
|
import pdfkit
|
||||||
from matplotlib.colors import ListedColormap
|
from matplotlib.colors import ListedColormap
|
||||||
|
import matplotlib.ticker as mticker
|
||||||
import argparse
|
import argparse
|
||||||
|
import traceback
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
# TODO have scipy be part of the base install
|
||||||
|
try:
|
||||||
|
from scipy import interpolate
|
||||||
|
|
||||||
|
except Exception as x:
|
||||||
|
print("Info: scipy package not installed, Needed for smoothing linear plots 'pip install scipy' ")
|
||||||
|
traceback.print_exception(Exception, x, x.__traceback__, chain=True)
|
||||||
|
|
||||||
|
|
||||||
sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../")))
|
sys.path.append(os.path.join(os.path.abspath(__file__ + "../../../")))
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
lf_logger_config = importlib.import_module("py-scripts.lf_logger_config")
|
||||||
|
|
||||||
lf_csv = importlib.import_module("py-scripts.lf_csv")
|
lf_csv = importlib.import_module("py-scripts.lf_csv")
|
||||||
lf_csv = lf_csv.lf_csv
|
lf_csv = lf_csv.lf_csv
|
||||||
|
|
||||||
@@ -57,6 +73,7 @@ class lf_bar_graph:
|
|||||||
_xaxis_step=1,
|
_xaxis_step=1,
|
||||||
_xticks_font=None,
|
_xticks_font=None,
|
||||||
_xaxis_value_location=0,
|
_xaxis_value_location=0,
|
||||||
|
_xticks_rotation=None,
|
||||||
_text_font=None,
|
_text_font=None,
|
||||||
_text_rotation=None,
|
_text_rotation=None,
|
||||||
_grp_title="",
|
_grp_title="",
|
||||||
@@ -66,7 +83,10 @@ class lf_bar_graph:
|
|||||||
_legend_ncol=1,
|
_legend_ncol=1,
|
||||||
_legend_fontsize=None,
|
_legend_fontsize=None,
|
||||||
_dpi=96,
|
_dpi=96,
|
||||||
_enable_csv=False):
|
_enable_csv=False,
|
||||||
|
_remove_border=None,
|
||||||
|
_alignment=None
|
||||||
|
):
|
||||||
|
|
||||||
if _data_set is None:
|
if _data_set is None:
|
||||||
_data_set = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]]
|
_data_set = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]]
|
||||||
@@ -107,6 +127,9 @@ class lf_bar_graph:
|
|||||||
self.legend_box = _legend_box
|
self.legend_box = _legend_box
|
||||||
self.legend_ncol = _legend_ncol
|
self.legend_ncol = _legend_ncol
|
||||||
self.legend_fontsize = _legend_fontsize
|
self.legend_fontsize = _legend_fontsize
|
||||||
|
self.remove_border = _remove_border
|
||||||
|
self.alignment = _alignment
|
||||||
|
self.xticks_rotation = _xticks_rotation
|
||||||
|
|
||||||
def build_bar_graph(self):
|
def build_bar_graph(self):
|
||||||
if self.color is None:
|
if self.color is None:
|
||||||
@@ -116,8 +139,17 @@ class lf_bar_graph:
|
|||||||
self.color.append(self.color_name[i])
|
self.color.append(self.color_name[i])
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
||||||
plt.subplots(figsize=self.figsize)
|
fig_size, ax = plt.subplots(figsize=self.figsize, gridspec_kw=self.alignment)
|
||||||
i = 0
|
i = 0
|
||||||
|
# to remove the borders
|
||||||
|
if self.remove_border is not None:
|
||||||
|
for border in self.remove_border:
|
||||||
|
ax.spines[border].set_color(None)
|
||||||
|
if 'left' in self.remove_border: # to remove the y-axis labeling
|
||||||
|
yaxis_visable =False
|
||||||
|
else:
|
||||||
|
yaxis_visable=True
|
||||||
|
ax.yaxis.set_visible(yaxis_visable)
|
||||||
|
|
||||||
def show_value(rectangles):
|
def show_value(rectangles):
|
||||||
for rect in rectangles:
|
for rect in rectangles:
|
||||||
@@ -148,10 +180,10 @@ class lf_bar_graph:
|
|||||||
plt.xticks(np.arange(0,
|
plt.xticks(np.arange(0,
|
||||||
len(self.xaxis_categories),
|
len(self.xaxis_categories),
|
||||||
step=self.xaxis_step),
|
step=self.xaxis_step),
|
||||||
fontsize=self.xticks_font)
|
fontsize=self.xticks_font,rotation=self.xticks_rotation)
|
||||||
else:
|
else:
|
||||||
plt.xticks([i + self._xaxis_value_location for i in np.arange(0, len(self.data_set[0]), step=self.xaxis_step)],
|
plt.xticks([i + self._xaxis_value_location for i in np.arange(0, len(self.data_set[0]), step=self.xaxis_step)],
|
||||||
self.xaxis_categories, fontsize=self.xticks_font)
|
self.xaxis_categories, fontsize=self.xticks_font,rotation=self.xticks_rotation)
|
||||||
plt.legend(
|
plt.legend(
|
||||||
handles=self.legend_handles,
|
handles=self.legend_handles,
|
||||||
loc=self.legend_loc,
|
loc=self.legend_loc,
|
||||||
@@ -163,7 +195,7 @@ class lf_bar_graph:
|
|||||||
plt.gcf()
|
plt.gcf()
|
||||||
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
||||||
plt.close()
|
plt.close()
|
||||||
print("{}.png".format(self.graph_image_name))
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
if self.enable_csv:
|
if self.enable_csv:
|
||||||
if self.data_set is not None and self.xaxis_categories is not None:
|
if self.data_set is not None and self.xaxis_categories is not None:
|
||||||
if len(self.xaxis_categories) == len(self.data_set[0]):
|
if len(self.xaxis_categories) == len(self.data_set[0]):
|
||||||
@@ -179,11 +211,181 @@ class lf_bar_graph:
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Length and x-axis values and y-axis values should be same.")
|
"Length and x-axis values and y-axis values should be same.")
|
||||||
else:
|
else:
|
||||||
print("No Dataset Found")
|
logger.debug("No Dataset Found")
|
||||||
print("{}.csv".format(self.graph_image_name))
|
logger.debug("{}.csv".format(self.graph_image_name))
|
||||||
return "%s.png" % self.graph_image_name
|
return "%s.png" % self.graph_image_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class lf_bar_graph_horizontal:
|
||||||
|
def __init__(self, _data_set=None,
|
||||||
|
_xaxis_name="x-axis",
|
||||||
|
_yaxis_name="y-axis",
|
||||||
|
_yaxis_categories=None,
|
||||||
|
_yaxis_label=None,
|
||||||
|
_graph_title="",
|
||||||
|
_title_size=16,
|
||||||
|
_graph_image_name="image_name",
|
||||||
|
_label=None,
|
||||||
|
_color=None,
|
||||||
|
_bar_height=0.25,
|
||||||
|
_color_edge='grey',
|
||||||
|
_font_weight='bold',
|
||||||
|
_color_name=None,
|
||||||
|
_figsize=(10, 5),
|
||||||
|
_show_bar_value=False,
|
||||||
|
_yaxis_step=1,
|
||||||
|
_yticks_font=None,
|
||||||
|
_yaxis_value_location=0,
|
||||||
|
_yticks_rotation=None,
|
||||||
|
_text_font=None,
|
||||||
|
_text_rotation=None,
|
||||||
|
_grp_title="",
|
||||||
|
_legend_handles=None,
|
||||||
|
_legend_loc="best",
|
||||||
|
_legend_box=None,
|
||||||
|
_legend_ncol=1,
|
||||||
|
_legend_fontsize=None,
|
||||||
|
_dpi=96,
|
||||||
|
_enable_csv=False,
|
||||||
|
_remove_border=None,
|
||||||
|
_alignment=None
|
||||||
|
):
|
||||||
|
|
||||||
|
if _data_set is None:
|
||||||
|
_data_set = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]]
|
||||||
|
if _yaxis_categories is None:
|
||||||
|
_yaxis_categories = [1, 2, 3, 4]
|
||||||
|
if _yaxis_label is None:
|
||||||
|
_yaxis_label = ["a", "b", "c", "d"]
|
||||||
|
if _label is None:
|
||||||
|
_label = ["bi-downlink", "bi-uplink", 'uplink']
|
||||||
|
if _color_name is None:
|
||||||
|
_color_name = ['lightcoral', 'darkgrey', 'r', 'g', 'b', 'y']
|
||||||
|
self.data_set = _data_set
|
||||||
|
self.xaxis_name = _xaxis_name
|
||||||
|
self.yaxis_name = _yaxis_name
|
||||||
|
self.yaxis_categories = _yaxis_categories
|
||||||
|
self.yaxis_label = _yaxis_label
|
||||||
|
self.title = _graph_title
|
||||||
|
self.title_size = _title_size
|
||||||
|
self.graph_image_name = _graph_image_name
|
||||||
|
self.label = _label
|
||||||
|
self.color = _color
|
||||||
|
self.bar_height = _bar_height
|
||||||
|
self.color_edge = _color_edge
|
||||||
|
self.font_weight = _font_weight
|
||||||
|
self.color_name = _color_name
|
||||||
|
self.figsize = _figsize
|
||||||
|
self.show_bar_value = _show_bar_value
|
||||||
|
self.yaxis_step = _yaxis_step
|
||||||
|
self.yticks_font = _yticks_font
|
||||||
|
self._yaxis_value_location = _yaxis_value_location
|
||||||
|
self.text_font = _text_font
|
||||||
|
self.text_rotation = _text_rotation
|
||||||
|
self.grp_title = _grp_title
|
||||||
|
self.enable_csv = _enable_csv
|
||||||
|
self.lf_csv = lf_csv()
|
||||||
|
self.legend_handles = _legend_handles
|
||||||
|
self.legend_loc = _legend_loc
|
||||||
|
self.legend_box = _legend_box
|
||||||
|
self.legend_ncol = _legend_ncol
|
||||||
|
self.legend_fontsize = _legend_fontsize
|
||||||
|
self.remove_border = _remove_border
|
||||||
|
self.alignment = _alignment
|
||||||
|
self.yticks_rotation = _yticks_rotation
|
||||||
|
|
||||||
|
def build_bar_graph_horizontal(self):
|
||||||
|
if self.color is None:
|
||||||
|
i = 0
|
||||||
|
self.color = []
|
||||||
|
for _ in self.data_set:
|
||||||
|
self.color.append(self.color_name[i])
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
fig_size, ax = plt.subplots(figsize=self.figsize, gridspec_kw=self.alignment)
|
||||||
|
i = 0
|
||||||
|
# to remove the borders
|
||||||
|
if self.remove_border is not None:
|
||||||
|
for border in self.remove_border:
|
||||||
|
ax.spines[border].set_color(None)
|
||||||
|
if 'left' in self.remove_border: # to remove the y-axis labeling
|
||||||
|
yaxis_visable =False
|
||||||
|
else:
|
||||||
|
yaxis_visable=True
|
||||||
|
ax.yaxis.set_visible(yaxis_visable)
|
||||||
|
|
||||||
|
def show_value(rectangles):
|
||||||
|
for rect in rectangles:
|
||||||
|
w = rect.get_width()
|
||||||
|
y = rect.get_y()
|
||||||
|
h = rect.get_height()
|
||||||
|
x = rect.get_x()
|
||||||
|
# adding 1 may not always work based on the x axis scale may need to be configurable
|
||||||
|
plt.text(w + 1 , rect.get_y() + rect.get_height() / 4., w,
|
||||||
|
ha='center', va='bottom', rotation=self.text_rotation, fontsize=self.text_font)
|
||||||
|
|
||||||
|
for _ in self.data_set:
|
||||||
|
if i > 0:
|
||||||
|
br = br1
|
||||||
|
br2 = [y + self.bar_height for y in br]
|
||||||
|
rects = plt.barh(br2, self.data_set[i], color=self.color[i], height=self.bar_height,
|
||||||
|
edgecolor=self.color_edge, label=self.label[i])
|
||||||
|
if self.show_bar_value:
|
||||||
|
show_value(rects)
|
||||||
|
br1 = br2
|
||||||
|
i = i + 1
|
||||||
|
else:
|
||||||
|
br1 = np.arange(len(self.data_set[i]))
|
||||||
|
rects = plt.barh(br1, self.data_set[i], color=self.color[i], height=self.bar_height,
|
||||||
|
edgecolor=self.color_edge, label=self.label[i])
|
||||||
|
if self.show_bar_value:
|
||||||
|
show_value(rects)
|
||||||
|
i = i + 1
|
||||||
|
plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15)
|
||||||
|
plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15)
|
||||||
|
if self.yaxis_categories[0] == 0:
|
||||||
|
plt.yticks(np.arange(0,
|
||||||
|
len(self.yaxis_categories),
|
||||||
|
step=self.yaxis_step),
|
||||||
|
fontsize=self.yticks_font,rotation=self.yticks_rotation)
|
||||||
|
else:
|
||||||
|
plt.yticks([i + self._yaxis_value_location for i in np.arange(0, len(self.data_set[0]), step=self.yaxis_step)],
|
||||||
|
self.yaxis_categories, fontsize=self.yticks_font,rotation=self.yticks_rotation)
|
||||||
|
plt.legend(
|
||||||
|
handles=self.legend_handles,
|
||||||
|
loc=self.legend_loc,
|
||||||
|
bbox_to_anchor=self.legend_box,
|
||||||
|
ncol=self.legend_ncol,
|
||||||
|
fontsize=self.legend_fontsize)
|
||||||
|
plt.suptitle(self.title, fontsize=self.title_size)
|
||||||
|
plt.title(self.grp_title)
|
||||||
|
plt.gcf()
|
||||||
|
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
||||||
|
plt.close()
|
||||||
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
|
if self.enable_csv:
|
||||||
|
if self.data_set is not None and self.yaxis_categories is not None:
|
||||||
|
if len(self.yaxis_categories) == len(self.data_set[0]):
|
||||||
|
self.lf_csv.columns = []
|
||||||
|
self.lf_csv.rows = []
|
||||||
|
self.lf_csv.columns.append(self.yaxis_name)
|
||||||
|
self.lf_csv.columns.extend(self.label)
|
||||||
|
self.lf_csv.rows.append(self.yaxis_categories)
|
||||||
|
self.lf_csv.rows.extend(self.data_set)
|
||||||
|
self.lf_csv.filename = f"{self.graph_image_name}.csv"
|
||||||
|
self.lf_csv.generate_csv()
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
"Length and x-axis values and y-axis values should be same.")
|
||||||
|
else:
|
||||||
|
logger.debug("No Dataset Found")
|
||||||
|
logger.debug("{}.csv".format(self.graph_image_name))
|
||||||
|
return "%s.png" % self.graph_image_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class lf_scatter_graph:
|
class lf_scatter_graph:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
_x_data_set=None,
|
_x_data_set=None,
|
||||||
@@ -254,7 +456,7 @@ class lf_scatter_graph:
|
|||||||
plt.legend(handles=scatter.legend_elements()[0], labels=self.label)
|
plt.legend(handles=scatter.legend_elements()[0], labels=self.label)
|
||||||
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
||||||
plt.close()
|
plt.close()
|
||||||
print("{}.png".format(self.graph_image_name))
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
if self.enable_csv:
|
if self.enable_csv:
|
||||||
self.lf_csv.columns = self.label
|
self.lf_csv.columns = self.label
|
||||||
self.lf_csv.rows = self.y_data_set
|
self.lf_csv.rows = self.y_data_set
|
||||||
@@ -263,8 +465,267 @@ class lf_scatter_graph:
|
|||||||
|
|
||||||
return "%s.png" % self.graph_image_name
|
return "%s.png" % self.graph_image_name
|
||||||
|
|
||||||
|
# have a second yaxis with line graph
|
||||||
|
class lf_bar_line_graph:
|
||||||
|
def __init__(self,
|
||||||
|
_data_set1=None,
|
||||||
|
# Note data_set2, data_set2_poly and data_set2_spline needs same size list
|
||||||
|
_data_set2=None,
|
||||||
|
_data_set2_poly=[False], # Values are True or False
|
||||||
|
_data_set2_poly_degree=[3],
|
||||||
|
_data_set2_interp1d=[False], # Values are True or False
|
||||||
|
_xaxis_name="x-axis",
|
||||||
|
_y1axis_name="y1-axis",
|
||||||
|
_y2axis_name="y2-axis",
|
||||||
|
_xaxis_categories=None,
|
||||||
|
_xaxis_label=None,
|
||||||
|
_graph_title="",
|
||||||
|
_title_size=16,
|
||||||
|
_graph_image_name="image_name",
|
||||||
|
_label1=None,
|
||||||
|
_label2=None,
|
||||||
|
_label2_poly=None,
|
||||||
|
_label2_interp1d=None,
|
||||||
|
_color1=None,
|
||||||
|
_color2=None,
|
||||||
|
_color2_poly=None,
|
||||||
|
_color2_interp1d=None,
|
||||||
|
_bar_width=0.25,
|
||||||
|
_color_edge='grey',
|
||||||
|
_font_weight='bold',
|
||||||
|
_color_name1=None,
|
||||||
|
_color_name2=None,
|
||||||
|
_marker=None,
|
||||||
|
_figsize=(10, 5),
|
||||||
|
_show_bar_value=False,
|
||||||
|
_xaxis_step=1,
|
||||||
|
_xticks_font=None,
|
||||||
|
_xaxis_value_location=0,
|
||||||
|
_text_font=None,
|
||||||
|
_text_rotation=None,
|
||||||
|
_grp_title="",
|
||||||
|
_legend_handles=None,
|
||||||
|
_legend_loc1="best",
|
||||||
|
_legend_loc2="best",
|
||||||
|
_legend_box1=None,
|
||||||
|
_legend_box2=None,
|
||||||
|
_legend_ncol=1,
|
||||||
|
_legend_fontsize=None,
|
||||||
|
_dpi=96,
|
||||||
|
_enable_csv=False):
|
||||||
|
|
||||||
|
if _data_set1 is None:
|
||||||
|
_data_set1 = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]]
|
||||||
|
if _xaxis_categories is None:
|
||||||
|
_xaxis_categories = [1, 2, 3, 4]
|
||||||
|
if _xaxis_label is None:
|
||||||
|
_xaxis_label = ["a", "b", "c", "d"]
|
||||||
|
if _label1 is None:
|
||||||
|
_label1 = ["bi-downlink", "bi-uplink", 'uplink']
|
||||||
|
if _label2 is None:
|
||||||
|
_label2 = ["bi-downlink", "bi-uplink", 'uplink']
|
||||||
|
|
||||||
|
if _color_name1 is None:
|
||||||
|
_color_name1 = ['lightcoral', 'darkgrey', 'r', 'g', 'b', 'y']
|
||||||
|
if _color_name2 is None:
|
||||||
|
_color_name2 = ['lightcoral', 'darkgrey', 'r', 'g', 'b', 'y']
|
||||||
|
self.data_set1 = _data_set1
|
||||||
|
self.data_set2 = _data_set2
|
||||||
|
self.data_set2_poly = _data_set2_poly
|
||||||
|
self.data_set2_poly_degree = _data_set2_poly_degree
|
||||||
|
self.data_set2_interp1d = _data_set2_interp1d
|
||||||
|
self.xaxis_name = _xaxis_name
|
||||||
|
self.y1axis_name = _y1axis_name
|
||||||
|
self.y2axis_name = _y2axis_name
|
||||||
|
self.xaxis_categories = _xaxis_categories
|
||||||
|
self.xaxis_label = _xaxis_label
|
||||||
|
self.title = _graph_title
|
||||||
|
self.title_size = _title_size
|
||||||
|
self.graph_image_name = _graph_image_name
|
||||||
|
self.label1 = _label1
|
||||||
|
self.label2 = _label2
|
||||||
|
self.label2_poly = _label2_poly
|
||||||
|
self.label2_interp1d = _label2_interp1d
|
||||||
|
self.color1 = _color1
|
||||||
|
self.color2 = _color2
|
||||||
|
self.color2_poly = _color2_poly
|
||||||
|
self.color2_interp1d = _color2_interp1d
|
||||||
|
self.marker = _marker
|
||||||
|
self.bar_width = _bar_width
|
||||||
|
self.color_edge = _color_edge
|
||||||
|
self.font_weight = _font_weight
|
||||||
|
self.color_name1 = _color_name1
|
||||||
|
self.color_name2 = _color_name2
|
||||||
|
self.figsize = _figsize
|
||||||
|
self.show_bar_value = _show_bar_value
|
||||||
|
self.xaxis_step = _xaxis_step
|
||||||
|
self.xticks_font = _xticks_font
|
||||||
|
self._xaxis_value_location = _xaxis_value_location
|
||||||
|
self.text_font = _text_font
|
||||||
|
self.text_rotation = _text_rotation
|
||||||
|
self.grp_title = _grp_title
|
||||||
|
self.enable_csv = _enable_csv
|
||||||
|
self.lf_csv = lf_csv()
|
||||||
|
self.legend_handles = _legend_handles
|
||||||
|
self.legend_loc1 = _legend_loc1
|
||||||
|
self.legend_loc2 = _legend_loc2
|
||||||
|
self.legend_box1 = _legend_box1
|
||||||
|
self.legend_box2 = _legend_box2
|
||||||
|
self.legend_ncol = _legend_ncol
|
||||||
|
self.legend_fontsize = _legend_fontsize
|
||||||
|
|
||||||
|
def build_bar_line_graph(self):
|
||||||
|
if self.color1 is None:
|
||||||
|
i = 0
|
||||||
|
self.color1 = []
|
||||||
|
for _ in self.data_set1:
|
||||||
|
self.color1.append(self.color_name[i])
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
fig, ax1 = plt.subplots(figsize=self.figsize)
|
||||||
|
|
||||||
|
ax2 = ax1.twinx()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
def show_value(rectangles):
|
||||||
|
for rect in rectangles:
|
||||||
|
h = rect.get_height()
|
||||||
|
ax1.text(rect.get_x() + rect.get_width() / 2., h, h,
|
||||||
|
ha='center', va='bottom', rotation=self.text_rotation, fontsize=self.text_font)
|
||||||
|
|
||||||
|
for _ in self.data_set1:
|
||||||
|
if i > 0:
|
||||||
|
br = br1
|
||||||
|
br2 = [x + self.bar_width for x in br]
|
||||||
|
rects = ax1.bar(br2, self.data_set1[i], color=self.color1[i], width=self.bar_width,
|
||||||
|
edgecolor=self.color_edge, label=self.label1[i])
|
||||||
|
if self.show_bar_value:
|
||||||
|
show_value(rects)
|
||||||
|
br1 = br2
|
||||||
|
i = i + 1
|
||||||
|
else:
|
||||||
|
br1 = np.arange(len(self.data_set1[i]))
|
||||||
|
rects = ax1.bar(br1, self.data_set1[i], color=self.color1[i], width=self.bar_width,
|
||||||
|
edgecolor=self.color_edge, label=self.label1[i])
|
||||||
|
if self.show_bar_value:
|
||||||
|
show_value(rects)
|
||||||
|
i = i + 1
|
||||||
|
ax1.set_xlabel(self.xaxis_name, fontweight='bold', fontsize=15)
|
||||||
|
ax1.set_ylabel(self.y1axis_name, fontweight='bold', fontsize=15)
|
||||||
|
if self.xaxis_categories[0] == 0:
|
||||||
|
xsteps = plt.xticks(np.arange(0,
|
||||||
|
len(self.xaxis_categories),
|
||||||
|
step=self.xaxis_step),
|
||||||
|
fontsize=self.xticks_font)
|
||||||
|
else:
|
||||||
|
xsteps = plt.xticks([i + self._xaxis_value_location for i in np.arange(0, len(self.data_set1[0]), step=self.xaxis_step)],
|
||||||
|
self.xaxis_categories, fontsize=self.xticks_font)
|
||||||
|
ax1.legend(
|
||||||
|
handles=self.legend_handles,
|
||||||
|
loc=self.legend_loc1,
|
||||||
|
bbox_to_anchor=self.legend_box1,
|
||||||
|
ncol=self.legend_ncol,
|
||||||
|
fontsize=self.legend_fontsize)
|
||||||
|
|
||||||
|
|
||||||
|
# overlay line graph
|
||||||
|
def show_value2(data):
|
||||||
|
for item, value in enumerate(data):
|
||||||
|
ax2.text(item, value, "{value}".format(value=value), ha='center',rotation=self.text_rotation, fontsize=self.text_font)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for _ in self.data_set2:
|
||||||
|
br1 = np.arange(len(self.data_set2[i]))
|
||||||
|
ax2.plot(
|
||||||
|
br1,
|
||||||
|
self.data_set2[i],
|
||||||
|
color=self.color2[i],
|
||||||
|
label=self.label2[i],
|
||||||
|
marker=self.marker[i])
|
||||||
|
show_value2(self.data_set2[i])
|
||||||
|
# do polynomial smoothing
|
||||||
|
if self.data_set2_poly[i]:
|
||||||
|
poly = np.polyfit(br1,self.data_set2[i],self.data_set2_poly_degree[i])
|
||||||
|
poly_y = np.poly1d(poly)(br1)
|
||||||
|
ax2.plot(
|
||||||
|
br1,
|
||||||
|
poly_y,
|
||||||
|
color=self.color2_poly[i],
|
||||||
|
label=self.label2_poly[i]
|
||||||
|
)
|
||||||
|
if self.data_set2_interp1d[i]:
|
||||||
|
cubic_interpolation_model = interpolate.interp1d(br1, self.data_set2[i],kind="cubic")
|
||||||
|
|
||||||
|
x_sm = np.array(br1)
|
||||||
|
x_smooth = np.linspace(x_sm.min(), x_sm.max(), 500)
|
||||||
|
y_smooth = cubic_interpolation_model(x_smooth)
|
||||||
|
ax2.plot(
|
||||||
|
x_smooth,
|
||||||
|
y_smooth,
|
||||||
|
color=self.color2_interp1d[i],
|
||||||
|
label=self.label2_interp1d[i]
|
||||||
|
)
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
ax2.set_xlabel(self.xaxis_name, fontweight='bold', fontsize=15)
|
||||||
|
ax2.set_ylabel(self.y2axis_name, fontweight='bold', fontsize=15)
|
||||||
|
ax2.tick_params(axis = 'y', labelcolor = 'orange')
|
||||||
|
|
||||||
|
ax2.legend(
|
||||||
|
handles=self.legend_handles,
|
||||||
|
loc=self.legend_loc2,
|
||||||
|
bbox_to_anchor=self.legend_box2,
|
||||||
|
ncol=self.legend_ncol,
|
||||||
|
fontsize=self.legend_fontsize)
|
||||||
|
plt.suptitle(self.title, fontsize=self.title_size)
|
||||||
|
plt.title(self.grp_title)
|
||||||
|
plt.gcf()
|
||||||
|
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
||||||
|
plt.close()
|
||||||
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
|
# TODO work though this for two axis
|
||||||
|
if self.enable_csv:
|
||||||
|
if self.data_set is not None and self.xaxis_categories is not None:
|
||||||
|
if len(self.xaxis_categories) == len(self.data_set[0]):
|
||||||
|
self.lf_csv.columns = []
|
||||||
|
self.lf_csv.rows = []
|
||||||
|
self.lf_csv.columns.append(self.xaxis_name)
|
||||||
|
self.lf_csv.columns.extend(self.label)
|
||||||
|
self.lf_csv.rows.append(self.xaxis_categories)
|
||||||
|
self.lf_csv.rows.extend(self.data_set)
|
||||||
|
self.lf_csv.filename = f"{self.graph_image_name}.csv"
|
||||||
|
self.lf_csv.generate_csv()
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
"Length and x-axis values and y-axis values should be same.")
|
||||||
|
else:
|
||||||
|
logger.debug("No Dataset Found")
|
||||||
|
logger.debug("{}.csv".format(self.graph_image_name))
|
||||||
|
return "%s.png" % self.graph_image_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class lf_stacked_graph:
|
class lf_stacked_graph:
|
||||||
|
"""
|
||||||
|
usage: This will generate a vertically stacked graph with list _data_set as well as with dictionary _data_set.
|
||||||
|
|
||||||
|
example :
|
||||||
|
|
||||||
|
For a graph with dictionary data_set
|
||||||
|
|
||||||
|
obj = lf_stacked_graph(_data_set={'FCC0':0, 'FCC1':88.4,'FCC2':77.8,'FCC3':57.8,'FCC4':90.0,'FCC95':60.4,'FCC6':33.0},
|
||||||
|
_xaxis_name="", _yaxis_name="", _enable_csv=False, _remove_border=True)
|
||||||
|
obj.build_stacked_graph()
|
||||||
|
|
||||||
|
For a graph with list data_set
|
||||||
|
|
||||||
|
obj = lf_stacked_graph(_data_set=[['FCC0', 'FCC1', 'FCC2', 'FCC3', 'FCC4', 'FCC95', 'FCC6'],
|
||||||
|
[0, 88.4, 77.8, 57.8, 90.0, 60.4, 33.0],
|
||||||
|
[100.0, 11.6, 22.2, 42.2, 10.0, 39.6, 67.0]])
|
||||||
|
obj.build_stacked_graph()
|
||||||
|
|
||||||
|
"""
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
_data_set=None,
|
_data_set=None,
|
||||||
_xaxis_name="Stations",
|
_xaxis_name="Stations",
|
||||||
@@ -273,7 +734,17 @@ class lf_stacked_graph:
|
|||||||
_graph_image_name="image_name2",
|
_graph_image_name="image_name2",
|
||||||
_color=None,
|
_color=None,
|
||||||
_figsize=(9, 4),
|
_figsize=(9, 4),
|
||||||
_enable_csv=True):
|
_enable_csv=True,
|
||||||
|
_width=0.79,
|
||||||
|
_bar_text_color='white',
|
||||||
|
_bar_font_weight='bold',
|
||||||
|
_bar_font_size=8,
|
||||||
|
_legend_title="Issues",
|
||||||
|
_legend_bbox=(1.13, 1.01),
|
||||||
|
_legend_loc="upper right",
|
||||||
|
_remove_border=False,
|
||||||
|
_bar_text_rotation=0,
|
||||||
|
_x_ticklabels_rotation=0):
|
||||||
if _data_set is None:
|
if _data_set is None:
|
||||||
_data_set = [[1, 2, 3, 4], [1, 1, 1, 1], [1, 1, 1, 1]]
|
_data_set = [[1, 2, 3, 4], [1, 1, 1, 1], [1, 1, 1, 1]]
|
||||||
if _label is None:
|
if _label is None:
|
||||||
@@ -287,9 +758,19 @@ class lf_stacked_graph:
|
|||||||
self.color = _color
|
self.color = _color
|
||||||
self.enable_csv = _enable_csv
|
self.enable_csv = _enable_csv
|
||||||
self.lf_csv = lf_csv()
|
self.lf_csv = lf_csv()
|
||||||
|
self.width = _width
|
||||||
|
self.bar_text_color = _bar_text_color
|
||||||
|
self.bar_font_weight = _bar_font_weight
|
||||||
|
self.bar_font_size = _bar_font_size
|
||||||
|
self.legend_title = _legend_title
|
||||||
|
self.legend_bbox = _legend_bbox
|
||||||
|
self.legend_loc = _legend_loc
|
||||||
|
self.remove_border = _remove_border
|
||||||
|
self.bar_text_rotation = _bar_text_rotation
|
||||||
|
self.x_ticklabels_rotation = _x_ticklabels_rotation
|
||||||
|
|
||||||
def build_stacked_graph(self):
|
def build_stacked_graph(self):
|
||||||
plt.subplots(figsize=self.figsize)
|
fig, axes_subplot = plt.subplots(figsize=self.figsize)
|
||||||
if self.color is None:
|
if self.color is None:
|
||||||
self.color = [
|
self.color = [
|
||||||
"darkred",
|
"darkred",
|
||||||
@@ -298,22 +779,65 @@ class lf_stacked_graph:
|
|||||||
"skyblue",
|
"skyblue",
|
||||||
"indigo",
|
"indigo",
|
||||||
"plum"]
|
"plum"]
|
||||||
plt.bar(self.data_set[0], self.data_set[1], color=self.color[0])
|
if type(self.data_set) is list:
|
||||||
plt.bar(
|
plt.bar(self.data_set[0], self.data_set[1], color=self.color[0])
|
||||||
self.data_set[0],
|
plt.bar(
|
||||||
self.data_set[2],
|
self.data_set[0],
|
||||||
bottom=self.data_set[1],
|
self.data_set[2],
|
||||||
color=self.color[1])
|
bottom=self.data_set[1],
|
||||||
if len(self.data_set) > 3:
|
color=self.color[1])
|
||||||
for i in range(3, len(self.data_set)):
|
if len(self.data_set) > 3:
|
||||||
plt.bar(self.data_set[0], self.data_set[i],
|
for i in range(3, len(self.data_set)):
|
||||||
bottom=np.array(self.data_set[i - 2]) + np.array(self.data_set[i - 1]), color=self.color[i - 1])
|
plt.bar(self.data_set[0], self.data_set[i],
|
||||||
|
bottom=np.array(self.data_set[i - 2]) + np.array(self.data_set[i - 1]),color=self.color[i - 1])
|
||||||
|
plt.legend(self.label)
|
||||||
|
elif type(self.data_set) is dict:
|
||||||
|
lable_values = []
|
||||||
|
pass_values = []
|
||||||
|
fail_values = []
|
||||||
|
for i in self.data_set:
|
||||||
|
lable_values.append(i)
|
||||||
|
for j in self.data_set:
|
||||||
|
pass_values.append(self.data_set[j])
|
||||||
|
fail_values.append(round(float(100.0 - self.data_set[j]), 1))
|
||||||
|
|
||||||
|
width = self.width
|
||||||
|
figure_size, axes_subplot = plt.subplots(figsize=self.figsize)
|
||||||
|
|
||||||
|
# building vertical bar plot
|
||||||
|
bar_1 = plt.bar(lable_values, pass_values, width, color='green')
|
||||||
|
bar_2 = plt.bar(lable_values, fail_values, width, bottom=pass_values, color='red')
|
||||||
|
|
||||||
|
# inserting bar text
|
||||||
|
if len(list(self.data_set.keys())) > 10:
|
||||||
|
self.bar_text_rotation = 90
|
||||||
|
self.x_ticklabels_rotation = 90
|
||||||
|
for i, v in enumerate(pass_values):
|
||||||
|
if v != 0:
|
||||||
|
plt.text(i + .005, v * 0.45, "%s%s" % (v, "%"), color=self.bar_text_color,
|
||||||
|
fontweight=self.bar_font_weight,
|
||||||
|
fontsize=self.bar_font_size, ha="center", va="center", rotation=self.bar_text_rotation)
|
||||||
|
for i, v in enumerate(fail_values):
|
||||||
|
if v != 0:
|
||||||
|
plt.text(i + .005, v * 0.45 + pass_values[i], "%s%s" % (v, "%"), color=self.bar_text_color,
|
||||||
|
fontweight=self.bar_font_weight, fontsize=self.bar_font_size, ha="center", va="center" ,
|
||||||
|
rotation=self.bar_text_rotation)
|
||||||
|
plt.legend([bar_1, bar_2], self.label, title=self.legend_title, bbox_to_anchor=self.legend_bbox,
|
||||||
|
loc=self.legend_loc)
|
||||||
|
axes_subplot.set_xticks(list(self.data_set.keys()))
|
||||||
|
axes_subplot.set_xticklabels(list(self.data_set.keys()), rotation=self.x_ticklabels_rotation)
|
||||||
|
|
||||||
|
# to remove the borders
|
||||||
|
if self.remove_border:
|
||||||
|
for border in ['top', 'right', 'left', 'bottom']:
|
||||||
|
axes_subplot.spines[border].set_visible(False)
|
||||||
|
axes_subplot.yaxis.set_visible(False)
|
||||||
|
|
||||||
plt.xlabel(self.xaxis_name)
|
plt.xlabel(self.xaxis_name)
|
||||||
plt.ylabel(self.yaxis_name)
|
plt.ylabel(self.yaxis_name)
|
||||||
plt.legend(self.label)
|
plt.savefig("%s.png" % self.graph_image_name, bbox_inches="tight", dpi=96)
|
||||||
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
|
||||||
plt.close()
|
plt.close()
|
||||||
print("{}.png".format(self.graph_image_name))
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
if self.enable_csv:
|
if self.enable_csv:
|
||||||
self.lf_csv.columns = self.label
|
self.lf_csv.columns = self.label
|
||||||
self.lf_csv.rows = self.data_set
|
self.lf_csv.rows = self.data_set
|
||||||
@@ -413,7 +937,7 @@ class lf_horizontal_stacked_graph:
|
|||||||
labelbottom=False) # disable x-axis
|
labelbottom=False) # disable x-axis
|
||||||
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
||||||
plt.close()
|
plt.close()
|
||||||
print("{}.png".format(self.graph_image_name))
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
if self.enable_csv:
|
if self.enable_csv:
|
||||||
self.lf_csv.columns = self.label
|
self.lf_csv.columns = self.label
|
||||||
self.lf_csv.rows = self.data_set
|
self.lf_csv.rows = self.data_set
|
||||||
@@ -430,7 +954,7 @@ class lf_line_graph:
|
|||||||
_xaxis_label=None,
|
_xaxis_label=None,
|
||||||
_graph_title="",
|
_graph_title="",
|
||||||
_title_size=16,
|
_title_size=16,
|
||||||
_graph_image_name="image_name",
|
_graph_image_name="line_graph",
|
||||||
_label=None,
|
_label=None,
|
||||||
_font_weight='bold',
|
_font_weight='bold',
|
||||||
_color=None,
|
_color=None,
|
||||||
@@ -445,9 +969,12 @@ class lf_line_graph:
|
|||||||
_legend_fontsize=None,
|
_legend_fontsize=None,
|
||||||
_marker=None,
|
_marker=None,
|
||||||
_dpi=96,
|
_dpi=96,
|
||||||
_enable_csv=False):
|
_grid=True,
|
||||||
|
_enable_csv=False,
|
||||||
|
_reverse_x=False,
|
||||||
|
_reverse_y=False):
|
||||||
if _data_set is None:
|
if _data_set is None:
|
||||||
_data_set = [[30.4, 55.3, 69.2, 37.1], [45.1, 67.2, 34.3, 22.4], [22.5, 45.6, 12.7, 34.8]]
|
_data_set = [[30.4, 55.3, 69.2, 37.1, 44.0], [45.1, 67.2, 34.3, 22.4, 37.6], [22.5, 45.6, 12.7, 34.8, 22.5]]
|
||||||
if _xaxis_categories is None:
|
if _xaxis_categories is None:
|
||||||
_xaxis_categories = [1, 2, 3, 4, 5]
|
_xaxis_categories = [1, 2, 3, 4, 5]
|
||||||
if _xaxis_label is None:
|
if _xaxis_label is None:
|
||||||
@@ -456,6 +983,9 @@ class lf_line_graph:
|
|||||||
_label = ["bi-downlink", "bi-uplink", 'uplink']
|
_label = ["bi-downlink", "bi-uplink", 'uplink']
|
||||||
if _color is None:
|
if _color is None:
|
||||||
_color = ['forestgreen', 'c', 'r', 'g', 'b', 'p']
|
_color = ['forestgreen', 'c', 'r', 'g', 'b', 'p']
|
||||||
|
if _marker is None:
|
||||||
|
_marker = ['s', 'o', 'v'] # available markers = '.', 'o', 'v', '<', 's', '*', 'p', 'P'
|
||||||
|
self.grid = _grid
|
||||||
self.data_set = _data_set
|
self.data_set = _data_set
|
||||||
self.xaxis_name = _xaxis_name
|
self.xaxis_name = _xaxis_name
|
||||||
self.yaxis_name = _yaxis_name
|
self.yaxis_name = _yaxis_name
|
||||||
@@ -479,6 +1009,8 @@ class lf_line_graph:
|
|||||||
self.legend_box = _legend_box
|
self.legend_box = _legend_box
|
||||||
self.legend_ncol = _legend_ncol
|
self.legend_ncol = _legend_ncol
|
||||||
self.legend_fontsize = _legend_fontsize
|
self.legend_fontsize = _legend_fontsize
|
||||||
|
self.reverse_x = _reverse_x
|
||||||
|
self.reverse_y = _reverse_y
|
||||||
|
|
||||||
def build_line_graph(self):
|
def build_line_graph(self):
|
||||||
plt.subplots(figsize=self.figsize)
|
plt.subplots(figsize=self.figsize)
|
||||||
@@ -489,11 +1021,13 @@ class lf_line_graph:
|
|||||||
data,
|
data,
|
||||||
color=self.color[i],
|
color=self.color[i],
|
||||||
label=self.label[i],
|
label=self.label[i],
|
||||||
marker=self.marker)
|
marker=self.marker[i])
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15)
|
plt.xlabel(self.xaxis_name, fontweight='bold', fontsize=15)
|
||||||
plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15)
|
plt.ylabel(self.yaxis_name, fontweight='bold', fontsize=15)
|
||||||
|
if self.grid:
|
||||||
|
plt.grid(True, linestyle=':') # available line styles = ':', '-', '--', '-.'
|
||||||
plt.legend(
|
plt.legend(
|
||||||
handles=self.legend_handles,
|
handles=self.legend_handles,
|
||||||
loc=self.legend_loc,
|
loc=self.legend_loc,
|
||||||
@@ -501,10 +1035,14 @@ class lf_line_graph:
|
|||||||
ncol=self.legend_ncol,
|
ncol=self.legend_ncol,
|
||||||
fontsize=self.legend_fontsize)
|
fontsize=self.legend_fontsize)
|
||||||
plt.suptitle(self.grp_title, fontsize=self.title_size)
|
plt.suptitle(self.grp_title, fontsize=self.title_size)
|
||||||
|
if self.reverse_y:
|
||||||
|
plt.gca().invert_yaxis()
|
||||||
|
if self.reverse_x:
|
||||||
|
plt.gca().invert_xaxis()
|
||||||
plt.gcf()
|
plt.gcf()
|
||||||
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
plt.savefig("%s.png" % self.graph_image_name, dpi=96)
|
||||||
plt.close()
|
plt.close()
|
||||||
print("{}.png".format(self.graph_image_name))
|
logger.debug("{}.png".format(self.graph_image_name))
|
||||||
if self.enable_csv:
|
if self.enable_csv:
|
||||||
if self.data_set is not None:
|
if self.data_set is not None:
|
||||||
self.lf_csv.columns = self.label
|
self.lf_csv.columns = self.label
|
||||||
@@ -512,12 +1050,17 @@ class lf_line_graph:
|
|||||||
self.lf_csv.filename = f"{self.graph_image_name}.csv"
|
self.lf_csv.filename = f"{self.graph_image_name}.csv"
|
||||||
self.lf_csv.generate_csv()
|
self.lf_csv.generate_csv()
|
||||||
else:
|
else:
|
||||||
print("No Dataset Found")
|
logger.debug("No Dataset Found")
|
||||||
print("{}.csv".format(self.graph_image_name))
|
logger.debug("{}.csv".format(self.graph_image_name))
|
||||||
return "%s.png" % self.graph_image_name
|
return "%s.png" % self.graph_image_name
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
help_summary = '''\
|
||||||
|
This script facilitates the generation of comprehensive graphical reports. It offers a variety of graph types,
|
||||||
|
including bar graphs, horizontal bar graphs, scatter graphs, bar-line graphs, stacked graphs, horizontal stacked
|
||||||
|
graphs, and line graphs.
|
||||||
|
'''
|
||||||
# arguments
|
# arguments
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog='lf_graph.py',
|
prog='lf_graph.py',
|
||||||
@@ -551,10 +1094,44 @@ INCLUDE_IN_README
|
|||||||
dest='lfmgr',
|
dest='lfmgr',
|
||||||
help='sample argument: where LANforge GUI is running',
|
help='sample argument: where LANforge GUI is running',
|
||||||
default='localhost')
|
default='localhost')
|
||||||
|
# logging configuration
|
||||||
|
parser.add_argument(
|
||||||
|
'--debug',
|
||||||
|
help='--debug this will enable debugging in py-json method',
|
||||||
|
action='store_true')
|
||||||
|
parser.add_argument('--log_level',
|
||||||
|
default=None,
|
||||||
|
help='Set logging level: debug | info | warning | error | critical')
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--lf_logger_config_json",
|
||||||
|
help="--lf_logger_config_json <json file> , json configuration of logger")
|
||||||
|
|
||||||
|
parser.add_argument('--help_summary', help='Show summary of what this script does', default=None,
|
||||||
|
action="store_true")
|
||||||
|
|
||||||
# the args parser is not really used , this is so the report is not generated when testing
|
# the args parser is not really used , this is so the report is not generated when testing
|
||||||
# the imports with --help
|
# the imports with --help
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
print("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr))
|
|
||||||
|
if args.help_summary:
|
||||||
|
print(help_summary)
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
# set up logger
|
||||||
|
logger_config = lf_logger_config.lf_logger_config()
|
||||||
|
|
||||||
|
# set the logger level to debug
|
||||||
|
if args.log_level:
|
||||||
|
logger_config.set_level(level=args.log_level)
|
||||||
|
|
||||||
|
# lf_logger_config_json will take presidence to changing debug levels
|
||||||
|
if args.lf_logger_config_json:
|
||||||
|
# logger_config.lf_logger_config_json = "lf_logger_config.json"
|
||||||
|
logger_config.lf_logger_config_json = args.lf_logger_config_json
|
||||||
|
logger_config.load_lf_logger_config()
|
||||||
|
|
||||||
|
logger.debug("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr))
|
||||||
|
|
||||||
output_html_1 = "graph_1.html"
|
output_html_1 = "graph_1.html"
|
||||||
output_pdf_1 = "graph_1.pdf"
|
output_pdf_1 = "graph_1.pdf"
|
||||||
@@ -594,6 +1171,9 @@ INCLUDE_IN_README
|
|||||||
_label=["bi-downlink", "bi-uplink", 'uplink'],
|
_label=["bi-downlink", "bi-uplink", 'uplink'],
|
||||||
_color=None,
|
_color=None,
|
||||||
_color_edge='red',
|
_color_edge='red',
|
||||||
|
_show_bar_value=True,
|
||||||
|
_text_font=7,
|
||||||
|
_text_rotation=None,
|
||||||
_enable_csv=True)
|
_enable_csv=True)
|
||||||
graph_html_obj = """
|
graph_html_obj = """
|
||||||
<img align='center' style='padding:15;margin:5;width:1000px;' src=""" + "%s" % (graph.build_bar_graph()) + """ border='1' />
|
<img align='center' style='padding:15;margin:5;width:1000px;' src=""" + "%s" % (graph.build_bar_graph()) + """ border='1' />
|
||||||
@@ -604,6 +1184,10 @@ INCLUDE_IN_README
|
|||||||
test_file.write(graph_html_obj)
|
test_file.write(graph_html_obj)
|
||||||
test_file.close()
|
test_file.close()
|
||||||
|
|
||||||
|
graph = lf_line_graph()
|
||||||
|
|
||||||
|
graph.build_line_graph()
|
||||||
|
|
||||||
# write to pdf
|
# write to pdf
|
||||||
# write logic to generate pdf here
|
# write logic to generate pdf here
|
||||||
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
@@ -612,6 +1196,49 @@ INCLUDE_IN_README
|
|||||||
options = {"enable-local-file-access": None}
|
options = {"enable-local-file-access": None}
|
||||||
pdfkit.from_file(output_html_2, output_pdf_2, options=options)
|
pdfkit.from_file(output_html_2, output_pdf_2, options=options)
|
||||||
|
|
||||||
|
# test build_bar_graph_horizontal with defaults
|
||||||
|
dataset = [[45, 67, 34, 22, 31, 52, 60, 71, 24, 25, 45, 67, 34, 22, 31, 52, 60, 71, 24, 25], [22, 45, 12, 34, 70, 80, 14, 35, 44, 45,22, 45, 12, 34, 70, 80, 14, 35, 44, 45 ], [30, 55, 69, 37, 77, 24, 25, 77, 77, 80, 30, 55, 69, 37, 77, 24, 25, 77, 77, 80]]
|
||||||
|
y_axis_values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||||
|
|
||||||
|
# calculate the height of the y-axis .25 * number of values
|
||||||
|
y_fig_size = len(y_axis_values) * len(dataset) * .35
|
||||||
|
x_fig_size = 10
|
||||||
|
|
||||||
|
output_html_3 = "graph_3.html"
|
||||||
|
output_pdf_3 = "graph_3.pdf"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
graph = lf_bar_graph_horizontal(_data_set=dataset,
|
||||||
|
_xaxis_name="Throughput 2 (Mbps)",
|
||||||
|
_yaxis_name="stations",
|
||||||
|
_yaxis_categories=y_axis_values,
|
||||||
|
_graph_image_name="Bi-single_radio_2.4GHz",
|
||||||
|
_label=["bi-downlink", "bi-uplink", 'uplink'],
|
||||||
|
_color=None,
|
||||||
|
_color_edge='red',
|
||||||
|
_figsize=(x_fig_size, y_fig_size),
|
||||||
|
_show_bar_value= True,
|
||||||
|
_text_font=6,
|
||||||
|
_text_rotation=True,
|
||||||
|
_enable_csv=True)
|
||||||
|
graph_html_obj = """
|
||||||
|
<img align='center' style='padding:15;margin:5;width:1000px;' src=""" + "%s" % (graph.build_bar_graph_horizontal()) + """ border='1' />
|
||||||
|
<br><br>
|
||||||
|
"""
|
||||||
|
#
|
||||||
|
test_file = open(output_html_3, "w")
|
||||||
|
test_file.write(graph_html_obj)
|
||||||
|
test_file.close()
|
||||||
|
|
||||||
|
# write to pdf
|
||||||
|
# write logic to generate pdf here
|
||||||
|
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
|
# sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
|
# prevent eerror Blocked access to file
|
||||||
|
options = {"enable-local-file-access": None}
|
||||||
|
pdfkit.from_file(output_html_3, output_pdf_3, options=options)
|
||||||
|
|
||||||
|
|
||||||
# Unit Test
|
# Unit Test
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -86,7 +86,10 @@ class lf_report:
|
|||||||
self.graph_title = _graph_title
|
self.graph_title = _graph_title
|
||||||
self.date = _date
|
self.date = _date
|
||||||
self.output_html = _output_html
|
self.output_html = _output_html
|
||||||
|
if _output_html.lower().endswith(".pdf"):
|
||||||
|
raise ValueError("HTML output file cannot end with suffix '.pdf'")
|
||||||
self.path_date_time = _path_date_time
|
self.path_date_time = _path_date_time
|
||||||
|
self.report_location = "" # used by lf_check.py to know where to write the meta data "Report Location:::/home/lanforge/html-reports/wifi-capacity-2021-08-17-04-02-56"
|
||||||
self.write_output_html = ""
|
self.write_output_html = ""
|
||||||
self.write_output_index_html = ""
|
self.write_output_index_html = ""
|
||||||
self.output_pdf = _output_pdf
|
self.output_pdf = _output_pdf
|
||||||
@@ -101,6 +104,8 @@ class lf_report:
|
|||||||
self.pdf_link_html = ""
|
self.pdf_link_html = ""
|
||||||
self.objective = _obj
|
self.objective = _obj
|
||||||
self.obj_title = _obj_title
|
self.obj_title = _obj_title
|
||||||
|
self.description = ""
|
||||||
|
self.desc_title = ""
|
||||||
# self.systeminfopath = ""
|
# self.systeminfopath = ""
|
||||||
self.date_time_directory = ""
|
self.date_time_directory = ""
|
||||||
self.log_directory = ""
|
self.log_directory = ""
|
||||||
@@ -132,9 +137,12 @@ class lf_report:
|
|||||||
shutil.copy(banner_src_file, banner_dst_file)
|
shutil.copy(banner_src_file, banner_dst_file)
|
||||||
|
|
||||||
def move_data(self, directory=None, _file_name=None, directory_name=None):
|
def move_data(self, directory=None, _file_name=None, directory_name=None):
|
||||||
if directory_name is None:
|
if directory_name is None:
|
||||||
_src_file = str(self.current_path) + '/' + str(_file_name)
|
_src_file = str(self.current_path) + '/' + str(_file_name)
|
||||||
_dst_file = str(self.path_date_time) + '/' + str(directory) + '/' + str(_file_name)
|
if directory is None:
|
||||||
|
_dst_file = str(self.path_date_time)
|
||||||
|
else:
|
||||||
|
_dst_file = str(self.path_date_time) + '/' + str(directory) + '/' + str(_file_name)
|
||||||
else:
|
else:
|
||||||
_src_file = str(self.current_path) + '/' + str(directory_name)
|
_src_file = str(self.current_path) + '/' + str(directory_name)
|
||||||
_dst_file = str(self.path_date_time) + '/' + str(directory_name)
|
_dst_file = str(self.path_date_time) + '/' + str(directory_name)
|
||||||
@@ -251,6 +259,10 @@ class lf_report:
|
|||||||
fname, ext = os.path.splitext(_graph_title)
|
fname, ext = os.path.splitext(_graph_title)
|
||||||
self.csv_file_name = fname + ".csv"
|
self.csv_file_name = fname + ".csv"
|
||||||
|
|
||||||
|
def write_dataframe_to_csv(self, _index=False):
|
||||||
|
csv_file = "{path_date_time}/{csv_file_name}".format(path_date_time=self.path_date_time,csv_file_name=self.csv_file_name)
|
||||||
|
self.dataframe.to_csv(csv_file,index=_index)
|
||||||
|
|
||||||
# The _date is set when class is enstanciated / created so this set_date should be used with caution, used to synchronize results
|
# The _date is set when class is enstanciated / created so this set_date should be used with caution, used to synchronize results
|
||||||
def set_date(self, _date):
|
def set_date(self, _date):
|
||||||
self.date = _date
|
self.date = _date
|
||||||
@@ -275,6 +287,10 @@ class lf_report:
|
|||||||
self.objective = _obj
|
self.objective = _obj
|
||||||
self.obj_title = _obj_title
|
self.obj_title = _obj_title
|
||||||
|
|
||||||
|
def set_desc_html(self, _desc_title, _desc):
|
||||||
|
self.description = _desc
|
||||||
|
self.desc_title = _desc_title
|
||||||
|
|
||||||
def set_graph_image(self, _graph_image):
|
def set_graph_image(self, _graph_image):
|
||||||
self.graph_image = _graph_image
|
self.graph_image = _graph_image
|
||||||
|
|
||||||
@@ -305,8 +321,20 @@ class lf_report:
|
|||||||
output_file = str(self.path_date_time) + '/' + str(file)
|
output_file = str(self.path_date_time) + '/' + str(file)
|
||||||
logger.info("output file {}".format(output_file))
|
logger.info("output file {}".format(output_file))
|
||||||
return output_file
|
return output_file
|
||||||
|
# Report Location:::/<locaton> as a key in lf_check.py
|
||||||
|
def write_report_location(self):
|
||||||
|
self.report_location = self.path_date_time
|
||||||
|
logger.info("Report Location:::{report_location}".format(report_location=self.report_location))
|
||||||
|
|
||||||
|
|
||||||
def write_html(self):
|
def write_html(self):
|
||||||
|
if not self.output_html:
|
||||||
|
logger.info("no html file name, skipping report generation")
|
||||||
|
return
|
||||||
|
if self.output_html.lower().endswith(".pdf"):
|
||||||
|
raise ValueError("write_html: HTML filename [%s] should not end with .pdf" % self.output_html)
|
||||||
|
if self.write_output_html.endswith(".pdf"):
|
||||||
|
raise ValueError("wrong suffix for an HTML file: %s" % self.write_output_html)
|
||||||
self.write_output_html = str(self.path_date_time) + '/' + str(self.output_html)
|
self.write_output_html = str(self.path_date_time) + '/' + str(self.output_html)
|
||||||
logger.info("write_output_html: {}".format(self.write_output_html))
|
logger.info("write_output_html: {}".format(self.write_output_html))
|
||||||
try:
|
try:
|
||||||
@@ -319,7 +347,13 @@ class lf_report:
|
|||||||
return self.write_output_html
|
return self.write_output_html
|
||||||
|
|
||||||
def write_index_html(self):
|
def write_index_html(self):
|
||||||
self.write_output_index_html = str(self.path_date_time) + '/' + str("index.html")
|
# LAN-1535 scripting: test_l3.py output masks other output when browsing.
|
||||||
|
# consider renaming index.html to readme.html
|
||||||
|
# self.write_output_index_html = str(self.path_date_time) + '/' + str("index.html")
|
||||||
|
if not self.output_html:
|
||||||
|
logger.info("no html file name, skipping report generation")
|
||||||
|
return
|
||||||
|
self.write_output_index_html = str(self.path_date_time) + '/' + str("readme.html")
|
||||||
logger.info("write_output_index_html: {}".format(self.write_output_index_html))
|
logger.info("write_output_index_html: {}".format(self.write_output_index_html))
|
||||||
try:
|
try:
|
||||||
test_file = open(self.write_output_index_html, "w")
|
test_file = open(self.write_output_index_html, "w")
|
||||||
@@ -331,6 +365,11 @@ class lf_report:
|
|||||||
return self.write_output_index_html
|
return self.write_output_index_html
|
||||||
|
|
||||||
def write_html_with_timestamp(self):
|
def write_html_with_timestamp(self):
|
||||||
|
if not self.output_html:
|
||||||
|
logger.info("no html file name, skipping report generation")
|
||||||
|
return
|
||||||
|
if self.output_html.lower().endswith(".pdf"):
|
||||||
|
raise ValueError("write_html_with_timestamp: will not save file with PDF suffix [%s]" % self.output_html)
|
||||||
self.write_output_html = "{}/{}-{}".format(self.path_date_time, self.date, self.output_html)
|
self.write_output_html = "{}/{}-{}".format(self.path_date_time, self.date, self.output_html)
|
||||||
logger.info("write_output_html: {}".format(self.write_output_html))
|
logger.info("write_output_html: {}".format(self.write_output_html))
|
||||||
try:
|
try:
|
||||||
@@ -349,7 +388,9 @@ class lf_report:
|
|||||||
# write logic to generate pdf here
|
# write logic to generate pdf here
|
||||||
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
# sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb
|
# sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
|
if not self.output_pdf:
|
||||||
|
logger.info("write_pdf: no pdf file name, skipping pdf output")
|
||||||
|
return
|
||||||
options = {"enable-local-file-access": None,
|
options = {"enable-local-file-access": None,
|
||||||
'orientation': _orientation,
|
'orientation': _orientation,
|
||||||
'page-size': _page_size} # prevent error Blocked access to file
|
'page-size': _page_size} # prevent error Blocked access to file
|
||||||
@@ -363,7 +404,9 @@ class lf_report:
|
|||||||
# write logic to generate pdf here
|
# write logic to generate pdf here
|
||||||
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
# wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
# sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb
|
# sudo apt install ./wkhtmltox_0.12.6-1.focal_amd64.deb
|
||||||
|
if not self.output_pdf:
|
||||||
|
logger.info("write_pdf_with_timestamp: no pdf file name, skipping pdf output")
|
||||||
|
return
|
||||||
options = {"enable-local-file-access": None,
|
options = {"enable-local-file-access": None,
|
||||||
'orientation': _orientation,
|
'orientation': _orientation,
|
||||||
'page-size': _page_size} # prevent error Blocked access to file
|
'page-size': _page_size} # prevent error Blocked access to file
|
||||||
@@ -374,6 +417,14 @@ class lf_report:
|
|||||||
pdf_link_path = "{}/{}-{}".format(self.path_date_time, self.date, self.output_pdf)
|
pdf_link_path = "{}/{}-{}".format(self.path_date_time, self.date, self.output_pdf)
|
||||||
return pdf_link_path
|
return pdf_link_path
|
||||||
|
|
||||||
|
# used for relative pathing
|
||||||
|
def get_pdf_file(self):
|
||||||
|
if not self.output_pdf:
|
||||||
|
logger.info("get_pdf_file: no pdf name, returning None")
|
||||||
|
return None
|
||||||
|
pdf_file = "{}-{}".format(self.date, self.output_pdf)
|
||||||
|
return pdf_file
|
||||||
|
|
||||||
def build_pdf_link(self, _pdf_link_name, _pdf_link_path):
|
def build_pdf_link(self, _pdf_link_name, _pdf_link_path):
|
||||||
self.pdf_link_html = """
|
self.pdf_link_html = """
|
||||||
<!-- pdf link -->
|
<!-- pdf link -->
|
||||||
@@ -392,7 +443,8 @@ class lf_report:
|
|||||||
|
|
||||||
def generate_report(self):
|
def generate_report(self):
|
||||||
self.write_html()
|
self.write_html()
|
||||||
self.write_pdf()
|
if self.output_pdf:
|
||||||
|
self.write_pdf()
|
||||||
|
|
||||||
def build_all(self):
|
def build_all(self):
|
||||||
self.build_banner()
|
self.build_banner()
|
||||||
@@ -462,6 +514,32 @@ class lf_report:
|
|||||||
)
|
)
|
||||||
self.html += self.banner_html
|
self.html += self.banner_html
|
||||||
|
|
||||||
|
def build_banner_left_h2_font(self):
|
||||||
|
# NOTE: {{ }} are the ESCAPED curly braces
|
||||||
|
# JBR suggests rename method to start_html_doc()
|
||||||
|
# This method violates DRY, if the ID of the body/div#BannerBack/div element is actually necessary
|
||||||
|
# to specify, this needs to be made a parameter for build_banner() or start_html_doc()
|
||||||
|
self.banner_html = """<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
{head_tag}
|
||||||
|
<body>
|
||||||
|
<div id='BannerBack'>
|
||||||
|
<div id='BannerLeft'>
|
||||||
|
<img id='BannerLogo' align='right' src="CandelaLogo2-90dpi-200x90-trans.png" border='0'/>
|
||||||
|
<div class='HeaderStyle'>
|
||||||
|
<h2 class='TitleFontPrint' style='color:darkgreen;'>{title}</h2>
|
||||||
|
<h4 class='TitleFontPrintSub' style='color:darkgreen;'>{date}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
""".format(
|
||||||
|
head_tag=self.get_html_head(title=self.title),
|
||||||
|
title=self.title,
|
||||||
|
date=self.date,
|
||||||
|
)
|
||||||
|
self.html += self.banner_html
|
||||||
|
|
||||||
|
|
||||||
def build_table_title(self):
|
def build_table_title(self):
|
||||||
self.table_title_html = """
|
self.table_title_html = """
|
||||||
<!-- Table Title-->
|
<!-- Table Title-->
|
||||||
@@ -483,6 +561,14 @@ class lf_report:
|
|||||||
</div>""".format(text=self.text)
|
</div>""".format(text=self.text)
|
||||||
self.html += self.text_html
|
self.html += self.text_html
|
||||||
|
|
||||||
|
def build_text_simple(self):
|
||||||
|
# please do not use 'style=' tags unless you cannot override a class
|
||||||
|
self.text_html = """
|
||||||
|
<p align='left' width='900'>{text}</p>
|
||||||
|
""".format(text=self.text)
|
||||||
|
self.html += self.text_html
|
||||||
|
|
||||||
|
|
||||||
def build_date_time(self):
|
def build_date_time(self):
|
||||||
self.date_time = str(datetime.datetime.now().strftime("%Y-%m-%d-%H-h-%m-m-%S-s")).replace(':', '-')
|
self.date_time = str(datetime.datetime.now().strftime("%Y-%m-%d-%H-h-%m-m-%S-s")).replace(':', '-')
|
||||||
return self.date_time
|
return self.date_time
|
||||||
@@ -530,10 +616,10 @@ class lf_report:
|
|||||||
plt.savefig(str(self.path_date_time) + '/pie-chart.png')
|
plt.savefig(str(self.path_date_time) + '/pie-chart.png')
|
||||||
|
|
||||||
def save_bar_chart(self, xlabel, ylabel, bar_chart_data, name):
|
def save_bar_chart(self, xlabel, ylabel, bar_chart_data, name):
|
||||||
plot = bar_chart_data.plot.bar(alpha=0.9, rot=0, width=0.9, linewidth=0.9)
|
plot = bar_chart_data.plot.bar(alpha=0.9, rot=0, width=0.9, linewidth=0.9, figsize=(10, 6))
|
||||||
plot.legend(bbox_to_anchor=(1.0, 1.0))
|
plot.legend(bbox_to_anchor=(1.0, 1.0))
|
||||||
plot.spines['right'].set_visible(False)
|
# plot.spines['right'].set_visible(False)
|
||||||
plot.spines['top'].set_visible(False)
|
# plot.spines['top'].set_visible(False)
|
||||||
# plot.set_title(name)
|
# plot.set_title(name)
|
||||||
for p in plot.patches:
|
for p in plot.patches:
|
||||||
height = p.get_height()
|
height = p.get_height()
|
||||||
@@ -545,7 +631,7 @@ class lf_report:
|
|||||||
annotation_clip=False,
|
annotation_clip=False,
|
||||||
ha='center', va='bottom')
|
ha='center', va='bottom')
|
||||||
# plt.xlabel(xlabel)
|
# plt.xlabel(xlabel)
|
||||||
plt.xticks(rotation=45, horizontalalignment='right', fontweight='light', fontsize='small', )
|
plt.xticks(rotation=0, horizontalalignment='right', fontweight='light', fontsize='small', )
|
||||||
plt.ylabel(ylabel)
|
plt.ylabel(ylabel)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig(str(self.path_date_time) + '/' + name + '.png')
|
plt.savefig(str(self.path_date_time) + '/' + name + '.png')
|
||||||
@@ -647,6 +733,16 @@ function copyTextToClipboard(ele) {
|
|||||||
objective=self.objective)
|
objective=self.objective)
|
||||||
self.html += self.obj_html
|
self.html += self.obj_html
|
||||||
|
|
||||||
|
def build_description(self):
|
||||||
|
self.obj_html = """
|
||||||
|
<!-- Test Description -->
|
||||||
|
<h3 align='left'>{title}</h3>
|
||||||
|
<p align='left' width='900'>{description}</p>
|
||||||
|
""".format(title=self.desc_title,
|
||||||
|
description=self.description)
|
||||||
|
self.html += self.obj_html
|
||||||
|
|
||||||
|
|
||||||
def build_graph_title(self):
|
def build_graph_title(self):
|
||||||
self.table_graph_html = """
|
self.table_graph_html = """
|
||||||
<div class='HeaderStyle'>
|
<div class='HeaderStyle'>
|
||||||
@@ -660,6 +756,12 @@ function copyTextToClipboard(ele) {
|
|||||||
""".format(image=self.graph_image)
|
""".format(image=self.graph_image)
|
||||||
self.html += self.graph_html_obj
|
self.html += self.graph_html_obj
|
||||||
|
|
||||||
|
def build_graph_without_border(self):
|
||||||
|
self.graph_html_obj = """
|
||||||
|
<img align='left' style='padding:15px;margin:5px 5px 2em 5px;width:1000px;' src='{image}' border='0' />
|
||||||
|
""".format(image=self.graph_image)
|
||||||
|
self.html += self.graph_html_obj
|
||||||
|
|
||||||
def end_content_div(self):
|
def end_content_div(self):
|
||||||
self.html += "\n</div><!-- end contentDiv -->\n"
|
self.html += "\n</div><!-- end contentDiv -->\n"
|
||||||
|
|
||||||
@@ -676,9 +778,45 @@ function copyTextToClipboard(ele) {
|
|||||||
""".format(image=name)
|
""".format(image=name)
|
||||||
self.html += self.chart_html_obj
|
self.html += self.chart_html_obj
|
||||||
|
|
||||||
|
def build_chart_custom(self, name, align='center',padding='15px',margin='5px 5px 2em 5px',width='500px',height='500px'):
|
||||||
|
|
||||||
|
self.chart_html_obj = """
|
||||||
|
<img align='{align}' style='padding:{padding};margin:{margin};width:{width};height:{height};'
|
||||||
|
src='{image}'/> """.format(image=name,align=align,padding=padding,margin=margin,width=width, height=height)
|
||||||
|
self.html += self.chart_html_obj
|
||||||
|
|
||||||
|
def build_banner_cover(self):
|
||||||
|
# NOTE: {{ }} are the ESCAPED curly braces
|
||||||
|
# JBR suggests rename method to start_html_doc()
|
||||||
|
# This method violates DRY, if the ID of the body/div#BannerBack/div element is actually necessary
|
||||||
|
# to specify, this needs to be made a parameter for build_banner() or start_html_doc()
|
||||||
|
self.banner_html = """<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
{head_tag}
|
||||||
|
<body>
|
||||||
|
<div id='BannerBack' style='height: 100%; max-height: 100%;'>
|
||||||
|
<div id='BannerLeft' style="margin: 0%; background-size: 100%; max-height: 100%; max-width: 100%; width: 100%; height: 100%;">
|
||||||
|
<img id='BannerLogo' align='right' src="CandelaLogo2-90dpi-200x90-trans.png" border='0'/>
|
||||||
|
<div class='HeaderStyle'>
|
||||||
|
<h1 class='TitleFontPrint' style='color:darkgreen;'>{title}</h1>
|
||||||
|
<h4 class='TitleFontPrintSub' style='color:darkgreen;'>{date}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
""".format(
|
||||||
|
head_tag=self.get_html_head(title=self.title),
|
||||||
|
title=self.title,
|
||||||
|
date=self.date,
|
||||||
|
)
|
||||||
|
self.html += self.banner_html
|
||||||
|
|
||||||
# Unit Test
|
# Unit Test
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
help_summary = '''\
|
||||||
|
This script is designed to generate reports in file formats such as PDF and HTML, accommodating various user
|
||||||
|
preferences. The reports can encompass a range of elements, including graphs, tables, and customizable objectives,
|
||||||
|
tailored to meet specific user requirements
|
||||||
|
'''
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog="lf_report.py",
|
prog="lf_report.py",
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -686,7 +824,15 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument('--lfmgr', help='sample argument: where LANforge GUI is running', default='localhost')
|
parser.add_argument('--lfmgr', help='sample argument: where LANforge GUI is running', default='localhost')
|
||||||
# the args parser is not really used , this is so the report is not generated when testing
|
# the args parser is not really used , this is so the report is not generated when testing
|
||||||
# the imports with --help
|
# the imports with --help
|
||||||
|
parser.add_argument('--help_summary', help='Show summary of what this script does', default=None,
|
||||||
|
action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# help summary
|
||||||
|
if args.help_summary:
|
||||||
|
print(help_summary)
|
||||||
|
exit(0)
|
||||||
|
|
||||||
logger.info("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr))
|
logger.info("LANforge manager {lfmgr}".format(lfmgr=args.lfmgr))
|
||||||
|
|
||||||
# Testing: generate data frame
|
# Testing: generate data frame
|
||||||
@@ -723,6 +869,12 @@ if __name__ == "__main__":
|
|||||||
report.set_table_dataframe(dataframe2)
|
report.set_table_dataframe(dataframe2)
|
||||||
report.build_table()
|
report.build_table()
|
||||||
|
|
||||||
|
report.build_chart_title('default width')
|
||||||
|
report.build_chart("banner.png")
|
||||||
|
|
||||||
|
report.build_chart_title('custom width')
|
||||||
|
report.build_chart_custom(name="banner.png",width="1000")
|
||||||
|
|
||||||
# report.build_all()
|
# report.build_all()
|
||||||
# report.build_footer()
|
# report.build_footer()
|
||||||
report.build_footer_no_png()
|
report.build_footer_no_png()
|
||||||
|
|||||||
Reference in New Issue
Block a user