Skip to content

Commit

Permalink
[QPROF] Adding Merged Legend (#1281)
Browse files Browse the repository at this point in the history
- it is now possible to merge and separate the legends of two query profilers objects.

Should close:
https://jira.verticacorp.com/jira/browse/VER-96478?filter=-1
  • Loading branch information
oualib authored Sep 22, 2024
1 parent 4ffb60c commit fd1df5e
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 7 deletions.
2 changes: 1 addition & 1 deletion verticapy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
__license__: str = "Apache License, Version 2.0"
__version__: str = "1.0.5"
__iteration__: int = 1
__date__: str = "19092024"
__date__: str = "20092024"
__last_commit__: str = "d15329cab9a2360454f4473e676068d2f793b965"
__long_version__: str = f"{__version__}-{__iteration__}{__date__}-{__last_commit__}"
__codecov__: float = 0.84
Expand Down
86 changes: 86 additions & 0 deletions verticapy/performance/vertica/qprof_utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import re
from typing import Union, Set

from verticapy._typing import NoneType
from verticapy._utils._sql._sys import _executeSQL


Expand All @@ -26,6 +27,91 @@ class QprofUtility:
of static methods for QPROF.
"""

# Tree Comparaison Functions
@staticmethod
def get_tree_elements(qprof1: ..., qprof2: ..., **qplan_tree_params) -> ...:
"""
For 2 ``QueryProfiler`` objects. This
Function will return the two trees and
the unified legends.
Parameters
----------
qprof1: QueryProfiler
``QueryProfiler`` object.
qprof2: QueryProfiler
``QueryProfiler`` object.
**qplan_tree_params
Parameters to pass to the
``get_qplan_tree`` method.
Returns
-------
dict
``dict`` of ``Tree`` objects.
Examples
--------
See :py:meth:`~verticapy.performance.vertica.qprof_utility`
for more information.
"""

# Trees
tree1 = qprof1.get_qplan_tree(return_tree_obj=True, **qplan_tree_params)
tree2 = qprof2.get_qplan_tree(return_tree_obj=True, **qplan_tree_params)
tree1_html = tree1.get_tree()
tree2_html = tree2.get_tree()

# Unifying the legends
min1, max1 = tree1.get_metric1_minmax()
min2, max2 = tree2.get_metric1_minmax()
if isinstance(min2, NoneType):
min2 = min1
if isinstance(max2, NoneType):
max2 = max1
if not (isinstance(max2, NoneType)) and not (isinstance(min2, NoneType)):
minf1, maxf1 = min(min1, min2), max(max1, max2)
else:
minf1, maxf1 = 0, 0
min1, max1 = tree1.get_metric2_minmax()
min2, max2 = tree2.get_metric2_minmax()
if isinstance(min2, NoneType):
min2 = min1
if isinstance(max2, NoneType):
max2 = max1
if not (isinstance(max2, NoneType)) and not (isinstance(min2, NoneType)):
minf2, maxf2 = min(min1, min2), max(max1, max2)
else:
minf2, maxf2 = 0, 0

# Handling Missing Values
hasnull_1 = tree1.style["hasnull_0"] or tree2.style["hasnull_0"]
hasnull_2 = tree1.style["hasnull_1"] or tree2.style["hasnull_1"]

# Final Legends
legend1_html = tree1.get_legend1(
legend1_min=minf1, legend1_max=maxf1, hasnull_0=hasnull_1
)
legend2_html = tree1.get_legend2(
legend2_min=minf2, legend2_max=maxf2, hasnull_1=hasnull_2
)

# Path Transition
path_transition = tree1.get_path_transition(
rows_path_transition=tree1.rows + tree2.rows
)

return {
"tree1": tree1_html,
"tree2": tree2_html,
"legend1": legend1_html,
"legend2": legend2_html,
"path_transition": path_transition,
"initial_objects": [tree1, tree2],
}

# Utils

@staticmethod
def _get_label(
row: str, return_path_id: bool = True, row_idx: int = 0
Expand Down
39 changes: 33 additions & 6 deletions verticapy/performance/vertica/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,9 @@ def get_legend2(self, **tree_style) -> ...:
obj.style["display_tree"] = False
return obj.to_html()

def get_path_transition(self, **tree_style) -> ...:
def get_path_transition(
self, rows_path_transition: Optional[list] = None, **tree_style
) -> ...:
"""
Returns the Path Transition
legend without any additional
Expand All @@ -462,14 +464,16 @@ def get_path_transition(self, **tree_style) -> ...:
obj.style["display_legend1"] = False
obj.style["display_legend2"] = False
obj.style["display_tree"] = False
if isinstance(rows_path_transition, list):
obj.rows_path_transition = rows_path_transition
return obj.to_html()

def get_metric1_minmax(self) -> tuple:
"""
Returns the metric 1 min and max.
"""
if len(self.metric) == 0:
return None
return None, None
all_metrics = [
self._get_metric(self.rows[i], self.metric[0], i)
for i in range(len(self.rows))
Expand All @@ -481,7 +485,7 @@ def get_metric2_minmax(self) -> tuple:
Returns the metric 2 min and max.
"""
if len(self.metric) < 2:
return None
return None, None
all_metrics = [
self._get_metric(self.rows[i], self.metric[1], i)
for i in range(len(self.rows))
Expand Down Expand Up @@ -1901,14 +1905,37 @@ def _gen_links(self) -> str:
)
return res

def _gen_legend_annotations(self):
""" """
def _gen_legend_annotations(self, rows: Optional[list] = None):
"""
Generates the Path
Transitions Legend.
Parameters
----------
rows: list, optional
``list`` of ``str`` used
to create the final legend.
Returns
-------
str
Path Transitions Legend.
Examples
--------
See :py:meth:`~verticapy.performance.vertica.tree`
for more information.
"""
default_params = get_default_graphviz_options()
bgcolor = default_params["legend_bgcolor"]
fontcolor = default_params["legend_fontcolor"]
fillcolor = default_params["fillcolor"]
all_legend = {}
for row in self.rows:
if hasattr(self, "rows_path_transition"):
rows = self.rows_path_transition
elif not (rows):
rows = self.rows
for row in rows:
row_tmp = row.upper()
if "OUTER ->" in row_tmp:
all_legend[
Expand Down

0 comments on commit fd1df5e

Please sign in to comment.