8000 Add support for broader stats comparison by JiriPavela · Pull Request #308 · Perfexionists/perun · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add support for broader stats comparison #308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion perun/profile/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ class StatComparisonResult(enum.Enum):
INVALID = 5


class StatComparableType(enum.Enum):
"""Specifies the type of the aggregated stats in terms of the stored values that are compared.

When aggregated stats belong to the same comparable-type, it is possible to compare them
despite them being different aggregation, e.g., SingleValue (with numeric value) and
StatisticalSummary.
"""

8000 STRING = 1
NUMERIC = 2


@dataclasses.dataclass
class ProfileStat:
"""An internal representation of a profile stat.
Expand Down Expand Up @@ -246,6 +258,12 @@ def as_table(
:return: The representative value and a table representation of the aggregation.
"""

def get_comparable_type(self) -> StatComparableType:
"""Provide the comparable-type of the aggregated stats.

:return: The comparable-type of the aggregated stats object.
"""


@dataclasses.dataclass
class SingleValue(ProfileStatAggregation):
Expand Down Expand Up @@ -273,6 +291,11 @@ def as_table(self, _: str = "") -> tuple[str | float, dict[str, str | float]]:
# There are no details of a single value to generate into a table
return self.value, {}

def get_comparable_type(self) -> StatComparableType:
if isinstance(self.value, str):
return StatComparableType.STRING
return StatComparableType.NUMERIC


@dataclasses.dataclass
class StatisticalSummary(ProfileStatAggregation):
Expand Down Expand Up @@ -342,6 +365,9 @@ def infer_auto_comparison(self, comparison: ProfileStatComparison) -> ProfileSta
def as_table(self, key: str = _DEFAULT_KEY) -> tuple[float, dict[str, float]]:
return self.get_value(key), dataclasses.asdict(self)

def get_comparable_type(self) -> StatComparableType:
return StatComparableType.NUMERIC


@dataclasses.dataclass
class StringCollection(ProfileStatAggregation):
Expand Down Expand Up @@ -423,6 +449,9 @@ def as_table(
return representative_val, {f"{idx}.": value for idx, value in enumerate(self.sequence)}
return representative_val, self.counts

def get_comparable_type(self) -> StatComparableType:
return StatComparableType.STRING


def aggregate_stats(stat: ProfileStat) -> ProfileStatAggregation:
"""A factory that constructs the proper aggregation object based on the stat value(s) type.
Expand Down Expand Up @@ -462,7 +491,7 @@ def compare_stats(
value, other_value = stat.get_value(key), other_stat.get_value(key)
# Handle auto comparison according to the aggregation type
comparison = stat.infer_auto_comparison(comparison)
if type(stat) is not type(other_stat):
if stat.get_comparable_type() != other_stat.get_comparable_type():
# Invalid comparison attempt
perun_log.warn(
f"Invalid comparison of {stat.__class__.__name__} and {other_stat.__class__.__name__}."
Expand Down
Loading
0