Build Views and Panels with the Python SDK¶
You can build dashboard views and manage code panels from Python instead of in the Comet UI. This is useful for giving many projects the same layout, keeping a dashboard's definition in version control, or backing up and copying panels.
| To do this | Use |
|---|---|
| Lay out charts, sections, filters and table columns | comet_ml.views with API.create_view or APIExperiment.create_view |
| Change a saved view in place | API.update_view or APIExperiment.update_view |
| Remove panels from a saved view (coming soon) | comet_ml.views.remove_panels, then update_view |
| Set or clear a project's default view (coming soon) | API.set_default_view, API.unset_default_view |
| List, download and upload code panels | API.get_code_panels, get_code_panel, get_code_panel_source, download_code_panel_zip, upload_code_panel_zip, upload_code_panel |
| Delete code panels (coming soon) | API.delete_code_panel |
For every argument of these functions, see the comet_ml.views reference, the API reference and the APIExperiment reference.
Note
A Comet installation may not have Python panels turned on. If they are not enabled, ask your administrator.
Build a project view¶
comet_ml.views builds a View without making any network calls. Pass the result to API.create_view to save it as a project dashboard:
import comet_ml
from comet_ml.views import Section, build_view, line_panel, scalar_panel
view = build_view(
"Training Overview",
sections=[
Section(
"At a glance",
[
scalar_panel("accuracy", aggregation="max"),
scalar_panel("loss", aggregation="min"),
],
columns=2,
),
Section(
"Curves",
[
line_panel(["loss", "val_loss"], name="Loss", smoothing=0.6),
line_panel(["accuracy", "val_accuracy"], name="Accuracy"),
],
columns=2,
),
],
)
comet_ml.API().create_view("my-workspace", "my-project", view)
The new view appears in the view selector at the top of the Project Panels page.
Panels¶
Each panel function returns one panel with a new, unique chart id. Build a new view for each project or experiment rather than reusing one.
| Function | Produces |
|---|---|
line_panel | A line chart; metric can be a list of metrics to overlay |
bar_panel | A bar chart, box plot or violin plot, one bar per experiment |
scatter_panel | A 2D or 3D scatter chart, one point per experiment |
parallel_panel | A parallel coordinates chart for a hyperparameter sweep |
scalar_panel | A scalar chart: a single number |
image_panel | An image panel across experiments |
data_panel | A data panel from a logged table |
javascript_panel | A JavaScript panel whose code is stored in the view (coming soon) |
python_panel | A Python panel |
custom_panel | A Panel library panel that is already on a dashboard |
legend_key() builds one entry of a chart's legend, so you can color a chart by experiment name, tags or a hyperparameter.
Options with a fixed set of values, such as aggregation, outliers or plot_type, are checked, because Comet ignores a value it doesn't recognize without reporting an error. precision is a number of decimal places.
Note
custom_panel refers to a Panel library panel that is already on a dashboard: read its instance id with get_views() or from the panel's URL in the UI. Placing a library panel on a dashboard for the first time can only be done in the UI.
JavaScript panels¶
Coming soon
JavaScript panels whose code is stored in the view are coming soon to the Comet UI. Until then, a view saved with a javascript_panel won't show the panel.
A javascript_panel keeps its code, HTML, CSS and resources in the view. The code defines a Comet.Panel subclass, which must be named MyPanel, and this.plot({data, layout}) draws a Plotly figure the same way the built-in charts do. Scatter, bar, box, violin and parcoords traces are supported.
from comet_ml.views import Section, build_view, javascript_panel
code = """
class MyPanel extends Comet.Panel {
async draw(experimentKeys, projectId) {
const results = await this.api.experimentMetricsForChart(experimentKeys, ['loss']);
const data = Object.entries(results).flatMap(([key, r]) =>
r.metrics.map(m => ({
type: 'scatter', mode: 'lines', name: r.experimentName || key,
x: m.steps, y: m.values, line: { color: this.getColor(key) }
}))
);
this.plot({ data, layout: {} });
}
}
"""
view = build_view("Loss", sections=[Section("Custom", [javascript_panel(code, name="Loss")])])
The panel code can use everything in the JavaScript SDK.
Python panels¶
A Python panel runs its code on Comet's servers and shows its output with comet_ml.ui. python_panel takes the panel's code in one of three ways:
python_panel(code=...): the code itself, stored in the view.python_panel(template_id): a panel in the workspace's Panel library, such as one uploaded withAPI.upload_code_panel.create_viewandupdate_viewcopy the panel's code into the view when they save it, and raiseValueErrorif the Panel library has no panel with that id.python_panel(template_id, revision_id): a Python panel made in the UI, with the ids read from a view returned byget_views().
To write the code directly into the view:
import comet_ml
from comet_ml.views import Section, build_view, python_panel
code = """
from comet_ml import API, ui
api = API()
experiments = api.get_panel_experiments()
ui.display(f"{len(experiments)} experiments in this view")
"""
view = build_view(
"Summary",
sections=[Section("Python", [python_panel(code=code, name="Experiment count")])],
)
comet_ml.API().create_view("my-workspace", "my-project", view)
To keep the panel in the Panel library as well, upload it and pass its id:
api = comet_ml.API()
result = api.upload_code_panel(
"my-workspace", "Experiment count", code, description="Counts the experiments"
)
view = build_view(
"Summary",
sections=[Section("Python", [python_panel(result["templateId"], name="Experiment count")])],
)
api.create_view("my-workspace", "my-project", view)
The view keeps the code it was saved with. If you later upload new code for the panel, save the view again with update_view to pick it up; see Manage code panels. For what a Python panel's code can do, see Python Panel and the Python Panel examples.
Sections¶
A Section is a titled group of panels that can be collapsed. columns is the number of panels per row: 1, 2 or 3. Section works out each panel's position. height is the row height in grid units: 1, 2 or 3.
from comet_ml.views import Section, data_panel, image_panel
section = Section("Media & tables", columns=2, height=2, expanded=False)
section.add(image_panel(["prediction-grid.png"]), data_panel("per_class_metrics.csv"))
add() returns the section, so you can chain calls.
Filters, table columns and settings¶
build_view also takes:
filters: a saved filter built withquery_state(),rule(),all_of()andany_of().table: the experiment table's columns and sorting, built withtable_state().config: settings for the whole view, such as x-axis, smoothing and sampling, built withglobal_config().auto_generate=True: Comet adds panels for newly logged metrics below your sections.personal=True: the view is visible only to you.
from comet_ml.views import all_of, any_of, build_view, global_config, query_state, rule, table_state
view = build_view(
"Successful runs",
sections=[...],
# accuracy > 0.9 OR loss < 0.1
filters=query_state(
any_of(
all_of(rule("accuracy", "greater", 0.9)),
all_of(rule("loss", "less", 0.1)),
)
),
table=table_state(
columns=["Name", "experimentTags", "learning_rate", "accuracy", "duration"],
sort_by="accuracy",
page_size=50,
),
config=global_config(x_axis="step", smoothing=0.3, sample_size=500),
)
global_config applies to every panel except those created with locked=True, which keep their own axis and smoothing settings. Experiment views take the same config, so you can build one global_config and pass it to both builders.
Build an experiment view¶
To lay out a single experiment's page, pass the same sections to build_experiment_view and save the result with APIExperiment.create_view:
import comet_ml
from comet_ml.views import Section, build_experiment_view, global_config, line_panel
experiment = comet_ml.API().get_experiments("my-workspace", "my-project")[0]
view = build_experiment_view(
"Run layout",
sections=[Section("Curves", [line_panel(["loss", "val_loss"])], columns=2)],
config=global_config(smoothing=0.4),
)
experiment.create_view(view)
Project views and experiment views store their layout differently, which is why there are two builders. create_view and update_view raise ValueError if given a view built for the other kind. Don't set experiment_key yourself: APIExperiment.create_view sets it.
Inspect a view¶
describe_view prints an outline of a view's sections, panels and filters. Use it to see what get_views() returned before copying or changing a view:
import comet_ml
from comet_ml.views import describe_view
for view in comet_ml.API().get_views("my-workspace", "my-project"):
print(describe_view(view))
Update a view in place¶
create_view always adds a new view. If the name is already taken, it raises comet_ml.exceptions.ViewNameTakenError, which you can also catch as a ValueError. To replace a saved view, copy its template_id and call update_view, which raises ValueError if no view has that id:
import comet_ml
from comet_ml.views import Section, build_view, scalar_panel
api = comet_ml.API()
existing = next(
v for v in api.get_views("my-workspace", "my-project") if v.name == "Training Overview"
)
view = build_view("Training Overview", [Section("At a glance", [scalar_panel("loss")])])
view.template_id = existing.template_id
api.update_view("my-workspace", "my-project", view)
APIExperiment.update_view(view) does the same for an experiment view. The new layout replaces the saved one completely.
Remove panels from a view¶
Coming soon
remove_panels is coming soon in a future release of the Python SDK.
comet_ml.views.remove_panels returns a copy of a view without the panels that match every argument you give: chart_id, name, instance_id or template_id. name matches a panel's name or, for a panel added from the Panel library in the UI, its instance name. Two panels can have the same name; describe_view shows each panel's chart_id, which is unique within a view. remove_panels raises ValueError if no panel matches. Save the result with update_view:
import comet_ml
from comet_ml.views import remove_panels
api = comet_ml.API()
view = next(
v for v in api.get_views("my-workspace", "my-project") if v.name == "Training Overview"
)
api.update_view("my-workspace", "my-project", remove_panels(view, name="Loss"))
Set the default view¶
Coming soon
set_default_view and unset_default_view are coming soon in a future release of the Python SDK and Comet server.
A project opens on its default view. API.set_default_view makes a project view the default for everyone in the project, or with scope="personal", only for you. Your personal default takes precedence over the project default. It takes a view from get_views() or create_view(), or the view's template_id. Experiment views can't be a project's default.
import comet_ml
api = comet_ml.API()
view = next(
v for v in api.get_views("my-workspace", "my-project") if v.name == "Training Overview"
)
api.set_default_view("my-workspace", "my-project", view)
api.set_default_view("my-workspace", "my-project", view, scope="personal")
API.unset_default_view(workspace, project_name, scope="project") clears a default. With no project default, the project opens on its auto-generated view. get_views() shows the current defaults in each view's project_default and project_personal_default.
Manage code panels¶
The API class can list, download and upload the Python and JavaScript panels in a workspace's Panel library:
get_code_panels(workspace): every code panel in a workspace, with itstemplateId,templateName,owner,scopeType,revisionIdandcreatedAt.get_code_panel(panel_id)andget_code_panel_source(panel_id): a panel's full data, or only its code.download_code_panel_zip(panel_id, filename=None): saves a panel as a zip file, by defaultpanel-PANEL-ID.zip, and returns the path.upload_code_panel_zip(workspace, filename, template_id=None): uploads a panel zip file.upload_code_panel(workspace, panel_name, code, template_id=None, description=None): uploads Python code as a panel, with an optional description for the Panel library.delete_code_panel(panel_id)(coming soon): deletes a panel from the Panel library, with all of its code revisions. Python panels saved withpython_panelhold a copy of the code and keep working. Views where the panel was added from the Panel library in the UI still list it, and it shows as broken until you remove it withremove_panels.
With template_id, both upload methods overwrite that panel instead of creating a new one. When upload_code_panel overwrites a panel, leaving description out keeps the panel's current description, and description="" clears it:
import comet_ml
api = comet_ml.API()
result = api.upload_code_panel("my-workspace", "Hello", "print('hello world')")
panel_id = result["templateId"]
# Later, replace the code
api.upload_code_panel("my-workspace", "Hello", "print('updated')", template_id=panel_id)
Note
After a panel is updated in place, refresh the browser to see the new code in the Comet UI. Views that show the panel through python_panel keep the code they were saved with until you save them again with update_view.
Things to know¶
- A panel for a metric the project never logged is empty, not an error. When applying one layout to many projects, read each project's metric names first and build only the panels that will have data.
- Copying a view between projects or workspaces:
create_viewremoves the view's ids for you. Experiment keys inside an individual chart's settings are not changed, so a panel pinned to a specific experiment needs fixing by hand. - "Unsaved Changes" views are the UI's per-user working copy of a project's view. They appear in
get_views()results; skip them when copying views. - Views can't be deleted from the SDK. Delete them in the UI.
Learn more¶
- Python SDK:
comet_ml.views - Python SDK: View
- Python SDK: API
- Python SDK: APIExperiment
- Project Panels page