mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
@@ -1,13 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from datetime import date, datetime
|
||||
from typing import TYPE_CHECKING, Dict, Iterable
|
||||
|
||||
from funcy import lmap
|
||||
|
||||
from dvc.cli import completion
|
||||
from dvc.cli.command import CmdBase
|
||||
from dvc.cli.utils import append_doc_link
|
||||
from dvc.commands.metrics import DEFAULT_PRECISION
|
||||
@@ -59,7 +57,7 @@ def baseline_styler(typ):
|
||||
return {"style": "bold"} if typ == "baseline" else {}
|
||||
|
||||
|
||||
def show_experiments( # noqa: C901, PLR0912
|
||||
def show_experiments( # noqa: C901
|
||||
td: "TabularData",
|
||||
headers: Dict[str, Iterable[str]],
|
||||
keep=None,
|
||||
@@ -67,7 +65,6 @@ def show_experiments( # noqa: C901, PLR0912
|
||||
pager=True,
|
||||
csv=False,
|
||||
markdown=False,
|
||||
pcp=False,
|
||||
**kwargs,
|
||||
):
|
||||
if keep:
|
||||
@@ -110,51 +107,23 @@ def show_experiments( # noqa: C901, PLR0912
|
||||
}
|
||||
)
|
||||
|
||||
if kwargs.get("only_changed", False) or pcp:
|
||||
if kwargs.get("only_changed", False):
|
||||
td.drop_duplicates("cols", ignore_empty=False)
|
||||
|
||||
cols_to_drop = set()
|
||||
if drop is not None:
|
||||
cols_to_drop = {col for col in td.keys() if re.match(drop, col)} # noqa: SIM118
|
||||
if pcp:
|
||||
cols_to_drop.add("Created")
|
||||
td.drop(*cols_to_drop)
|
||||
|
||||
if pcp:
|
||||
subset = {x for x in td.keys() if x != "Experiment"} # noqa: SIM118
|
||||
td.dropna(
|
||||
"rows",
|
||||
how="all",
|
||||
subset=subset,
|
||||
)
|
||||
td.drop_duplicates("rows", subset=subset)
|
||||
if "Experiment" in td:
|
||||
td.column("Experiment")[:] = [
|
||||
# remove tree characters
|
||||
str(x).encode("ascii", "ignore").strip().decode()
|
||||
for x in td.column("Experiment")
|
||||
]
|
||||
out = kwargs.get("out") or "dvc_plots"
|
||||
output_file = os.path.join(out, "index.html")
|
||||
ui.write(
|
||||
td.to_parallel_coordinates(
|
||||
output_path=os.path.abspath(output_file),
|
||||
color_by=kwargs.get("sort_by") or "Experiment",
|
||||
)
|
||||
)
|
||||
if kwargs.get("open"):
|
||||
return ui.open_browser(output_file)
|
||||
|
||||
else:
|
||||
td.render(
|
||||
pager=pager,
|
||||
borders="horizontals",
|
||||
rich_table=True,
|
||||
header_styles=styles,
|
||||
row_styles=row_styles,
|
||||
csv=csv,
|
||||
markdown=markdown,
|
||||
)
|
||||
td.render(
|
||||
pager=pager,
|
||||
borders="horizontals",
|
||||
rich_table=True,
|
||||
header_styles=styles,
|
||||
row_styles=row_styles,
|
||||
csv=csv,
|
||||
markdown=markdown,
|
||||
)
|
||||
|
||||
|
||||
def _normalize_headers(names, count):
|
||||
@@ -221,9 +190,6 @@ class CmdExperimentsShow(CmdBase):
|
||||
csv=self.args.csv,
|
||||
markdown=self.args.markdown,
|
||||
only_changed=self.args.only_changed,
|
||||
pcp=self.args.pcp,
|
||||
out=self.args.out,
|
||||
open=self.args.open,
|
||||
)
|
||||
return 0
|
||||
|
||||
@@ -342,27 +308,6 @@ def add_parser(experiments_subparsers, parent_parser):
|
||||
),
|
||||
metavar="<n>",
|
||||
)
|
||||
experiments_show_parser.add_argument(
|
||||
"--parallel-coordinates-plot",
|
||||
"--pcp",
|
||||
dest="pcp",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Generate a Parallel Coordinates Plot from the tabulated output.",
|
||||
)
|
||||
experiments_show_parser.add_argument(
|
||||
"-o",
|
||||
"--out",
|
||||
default=None,
|
||||
help="Destination folder to save the Parallel Coordinates Plot to",
|
||||
metavar="<path>",
|
||||
).complete = completion.DIR
|
||||
experiments_show_parser.add_argument(
|
||||
"--open",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Open the Parallel Coordinates Plot directly in the browser.",
|
||||
)
|
||||
experiments_show_parser.add_argument(
|
||||
"--no-fetch",
|
||||
dest="fetch_running",
|
||||
|
||||
@@ -22,7 +22,6 @@ from typing import (
|
||||
from funcy import reraise
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from dvc.types import StrPath
|
||||
from dvc.ui.table import CellT
|
||||
|
||||
|
||||
@@ -161,24 +160,6 @@ class TabularData(MutableSequence[Sequence["CellT"]]):
|
||||
writer.writerow(row)
|
||||
return buff.getvalue()
|
||||
|
||||
def to_parallel_coordinates(
|
||||
self, output_path: "StrPath", color_by: Optional[str] = None
|
||||
) -> "StrPath":
|
||||
from dvc_render.html import render_html
|
||||
from dvc_render.plotly import ParallelCoordinatesRenderer
|
||||
|
||||
render_html(
|
||||
renderers=[
|
||||
ParallelCoordinatesRenderer(
|
||||
self.as_dict(),
|
||||
color_by=color_by,
|
||||
fill_value=self._fill_value,
|
||||
)
|
||||
],
|
||||
output_file=output_path,
|
||||
)
|
||||
return output_path
|
||||
|
||||
def add_column(self, name: str) -> None:
|
||||
self._columns[name] = Column([self._fill_value] * len(self))
|
||||
self._keys.append(name)
|
||||
|
||||
@@ -551,85 +551,6 @@ def test_show_only_changed(tmp_dir, dvc, scm, capsys, copy_script):
|
||||
assert "metrics.yaml:goobar" in cap.out
|
||||
|
||||
|
||||
def test_show_parallel_coordinates(tmp_dir, dvc, scm, mocker, capsys, copy_script):
|
||||
from dvc.commands.experiments import show
|
||||
|
||||
webbroser_open = mocker.patch("webbrowser.open")
|
||||
show_experiments = mocker.spy(show, "show_experiments")
|
||||
|
||||
params_file = tmp_dir / "params.yaml"
|
||||
params_data = {
|
||||
"foo": 1,
|
||||
"bar": 1,
|
||||
}
|
||||
(tmp_dir / params_file).dump(params_data)
|
||||
|
||||
dvc.run(
|
||||
cmd="python copy.py params.yaml metrics.yaml",
|
||||
metrics_no_cache=["metrics.yaml"],
|
||||
params=["foo", "bar"],
|
||||
name="copy-file",
|
||||
deps=["copy.py"],
|
||||
)
|
||||
scm.add(
|
||||
[
|
||||
"dvc.yaml",
|
||||
"dvc.lock",
|
||||
"copy.py",
|
||||
"params.yaml",
|
||||
"metrics.yaml",
|
||||
".gitignore",
|
||||
]
|
||||
)
|
||||
scm.commit("init")
|
||||
|
||||
dvc.experiments.run(params=["foo=2"])
|
||||
|
||||
assert main(["exp", "show", "--pcp"]) == 0
|
||||
kwargs = show_experiments.call_args[1]
|
||||
|
||||
html_text = (tmp_dir / "dvc_plots" / "index.html").read_text()
|
||||
assert all(rev in html_text for rev in ["workspace", "master"])
|
||||
assert "[exp-" not in html_text
|
||||
|
||||
assert '{"label": "metrics.yaml:foo", "values": [2.0, 1.0]}' in html_text
|
||||
assert '{"label": "params.yaml:foo", "values": [2.0, 1.0]}' in html_text
|
||||
assert '"line": {"color": [1, 0]' in html_text
|
||||
assert '"label": "metrics.yaml:bar"' not in html_text
|
||||
assert '"label": "Created"' not in html_text
|
||||
|
||||
assert main(["exp", "show", "--pcp", "--sort-by", "metrics.yaml:foo"]) == 0
|
||||
kwargs = show_experiments.call_args[1]
|
||||
|
||||
html_text = (tmp_dir / "dvc_plots" / "index.html").read_text()
|
||||
assert '"line": {"color": [2.0, 1.0]' in html_text
|
||||
|
||||
assert main(["exp", "show", "--pcp", "--out", "experiments"]) == 0
|
||||
kwargs = show_experiments.call_args[1]
|
||||
|
||||
assert kwargs["out"] == "experiments"
|
||||
assert (tmp_dir / "experiments" / "index.html").exists()
|
||||
|
||||
assert main(["exp", "show", "--pcp", "--open"]) == 0
|
||||
|
||||
webbroser_open.assert_called()
|
||||
|
||||
params_data = {"foo": 1, "bar": 1, "foobar": 2}
|
||||
(tmp_dir / params_file).dump(params_data)
|
||||
assert main(["exp", "show", "--pcp"]) == 0
|
||||
html_text = (tmp_dir / "dvc_plots" / "index.html").read_text()
|
||||
assert '{"label": "foobar", "values": [2.0, null, null]}' in html_text
|
||||
|
||||
assert main(["exp", "show", "--pcp", "--drop", "foobar"]) == 0
|
||||
html_text = (tmp_dir / "dvc_plots" / "index.html").read_text()
|
||||
assert '"label": "Created"' not in html_text
|
||||
assert '"label": "foobar"' not in html_text
|
||||
|
||||
assert main(["exp", "show", "--pcp", "--drop", "Experiment"]) == 0
|
||||
html_text = (tmp_dir / "dvc_plots" / "index.html").read_text()
|
||||
assert '"label": "Experiment"' not in html_text
|
||||
|
||||
|
||||
@pytest.mark.vscode
|
||||
def test_show_outs(tmp_dir, dvc, scm, erepo_dir, copy_script):
|
||||
params_file = tmp_dir / "params.yaml"
|
||||
|
||||
@@ -374,21 +374,3 @@ def test_drop_duplicates_invalid_axis():
|
||||
|
||||
with pytest.raises(ValueError, match="Invalid 'axis' value foo."):
|
||||
td.drop_duplicates("foo")
|
||||
|
||||
|
||||
def test_to_parallel_coordinates(tmp_dir, mocker):
|
||||
(tmp_dir / "foo").mkdir()
|
||||
td = TabularData(["categorical", "scalar"])
|
||||
td.extend([["foo", "0.1"], ["bar", "2"]])
|
||||
|
||||
write = mocker.patch("dvc_render.html.render_html")
|
||||
renderer_class = mocker.patch("dvc_render.plotly.ParallelCoordinatesRenderer")
|
||||
renderer = renderer_class.return_value
|
||||
|
||||
td.to_parallel_coordinates(output_path="foo")
|
||||
|
||||
renderer_class.assert_called_with(
|
||||
td.as_dict(), color_by=None, fill_value=td._fill_value
|
||||
)
|
||||
|
||||
write.assert_called_with(renderers=[renderer], output_file="foo")
|
||||
|
||||
Reference in New Issue
Block a user