From cfc77a403e9487580a966669cc4be0f90d464d62 Mon Sep 17 00:00:00 2001 From: Birte Kristina Friesel Date: Fri, 9 Feb 2024 09:41:26 +0100 Subject: filter-param: support basic numeric operations and ∈ conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/cli.py | 27 +++++++++++++++++++++++---- lib/utils.py | 27 +++++++++++++++++++++------ 2 files changed, 44 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/cli.py b/lib/cli.py index fb1e722..4fd292b 100644 --- a/lib/cli.py +++ b/lib/cli.py @@ -416,8 +416,8 @@ def boxplot_param(args, model): title = None param_is_filtered = dict() if args.filter_param: - title = "filter: " + ", ".join( - map(lambda kv: f"{kv[0]}={kv[1]}", args.filter_param) + title = "filter: " + " && ".join( + map(lambda kv: f"{kv[0]} {kv[1]} {kv[2]}", args.filter_param) ) for param_name, _ in args.filter_param: param_is_filtered[param_name] = True @@ -595,9 +595,11 @@ def add_standard_arguments(parser): ) parser.add_argument( "--filter-param", - metavar="=[,=...]", + metavar="[;...]", type=str, - help="Only consider measurements where is . " + help="Only consider measurements where satisfies . " + " may be with operator being < / <= / = / >= / >, " + "or ∈[,...]. " "All other measurements (including those where it is None, that is, has not been set yet) are discarded. " "Note that this may remove entire function calls from the model.", ) @@ -668,6 +670,23 @@ def add_standard_arguments(parser): ) +def parse_filter_string(filter_string): + if "<=" in filter_string: + p, v = filter_string.split("<=") + return (p, "≤", v) + if ">=" in filter_string: + p, v = filter_string.split(">=") + return (p, "≥", v) + if "!=" in filter_string: + p, v = filter_string.split("!=") + return (p, "≠", v) + for op in ("<", ">", "≤", "≥", "=", "∈", "≠"): + if op in filter_string: + p, v = filter_string.split(op) + return (p, op, v) + raise ValueError(f"Cannot parse '{filter_string}'") + + def parse_shift_function(param_name, param_shift): if param_shift.startswith("+"): param_shift_value = float(param_shift[1:]) diff --git a/lib/utils.py b/lib/utils.py index 4282a14..989c830 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -608,14 +608,29 @@ def filter_aggregate_by_param(aggregate, parameters, parameter_filter): :param parameters: list of parameters, used to map parameter index to parameter name. parameters=['foo', ...] means 'foo' is the first parameter :param parameter_filter: [[name, value], [name, value], ...] list of parameter values to keep, all others are removed. Values refer to normalizad parameter data. """ - for param_name_and_value in parameter_filter: - param_index = parameters.index(param_name_and_value[0]) - param_value = soft_cast_int(param_name_and_value[1]) + for param_name, condition, param_value in parameter_filter: + param_index = parameters.index(param_name) + param_value = soft_cast_int(param_value) names_to_remove = set() + + if condition == "<": + condf = lambda x: x[param_index] < param_value + elif condition == "≤": + condf = lambda x: x[param_index] <= param_value + elif condition == "=": + condf = lambda x: x[param_index] == param_value + elif condition == "≠": + condf = lambda x: x[param_index] != param_value + elif condition == "≥": + condf = lambda x: x[param_index] >= param_value + elif condition == ">": + condf = lambda x: x[param_index] > param_value + elif condition == "∈": + param_values = tuple(map(soft_cast_int, param_value.split(","))) + condf = lambda x: x[param_index] in param_values + for name in aggregate.keys(): - indices_to_keep = list( - map(lambda x: x[param_index] == param_value, aggregate[name]["param"]) - ) + indices_to_keep = list(map(condf, aggregate[name]["param"])) aggregate[name]["param"] = list( map( lambda iv: iv[1], -- cgit v1.2.3