Implementation:Iterative Dvc Plots Collect
| Knowledge Sources | |
|---|---|
| Domains | Visualization, Version_Control |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
Concrete tool for iterating over Git revisions to collect plot definitions and lazy data source callables, provided by the DVC library.
Description
The Plots.collect method is the main entry point for the multi-revision plot data collection workflow in DVC. It is a generator method on the Plots class that iterates over a list of Git revisions (or the workspace), switching the repository's virtual filesystem to each revision using switch_repo from dvc.repo.experiments.brancher. For each revision, it calls _collect_definitions to gather plot specifications and _collect_data_sources to build lazy data loaders.
The companion brancher generator (from dvc.repo.brancher) provides the lower-level mechanism for iterating over Git revisions. It saves and restores the repository's filesystem state, yields the workspace first if requested, then iterates over resolved Git SHAs. Each revision triggers a filesystem switch to a GitFileSystem backed by that commit's tree, or to a LocalFileSystem for the workspace.
Together, these functions implement the pattern of collecting visualization data across repository history without modifying the working directory.
Usage
Use Plots.collect when you need to gather plot definitions and data sources across one or more revisions for rendering. This is typically called by Plots.show (single revision) or Plots.diff (multiple revisions). The returned iterator yields one dictionary per revision, which can be processed incrementally.
Code Reference
Source Location
- Repository: DVC
- File:
dvc/repo/plots/__init__.py - Lines: L74-156 (Plots.collect)
- File:
dvc/repo/brancher.py - Lines: L17-110 (brancher)
Signature
class Plots:
def collect(
self,
targets: Optional[list[str]] = None,
revs: Optional[list[str]] = None,
recursive: bool = False,
onerror: Optional[Callable] = None,
props: Optional[dict] = None,
) -> Iterator[dict]:
...
def brancher(
self,
revs=None,
all_branches=False,
all_tags=False,
all_commits=False,
all_experiments=False,
workspace=True,
commit_date: Optional[str] = None,
sha_only=False,
num=1,
) -> Iterator[str]:
...
Import
from dvc.repo.plots import Plots
from dvc.repo.brancher import brancher
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| targets | Optional[list[str]] | No | List of plot file paths or plot IDs to filter. None or empty list collects all plots. |
| revs | Optional[list[str]] | No | List of Git revision identifiers (branch names, tags, SHAs) or the special value "workspace". Defaults to ["workspace"] if None. |
| recursive | bool | No | Whether to recursively search for plot outputs within directories. Defaults to False. |
| onerror | Optional[Callable] | No | Error handler callback for graceful failure handling during definition and data collection. |
| props | Optional[dict] | No | User-provided property overrides to merge onto every collected plot definition. |
Outputs
| Name | Type | Description |
|---|---|---|
| result | Iterator[dict] | A generator yielding one dictionary per revision. Each dictionary is keyed by the revision name and contains two sub-keys: "definitions" (nested dict of config_file to plot_id to properties) and "sources" (dict of filename to {"data_source": callable, "props": dict}). The data_source callable is a functools.partial that, when invoked, reads and parses the file. |
Usage Examples
Basic Usage
from dvc.repo import Repo
from dvc.repo.plots import Plots
repo = Repo()
plots = Plots(repo)
# Collect plots from workspace only
for rev_data in plots.collect(targets=None, revs=None):
for rev_name, content in rev_data.items():
print(f"Revision: {rev_name}")
definitions = content.get("definitions", {})
sources = content.get("sources", {})
print(f" Definitions from {len(definitions)} config files")
print(f" {len(sources.get('data', {}))} data sources")
Multi-Revision Comparison
from dvc.repo import Repo
from dvc.repo.plots import Plots
repo = Repo()
plots = Plots(repo)
# Collect plots from workspace and two historical revisions
all_data = {}
for rev_data in plots.collect(
targets=["plots/metrics.csv"],
revs=["workspace", "v1.0", "v2.0"],
props={"template": "linear", "x": "epoch"},
):
all_data.update(rev_data)
# Each revision's data sources are lazy - invoke to load
for rev, content in all_data.items():
sources = content.get("sources", {}).get("data", {})
for filename, source_info in sources.items():
# This triggers actual file reading and parsing
data = source_info["data_source"]()
print(f" {rev}/{filename}: {len(data.get('data', []))} records")
Using with Plots.show
from dvc.repo import Repo
repo = Repo()
# Plots.show calls collect internally and resolves all data sources
result = repo.plots.show(
targets=["loss.csv"],
revs=["workspace", "main"],
props={"x": "step", "y": "loss"},
)
# result is a fully resolved dict with data loaded for all revisions
for rev, data in result.items():
print(f"Revision {rev}: loaded")