Skip to content

Commit

Permalink
exp show: Add --drop and --keep args
Browse files Browse the repository at this point in the history
Removed `--include-metrics` / `--include-params` and
`--exclude-metrics` / `--exclude-params`.

Removed `--no-timestamp` . Can be done by `--drop Created`.

`--drop` and `--keep` operate directly on the table columns.

`--keep` does not perform any filtering. It's only used
to specify columns to keep despite the other filtering.

For example `--only-changed --keep foo` will prevent
`foo` from being removed by `--only-changed`.

Another example, `--drop train.* --keep train.dropout`
will remove all columns matching `train.*` except for
`train.dropout`.

Closes #7079
Pre-requisite for #6434
Pre-requisite for #7080
  • Loading branch information
daavoo committed Dec 23, 2021
1 parent 3964f3d commit 11c1e12
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 246 deletions.
159 changes: 28 additions & 131 deletions dvc/command/experiments/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
import logging
from collections import Counter, OrderedDict, defaultdict
from datetime import date, datetime
from fnmatch import fnmatch
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Iterable, Optional
from typing import TYPE_CHECKING

from funcy import lmap

Expand All @@ -27,64 +26,6 @@
logger = logging.getLogger(__name__)


def _filter_name(names, label, filter_strs):
ret = defaultdict(dict)
path_filters = defaultdict(list)

for filter_s in filter_strs:
path, _, name = filter_s.rpartition(":")
path_filters[path].append(name)

for path, filters in path_filters.items():
if path:
match_paths = [path]
else:
match_paths = names.keys()
for match_path in match_paths:
for f in filters:
matches = [
name for name in names[match_path] if fnmatch(name, f)
]
if not matches:
raise InvalidArgumentError(
f"'{f}' does not match any known {label}"
)
ret[match_path].update({match: None for match in matches})

return ret


def _filter_names(
names: Dict[str, Dict[str, None]],
label: str,
include: Optional[Iterable],
exclude: Optional[Iterable],
):
if include and exclude:
intersection = set(include) & set(exclude)
if intersection:
values = ", ".join(intersection)
raise InvalidArgumentError(
f"'{values}' specified in both --include-{label} and"
f" --exclude-{label}"
)

if include:
ret = _filter_name(names, label, include)
else:
ret = names

if exclude:
to_remove = _filter_name(names, label, exclude)
for path in to_remove:
if path in ret:
for key in to_remove[path]:
if key in ret[path]:
del ret[path][key]

return ret


def _update_names(names, items):
for name, item in items:
item = item.get("data", {})
Expand All @@ -102,18 +43,6 @@ def _collect_names(all_experiments, **kwargs):
exp = exp_data.get("data", {})
_update_names(metric_names, exp.get("metrics", {}).items())
_update_names(param_names, exp.get("params", {}).items())
metric_names = _filter_names(
metric_names,
"metrics",
kwargs.get("include_metrics"),
kwargs.get("exclude_metrics"),
)
param_names = _filter_names(
param_names,
"params",
kwargs.get("include_params"),
kwargs.get("exclude_params"),
)

return metric_names, param_names

Expand Down Expand Up @@ -307,17 +236,6 @@ def _extend_row(row, names, items, precision, fill_value=FILL_VALUE):
row.append(ui.rich_text(str(_format_field(value, precision))))


def _parse_filter_list(param_list):
ret = []
for param_str in param_list:
path, _, param_str = param_str.rpartition(":")
if path:
ret.extend(f"{path}:{param}" for param in param_str.split(","))
else:
ret.extend(param_str.split(","))
return ret


def experiments_table(
all_experiments,
headers,
Expand Down Expand Up @@ -380,27 +298,17 @@ def baseline_styler(typ):

def show_experiments(
all_experiments,
keep=None,
drop=None,
pager=True,
no_timestamp=False,
csv=False,
markdown=False,
html=False,
**kwargs,
):
from funcy.seqs import flatten as flatten_list

include_metrics = _parse_filter_list(kwargs.pop("include_metrics", []))
exclude_metrics = _parse_filter_list(kwargs.pop("exclude_metrics", []))
include_params = _parse_filter_list(kwargs.pop("include_params", []))
exclude_params = _parse_filter_list(kwargs.pop("exclude_params", []))

metric_names, param_names = _collect_names(
all_experiments,
include_metrics=include_metrics,
exclude_metrics=exclude_metrics,
include_params=include_params,
exclude_params=exclude_params,
)
metric_names, param_names = _collect_names(all_experiments)

headers = [
"Experiment",
Expand Down Expand Up @@ -431,9 +339,8 @@ def show_experiments(
kwargs.get("fill_value"),
kwargs.get("iso"),
)

if no_timestamp or html:
td.drop("Created")
if keep:
td.protect(*keep)

for col in ("State", "Executor"):
if td.is_empty(col):
Expand Down Expand Up @@ -475,9 +382,22 @@ def show_experiments(
if kwargs.get("only_changed", False) or html:
td.drop_duplicates("cols")

if drop is not None:
if html:
drop.append("Created")
td.drop(*drop)

html_args = {}
if html:
td.dropna("rows", how="all")
subset = [x for x in td.keys() if x != "Experiment"]
td.dropna(
"rows",
how="all",
subset=subset,
)
td.drop_duplicates(
"rows",
subset=subset)
td.column("Experiment")[:] = [
# remove tree characters
str(x).encode("ascii", "ignore").strip().decode()
Expand Down Expand Up @@ -553,11 +473,8 @@ def run(self):

show_experiments(
all_experiments,
include_metrics=self.args.include_metrics,
exclude_metrics=self.args.exclude_metrics,
include_params=self.args.include_params,
exclude_params=self.args.exclude_params,
no_timestamp=self.args.no_timestamp,
keep=self.args.keep,
drop=self.args.drop,
sort_by=self.args.sort_by,
sort_order=self.args.sort_order,
precision=precision,
Expand Down Expand Up @@ -620,32 +537,18 @@ def add_parser(experiments_subparsers, parent_parser):
help="Do not pipe output into a pager.",
)
experiments_show_parser.add_argument(
"--include-metrics",
"--keep",
action="append",
default=[],
help="Include the specified metrics in output table.",
metavar="<metrics_list>",
help="Always show the specified columns in output table.",
metavar="<column_list>",
)
experiments_show_parser.add_argument(
"--exclude-metrics",
"--drop",
action="append",
default=[],
help="Exclude the specified metrics from output table.",
metavar="<metrics_list>",
)
experiments_show_parser.add_argument(
"--include-params",
action="append",
default=[],
help="Include the specified params in output table.",
metavar="<params_list>",
)
experiments_show_parser.add_argument(
"--exclude-params",
action="append",
default=[],
help="Exclude the specified params from output table.",
metavar="<params_list>",
help="Remove the specified columns from output table.",
metavar="<column_list>",
)
experiments_show_parser.add_argument(
"--param-deps",
Expand All @@ -667,12 +570,6 @@ def add_parser(experiments_subparsers, parent_parser):
choices=("asc", "desc"),
default="asc",
)
experiments_show_parser.add_argument(
"--no-timestamp",
action="store_true",
default=False,
help="Do not show experiment timestamps.",
)
experiments_show_parser.add_argument(
"--sha",
action="store_true",
Expand Down
Loading

0 comments on commit 11c1e12

Please sign in to comment.