|
from __future__ import annotations |
|
|
|
from dataclasses import dataclass |
|
from typing import Any |
|
|
|
import wandb |
|
|
|
|
|
@dataclass |
|
class CustomChartSpec: |
|
spec_name: str |
|
fields: dict[str, Any] |
|
string_fields: dict[str, Any] |
|
key: str = "" |
|
panel_type: str = "Vega2" |
|
split_table: bool = False |
|
|
|
@property |
|
def table_key(self) -> str: |
|
if not self.key: |
|
raise wandb.Error("Key for the custom chart spec is not set.") |
|
if self.split_table: |
|
return f"Custom Chart Tables/{self.key}_table" |
|
return f"{self.key}_table" |
|
|
|
@property |
|
def config_value(self) -> dict[str, Any]: |
|
return { |
|
"panel_type": self.panel_type, |
|
"panel_config": { |
|
"panelDefId": self.spec_name, |
|
"fieldSettings": self.fields, |
|
"stringSettings": self.string_fields, |
|
"transform": {"name": "tableWithLeafColNames"}, |
|
"userQuery": { |
|
"queryFields": [ |
|
{ |
|
"name": "runSets", |
|
"args": [{"name": "runSets", "value": "${runSets}"}], |
|
"fields": [ |
|
{"name": "id", "fields": []}, |
|
{"name": "name", "fields": []}, |
|
{"name": "_defaultColorIndex", "fields": []}, |
|
{ |
|
"name": "summaryTable", |
|
"args": [ |
|
{ |
|
"name": "tableKey", |
|
"value": self.table_key, |
|
} |
|
], |
|
"fields": [], |
|
}, |
|
], |
|
} |
|
], |
|
}, |
|
}, |
|
} |
|
|
|
@property |
|
def config_key(self) -> tuple[str, str, str]: |
|
return ("_wandb", "visualize", self.key) |
|
|
|
|
|
@dataclass |
|
class CustomChart: |
|
table: wandb.Table |
|
spec: CustomChartSpec |
|
|
|
def set_key(self, key: str): |
|
"""Sets the key for the spec and updates dependent configurations.""" |
|
self.spec.key = key |
|
|
|
|
|
def plot_table( |
|
vega_spec_name: str, |
|
data_table: wandb.Table, |
|
fields: dict[str, Any], |
|
string_fields: dict[str, Any] | None = None, |
|
split_table: bool = False, |
|
) -> CustomChart: |
|
"""Creates a custom charts using a Vega-Lite specification and a `wandb.Table`. |
|
|
|
This function creates a custom chart based on a Vega-Lite specification and |
|
a data table represented by a `wandb.Table` object. The specification needs |
|
to be predefined and stored in the W&B backend. The function returns a custom |
|
chart object that can be logged to W&B using `wandb.log()`. |
|
|
|
Args: |
|
vega_spec_name (str): The name or identifier of the Vega-Lite spec |
|
that defines the visualization structure. |
|
data_table (wandb.Table): A `wandb.Table` object containing the data to be |
|
visualized. |
|
fields (dict[str, Any]): A mapping between the fields in the Vega-Lite spec and the |
|
corresponding columns in the data table to be visualized. |
|
string_fields (dict[str, Any] | None): A dictionary for providing values for any string constants |
|
required by the custom visualization. |
|
split_table (bool): Whether the table should be split into a separate section |
|
in the W&B UI. If `True`, the table will be displayed in a section named |
|
"Custom Chart Tables". Default is `False`. |
|
|
|
Returns: |
|
CustomChart: A custom chart object that can be logged to W&B. To log the |
|
chart, pass it to `wandb.log()`. |
|
|
|
Raises: |
|
wandb.Error: If `data_table` is not a `wandb.Table` object. |
|
""" |
|
|
|
if not isinstance(data_table, wandb.Table): |
|
raise wandb.Error( |
|
f"Expected `data_table` to be `wandb.Table` type, instead got {type(data_table).__name__}" |
|
) |
|
|
|
return CustomChart( |
|
table=data_table, |
|
spec=CustomChartSpec( |
|
spec_name=vega_spec_name, |
|
fields=fields, |
|
string_fields=string_fields or {}, |
|
split_table=split_table, |
|
), |
|
) |
|
|