scope_profiler.plotting_scripts
Plotting utilities for visualizing profiling data using maxplotlib.
This package provides plotting functions that can export to both matplotlib
and plotly backends using maxplotlib as the unified interface. It is split
into one module per chart type; everything is re-exported here so
scope_profiler.plotting_scripts keeps behaving like a single module for
callers and tests (including attribute-level monkeypatching).
Attributes
| Name | Description |
|---|---|
DEFAULT_CMAP | No description. |
FLAME_CMAP | No description. |
plot_flame | No description. |
Functions
| Name | Description |
|---|---|
_add_pyvis_controls | Add lightweight search/focus/collapse controls to a PyVis document. |
_aggregate_gantt_intervals | Filter and optionally coalesce timeline intervals. |
_as_runs | Normalize the input, dropping result sets this rank must not draw. |
_close_matplotlib_figure | Release the figure maxplotlib keeps open after rendering. |
_display_matplotlib_figure_in_notebook | Use IPython rich display when running inside a Jupyter kernel. |
_duration_timeseries | Aggregate one region's calls over ranks into a duration-versus-time series. |
_filename_slug | Make a label safe to paste into a filename. |
_get_canvas | Get maxplotlib Canvas for plotting. |
_get_cmap_colors | Sample n_colors #rrggbb strings from a matplotlib colormap. |
_group_regions | Collapse regions matching a pattern into a single combined bar. |
_hover_region | Pick the region object whose summary matches what is being plotted. |
_hover_summary | Render a region's own get_summary() as Plotly hover text. |
_hover_value | Format one get_summary() entry for the hover box. |
_normalize_ranks | No description. |
_panel_gridspec | Reserve figure margins for tick labels, axis labels and titles. |
_prepare_gantt_data | No description. |
_region_color_map | Assign each region name a stable color from a canonical sorted order. |
_region_summary | A region's get_summary(), minus what a broken call graph withholds. |
_render | Save and/or display a canvas. |
_save_matplotlib_figure | Save a materialized Matplotlib figure using canvas-level DPI if present. |
_set_xticks | Set x ticks, returning whether optional tick-label kwargs were accepted. |
_show_matplotlib_figure | Display a Matplotlib figure in notebooks and regular Python sessions. |
_stacked_segments | Split each bar's inclusive time into self time plus its direct children. |
_to_hex | Convert a matplotlib color (e.g. an RGBA tuple) to a #rrggbb string. |
_unique_labels | No description. |
_write_csv | Write rows of plotting data to a plain-text CSV file. |
_write_json | Write the exact data behind a plot to a JSON file. |
_write_parquet | Write the same rows writecsv would to a columnar Parquet file. |
available_likwid_metrics | List the LIKWID metric/event names available for :func:plot_likwid. |
available_perf_event_metrics | List available raw events and valid derived perf-event ratios. |
collect_region_statistics | Collect aggregate region-duration statistics for one or more profiling files. |
collect_roofline_points | Derive one roofline point per selected LIKWID region and rank. |
plot_callgraph | Plot the explicit call graph, without using timestamps or durations. |
plot_duration_histogram | Plot each region's call-duration distribution as a frequency line. |
plot_duration_timeseries | Plot each region's call duration over wall-clock time, with a min-max band. |
plot_durations | Plot duration bar charts for one or more profiling files using maxplotlib. |
plot_flame_chart | Plot a flame chart reconstructing the call stack from region timings. |
plot_flame_graph | Plot an aggregated flame graph whose x-axis represents total time. |
plot_gantt | Plot a Gantt chart of all (or selected) regions with per-rank lanes using maxplotlib. |
plot_imbalance | Plot each region's duration statistic per rank, to surface load imbalance. |
plot_likwid | Plot one LIKWID derived metric or raw event, grouped by region and rank. |
plot_perf_events | Plot one raw perf event or derived ratio for every region and rank. |
plot_rank_heatmap | Plot total or exclusive region time as a rank-by-region heatmap. |
plot_roofline | Plot attained performance against arithmetic intensity for LIKWID regions. |
plot_scaling_efficiency | Plot parallel scaling efficiency (measured speedup / ideal speedup). |
plot_speedup | Plot scope speedup versus a chosen parallelism/metadata field using maxplotlib. |
plot_timeline_density | Plot binned region occupancy instead of individual timeline bars. |
plot_weak_scaling | Plot weak-scaling runtime versus a chosen parallelism/metadata field. |
plot_weak_scaling_efficiency | Plot weak-scaling efficiency: baseline runtime over runtime at each scale. |
write_region_statistics_json | Write aggregate region-duration statistics to a JSON file. |
Modules
callgraphCall-graph rendering (PyVis network view of explicit caller/callee edges).duration_timeseriesDuration-vs-time scatter: per-region call durations across the run.durationsDuration bar charts: per-region totals/averages, optionally stacked by caller.flameFlame chart rendering: nested call-stack frames sized by duration.ganttGantt chart rendering: per-rank timeline bars for one or more profiling runs.heatmapRank x region duration heatmap.histogramPer-region duration-distribution histograms.imbalanceRank-imbalance plots: per-region duration spread across ranks.likwidLIKWID hardware-counter bar charts.perf_eventsBar charts for built-in Linux perf-event counter totals and ratios.rooflineRoofline analysis from LIKWID FLOP-rate and memory-bandwidth metrics.scalingScaling charts: speedup, weak-scaling, and parallel-efficiency curves.statisticsRegion-duration statistics collection (JSON export, no chart rendering).timelineTimeline density heatmap: call-count intensity over time, per region.
DEFAULT_CMAPattributemodule attribute#
scope_profiler.plotting_scripts._utilsView sourceDEFAULT_CMAP = 'tab20'FLAME_CMAPattributemodule attribute#
scope_profiler.plotting_scripts.flameView sourceFLAME_CMAP = 'inferno'plot_flameattributemodule attribute#
scope_profiler.plotting_scripts.flameView sourceplot_flame = plot_flame_chart_add_pyvis_controlsfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _add_pyvis_controls(filepath: str | Path) -> NoneAdd lightweight search/focus/collapse controls to a PyVis document.
_aggregate_gantt_intervalsfunction#
scope_profiler.plotting_scripts.ganttView sourcedef _aggregate_gantt_intervals(intervals: Sequence[tuple[float, float]], *, min_duration: float = 0.0, start_time: float | None = None, end_time: float | None = None, block_size: int = 1) -> list[tuple[float, float, int]]Filter and optionally coalesce timeline intervals.
start_time/end_time are relative to the plot origin. Intervals
crossing a window boundary are clipped. Coalescing preserves event order
and reports the number of calls represented by each returned bar.
_as_runsfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _as_runs(profiling_data: ProfilingResults | Sequence[ProfilingResults]) -> list[ProfilingResults]Normalize the input, dropping result sets this rank must not draw.
Under MPI only rank 0 holds the run’s data; every other rank gets an empty,
non-root result set from finalize(return_results=True). Dropping those
here is what lets a parallel script call the plot functions and exporters
unguarded and still produce exactly one set of figures. An empty list back
therefore means “not this rank’s job” - callers return quietly - while an
empty input is a mistake and raises.
_close_matplotlib_figurefunction#
scope_profiler.plotting_scripts._utilsView sourcedef _close_matplotlib_figure(canvas, fig=None) -> NoneRelease the figure maxplotlib keeps open after rendering.
_display_matplotlib_figure_in_notebookfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _display_matplotlib_figure_in_notebook(fig) -> boolUse IPython rich display when running inside a Jupyter kernel.
_duration_timeseriesfunction#
scope_profiler.plotting_scripts.duration_timeseriesView sourcedef _duration_timeseries(region, ranks: list[int] | None, first_start_time: float) -> dict[str, np.ndarray] | NoneAggregate one region’s calls over ranks into a duration-versus-time series.
Calls are matched across ranks by call index, so point i describes the
i-th call of the region on every rank that got that far. Ranks that stopped
calling the region earlier simply drop out of the later points, which keeps
ragged call counts (e.g. a rank-dependent number of iterations) usable.
Returns None if no selected rank recorded any call.
_filename_slugfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _filename_slug(label: str) -> strMake a label safe to paste into a filename.
Labels are free text and are used to name exported files, so a perfectly
reasonable one like "128 ranks" would otherwise produce
profile_128 ranks_rank0.prof. Only the path is sanitized; the label
inside the exported document stays as the user wrote it.
_get_canvasfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _get_canvas()Get maxplotlib Canvas for plotting.
_get_cmap_colorsfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _get_cmap_colors(cmap: str, n_colors: int) -> list[str]Sample n_colors #rrggbb strings from a matplotlib colormap.
Hex strings (rather than RGBA tuples) are returned so the colors can be handed to any maxplotlib backend unchanged.
_group_regionsfunction#
scope_profiler.plotting_scripts.durationsView sourcedef _group_regions(region_names: list[str], combine_regions: dict[str, list[str] | str] | None) -> tuple[list[str], dict[str, list[str]]]Collapse regions matching a pattern into a single combined bar.
combine_regions maps a display name (e.g. "setup") to one or more
regex patterns (matched the same way as include); every region in
region_names matching one of a group’s patterns is pooled into a
single bar under that display name, in the position of its first match.
A region matching patterns from more than one group is claimed by
whichever group is listed first. Regions matching no group pass through
unchanged, one bar each.
Returns the ordered list of bar display names, plus a {display_name: [member region names]} map used to pool each bar’s underlying data.
_hover_regionfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _hover_region(region, ranks: list[int] | None, num_ranks: int | None = None)Pick the region object whose summary matches what is being plotted.
A plot restricted to a single rank should not describe itself with
statistics pooled over every rank, and MPIRegion[rank] is the same
get_summary() one level down. num_ranks is the run’s rank count,
which decides whether the title names the rank.
_hover_summaryfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _hover_summary(region, title: str | None = None, extra: Sequence[tuple[str, object]] = ()) -> strRender a region’s own get_summary() as Plotly hover text.
Both :class:~scope_profiler.region.Region (one rank) and
:class:~scope_profiler.mpi_region.MPIRegion (pooled over ranks) expose
get_summary(), so hovering shows exactly the statistics that region
object reports - there is no second, parallel definition of “the usual
information” to keep in step with it.
extra lines (the hovered call’s own start and duration, a bar’s
value, …) are placed above the summary, since they are what identifies
the point being hovered.
_hover_valuefunction#
scope_profiler.plotting_scripts._utilsView sourcedef _hover_value(key: str, value) -> strFormat one get_summary() entry for the hover box.
_normalize_ranksfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _normalize_ranks(ranks: list[int] | int | None) -> list[int] | None_panel_gridspecfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _panel_gridspec(fig_width: float, fig_height: float, label_chars: int, multi_panel: bool) -> dictReserve figure margins for tick labels, axis labels and titles.
maxplotlib renders without tight_layout, so long y-tick labels (region
names) and the x-axis label would otherwise be cut off at the figure edge.
_prepare_gantt_datafunction#
scope_profiler.plotting_scripts.ganttView sourcedef _prepare_gantt_data(profiling_data: ProfilingResults, ranks: list[int] | int | None, include: list[str] | str | None, exclude: list[str] | str | None) -> tuple[list, list[int], float]_region_color_mapfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _region_color_map(region_names, cmap: str = DEFAULT_CMAP) -> dictAssign each region name a stable color from a canonical sorted order.
_region_summaryfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _region_summary(region) -> dictA region’s get_summary(), minus what a broken call graph withholds.
get_summary() reports exclusive time, which is reconstructed from
timestamp containment and therefore unavailable on a rank whose calls
are not properly nested. That is a reason to leave one line out of a
hover box, not to fail the plot.
_renderfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _render(canvas, filepath: str | None, show: bool, backend: str, plotly_layout: dict | None = None, x_tick_rotation: float | None = None, return_fig: bool = False, matplotlib_postprocess=None, plotly_postprocess=None) -> tuple[object, object] | objectSave and/or display a canvas.
_save_matplotlib_figurefunction#
scope_profiler.plotting_scripts._utilsView sourcedef _save_matplotlib_figure(fig, canvas, filepath: str | Path) -> NoneSave a materialized Matplotlib figure using canvas-level DPI if present.
_set_xticksfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _set_xticks(canvas, ticks, labels=None, **kwargs) -> boolSet x ticks, returning whether optional tick-label kwargs were accepted.
_show_matplotlib_figurefunction#
scope_profiler.plotting_scripts._utilsView sourcedef _show_matplotlib_figure(fig) -> boolDisplay a Matplotlib figure in notebooks and regular Python sessions.
_stacked_segmentsfunction#
scope_profiler.plotting_scripts.durationsView sourcedef _stacked_segments(run: ProfilingResults, region_members: dict[str, list[str]], ranks: list[int] | None = None) -> dict[str, dict[str, float]]Split each bar’s inclusive time into self time plus its direct children.
Regions record no call graph, so the nesting is reconstructed from
timestamp containment (:func:~scope_profiler.call_stack.build_call_arrays)
- the same call graph the flame chart draws, over all the run’s regions, not just the plotted ones, since a region filtered out of the bars is still somebody’s parent.
Every call is credited to the bar its parent belongs to. A call whose
parent is in the same bar (a recursive region, or two members of one
combine_regions group nested in each other) is left in that bar’s
self time rather than becoming a segment of itself, so a bar’s segments
always sum to time spent inside it, counted once.
Returns {bar name: {segment label: total nanoseconds}}, where the
"self" segment is exclusive time and every other key is a child
region’s name - its bar name when that child is itself a plotted bar.
_to_hexfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _to_hex(color) -> strConvert a matplotlib color (e.g. an RGBA tuple) to a #rrggbb string.
_unique_labelsfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _unique_labels(labels: Sequence[str]) -> list[str]_write_csvfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _write_csv(filepath: str | Path, header: Sequence[str], rows: Sequence[Sequence]) -> NoneWrite rows of plotting data to a plain-text CSV file.
_write_jsonfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _write_json(filepath: str | Path, payload: dict, plot: str) -> NoneWrite the exact data behind a plot to a JSON file.
Every plot-data document carries the same envelope - format,
format_version and the plot kind that produced it - so a consumer
(e.g. the @scope-profiler/plotly package) can dispatch on the file
itself instead of guessing from its keys. Stamping it here rather than at
each call site is what keeps the envelope on every kind.
_write_parquetfunction#
scope_profiler.plotting_scripts._utilsView sourcedef _write_parquet(filepath: str | Path, header: Sequence[str], rows: Sequence[Sequence]) -> NoneWrite the same rows _write_csv would to a columnar Parquet file.
Same tabular shape as the CSV export, for a caller that wants a typed, columnar file to load with pandas/polars/DuckDB rather than parse a delimited text file.
available_likwid_metricsfunction#
scope_profiler.plotting_scripts.likwidView sourcedef available_likwid_metrics(profiling_data: ProfilingResults | Sequence[ProfilingResults]) -> list[str]List the LIKWID metric/event names available for :func:plot_likwid.
Union over every run, rank and region, in the order LIKWID reported them
(derived metrics first, then raw events) - so a caller who does not know
what a run measured can list the valid metric values before plotting.
available_perf_event_metricsfunction#
scope_profiler.plotting_scripts.perf_eventsView sourcedef available_perf_event_metrics(profiling_data: ProfilingResults | Sequence[ProfilingResults]) -> list[str]List available raw events and valid derived perf-event ratios.
collect_region_statisticsfunction#
scope_profiler.plotting_scripts.statisticsView sourcedef collect_region_statistics(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, labels: Sequence[str] | None = None) -> dictCollect aggregate region-duration statistics for one or more profiling files.
collect_roofline_pointsfunction#
scope_profiler.plotting_scripts.rooflineView sourcedef collect_roofline_points(profiling_data: ProfilingResults | Sequence[ProfilingResults], *, flops_metric: str | None = None, bandwidth_metric: str | None = None, ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None) -> list[dict]Derive one roofline point per selected LIKWID region and rank.
flops_metric and bandwidth_metric select exact LIKWID derived
metric names. When omitted, the first names containing FLOP/s and
bandwidth respectively are selected for each region. Supplying exact
names is recommended when a group offers both single- and double-precision
FLOP rates.
plot_callgraphfunction#
scope_profiler.plotting_scripts.callgraphView sourcedef plot_callgraph(profiling_data: ProfilingResults, rank: int = 0, include=None, exclude=None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False, compact: bool = False, fluid: bool = False) -> object | NonePlot the explicit call graph, without using timestamps or durations.
When compact is true, all invocations of a region are represented by
one node named after that region. Edges then describe distinct
caller/callee region relationships rather than individual call IDs.
fluid applies a deterministic force-directed layout to the compact
graph, similar to an Obsidian-style node graph.
plot_duration_histogramfunction#
scope_profiler.plotting_scripts.histogramView sourcedef plot_duration_histogram(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, bins: int = 30, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, log_scale: bool = False, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib') -> NonePlot each region’s call-duration distribution as a frequency line.
One panel per file, one line per region, giving the count of calls
falling in each duration bin - so a region whose calls are mostly fast
with an occasional slow outlier shows up as a peak with a long tail,
something the mean/min/max in :func:plot_durations cannot distinguish
from a uniformly slower region.
Parameters
bins : int Number of histogram bins spanning each file’s observed duration range (default: 30). All regions in a panel share the same bin edges, so the curves are directly comparable. backend : str Backend to use for rendering: “matplotlib” (default) or “plotly”.
plot_duration_timeseriesfunction#
scope_profiler.plotting_scripts.duration_timeseriesView sourcedef plot_duration_timeseries(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, log_scale: bool = False, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> NonePlot each region’s call duration over wall-clock time, with a min-max band.
One line per region tracks the mean duration over the ranks that recorded each call, shaded between the minimum and maximum duration seen across those ranks, so rank imbalance shows up as a widening band.
Parameters
backend : str
Backend to use for rendering: “matplotlib” (default) or “plotly”.
return_fig : bool
Return the rendered figure instead of the default None. Matplotlib
returns (fig, axes); Plotly returns its figure object.
plot_durationsfunction#
scope_profiler.plotting_scripts.durationsView sourcedef plot_durations(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, labels: Sequence[str] | None = None, metric: str = 'total', metrics: Sequence[str] | None = None, sort_by: str | None = None, top_n: int | None = None, combine_regions: dict[str, list[str] | str] | None = None, stack_children: bool = False, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, log_scale: bool = False, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> list[str] | list[object] | objectPlot duration bar charts for one or more profiling files using maxplotlib.
Parameters
combine_regions : dict[str, list[str] | str], optional
Merge several regions into a single bar, e.g. {"setup": ["setup: .*"]} combines every setup: ... region into one bar named
“setup”, pooling their calls the same way sort_by and the other
duration statistics pool a single region’s calls. Each value is one
or more regex patterns (matched like include); a region matching
several groups is claimed by whichever group is listed first.
metric : str
Duration metric to render (avg, min, max, total,
first or last). first/last are the durations of the
chronologically first and last call, which show how much of a
region’s cost is one-off warmup rather than steady state.
metrics : Sequence[str], optional
Render several metrics instead of one. Each gets its own figure —
filepath is suffixed with the metric name, as it always was for
multiple metrics - but a single data_filepath holds them all,
with the metric named per row, so one export can back a chart whose
metric the viewer switches. Overrides metric when given.
stack_children : bool
Split each bar into the region’s own (exclusive) time plus one
segment per region called directly from it, stacked on top of each
other, so a bar shows where its time went instead of only how much
there was. The nesting comes from timestamp containment, the same
reconstruction the flame chart uses, over every region in the run —
a child that is filtered out of the bars still gets its own segment.
Only total and avg decompose this way; min/max are
rejected. Colors then identify segments rather than runs, so with
several runs the bars are still grouped per region in run order but
the legend names the segments.
backend : str
Backend to use for rendering: “matplotlib” (default) or “plotly”.
return_fig : bool
Return the rendered figure instead of the saved filepath list.
Returns
list[str]
List of filepaths that were written (empty if filepath is None).
With return_fig, the rendered figure, or the list of figures
when several metrics were requested.
plot_flame_chartfunction#
scope_profiler.plotting_scripts.flameView sourcedef plot_flame_chart(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = FLAME_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot a flame chart reconstructing the call stack from region timings.
Parameters
backend : str
Backend to use for rendering: “matplotlib” (default) or “plotly”.
return_fig : bool
Return the rendered figure instead of the default None. Matplotlib
returns (fig, axes); Plotly returns its figure object.
plot_flame_graphfunction#
scope_profiler.plotting_scripts.flameView sourcedef plot_flame_graph(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = FLAME_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot an aggregated flame graph whose x-axis represents total time.
plot_ganttfunction#
scope_profiler.plotting_scripts.ganttView sourcedef plot_gantt(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False, min_duration: float = 0.0, start_time: float | None = None, end_time: float | None = None, aggregate_calls: int = 1, collapse_depth: int | None = None) -> object | NonePlot a Gantt chart of all (or selected) regions with per-rank lanes using maxplotlib.
Parameters
backend : str
Backend to use for rendering: “matplotlib” (default) or “plotly”.
return_fig : bool
Return the rendered figure instead of the default None. Matplotlib
returns (fig, axes); Plotly returns its figure object.
plot_imbalancefunction#
scope_profiler.plotting_scripts.imbalanceView sourcedef plot_imbalance(profiling_data: ProfilingResults | Sequence[ProfilingResults], metric: str = 'total', ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, log_scale: bool = False, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib') -> NonePlot each region’s duration statistic per rank, to surface load imbalance.
One point per (region, rank), connected by a line in rank order, with a
dashed horizontal line at the mean over ranks - so a straggler rank shows
up as a point sitting well off its region’s line. This is a per-rank view
of the same statistics :func:plot_durations aggregates across ranks.
Parameters
metric : str
Which per-call duration statistic to plot per rank; one of
"avg", "min", "max", "total" (default: "total",
the total time a rank spent in the region).
backend : str
Backend to use for rendering: “matplotlib” (default) or “plotly”.
plot_likwidfunction#
scope_profiler.plotting_scripts.likwidView sourcedef plot_likwid(profiling_data: ProfilingResults | Sequence[ProfilingResults], metric: str, ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, labels: Sequence[str] | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, log_scale: bool = False, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib') -> NonePlot one LIKWID derived metric or raw event, grouped by region and rank.
LIKWID counters are otherwise only visible as text tables
(:func:~scope_profiler.summary.print_likwid_tables); this gives the same
numbers a bar chart, one group of bars per region and one bar per rank, so
a metric like memory bandwidth or CPI can be compared across regions (or
across files, for a single rank) the same way :func:plot_durations
compares timings.
Parameters
metric : str
Name of a LIKWID derived metric (e.g. "CPI") or raw event/event
label (e.g. "CAS_COUNT_RD"). See :func:available_likwid_metrics
for the names a run actually recorded.
backend : str
Backend to use for rendering: “matplotlib” (default) or “plotly”.
plot_perf_eventsfunction#
scope_profiler.plotting_scripts.perf_eventsView sourcedef plot_perf_events(profiling_data: ProfilingResults | Sequence[ProfilingResults], metric: str = 'ipc', ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, labels: Sequence[str] | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, backend: str = 'matplotlib') -> NonePlot one raw perf event or derived ratio for every region and rank.
metric may be an event name recorded in the run, "ipc"
(instructions/cycle), or "cache-misses-per-ki". Derived metrics are
calculated from the region’s aggregated counters, not averages of call
ratios, which preserves their proper weighting.
plot_rank_heatmapfunction#
scope_profiler.plotting_scripts.heatmapView sourcedef plot_rank_heatmap(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = 'viridis', data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False, exclusive: bool = False) -> object | NonePlot total or exclusive region time as a rank-by-region heatmap.
plot_rooflinefunction#
scope_profiler.plotting_scripts.rooflineView sourcedef plot_roofline(profiling_data: ProfilingResults | Sequence[ProfilingResults], *, flops_metric: str | None = None, bandwidth_metric: str | None = None, peak_flops: float | None = None, peak_bandwidth: float | None = None, ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib') -> dictPlot attained performance against arithmetic intensity for LIKWID regions.
peak_flops (GFLOP/s) and peak_bandwidth (GB/s) should be measured
hardware ceilings for a true roofline. If either is absent, the largest
selected observation supplies that ceiling and the plot labels it
empirical; it is useful for comparing regions but must not be read as a
machine limit.
plot_scaling_efficiencyfunction#
scope_profiler.plotting_scripts.scalingView sourcedef plot_scaling_efficiency(profiling_data: ProfilingResults | Sequence[ProfilingResults], x_field: str = 'num_ranks', ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot parallel scaling efficiency (measured speedup / ideal speedup).
plot_speedupfunction#
scope_profiler.plotting_scripts.scalingView sourcedef plot_speedup(profiling_data: ProfilingResults | Sequence[ProfilingResults], x_field: str = 'num_ranks', ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot scope speedup versus a chosen parallelism/metadata field using maxplotlib.
Parameters
backend : str Backend to use for rendering: “matplotlib” (default) or “plotly”.
plot_timeline_densityfunction#
scope_profiler.plotting_scripts.timelineView sourcedef plot_timeline_density(profiling_data: ProfilingResults | Sequence[ProfilingResults], ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = 'magma', bins: int = 200, start_time: float | None = None, end_time: float | None = None, min_duration: float = 0.0, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot binned region occupancy instead of individual timeline bars.
Each cell contains the seconds of a region overlapping that time bin. This is intentionally an aggregate visualization: it remains readable when a run contains millions of short calls.
plot_weak_scalingfunction#
scope_profiler.plotting_scripts.scalingView sourcedef plot_weak_scaling(profiling_data: ProfilingResults | Sequence[ProfilingResults], x_field: str = 'num_ranks', ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot weak-scaling runtime versus a chosen parallelism/metadata field.
Runtime is normalized to the smallest scale, so ideal weak scaling is a horizontal line at 1.0. Lower values are not inherently better here: the useful signal is how closely each region stays near that line.
See :func:plot_weak_scaling_efficiency for the same data read as a
fraction of ideal instead.
plot_weak_scaling_efficiencyfunction#
scope_profiler.plotting_scripts.scalingView sourcedef plot_weak_scaling_efficiency(profiling_data: ProfilingResults | Sequence[ProfilingResults], x_field: str = 'num_ranks', ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, work_per_rank: Sequence[float] | None = None, filepath: str | None = None, show: bool = False, verbose: bool = True, cmap: str = DEFAULT_CMAP, data_filepath: str | Path | None = None, data_format: str = 'csv', backend: str = 'matplotlib', return_fig: bool = False) -> object | NonePlot weak-scaling efficiency: baseline runtime over runtime at each scale.
A weak-scaling study grows the problem with the machine, so every run does the same work per rank and ideal efficiency is a flat 1.0. A region at 0.6 on 64 ranks is spending 40% of its time on costs that only appear at that scale - communication, load imbalance, or contention.
This differs from :func:plot_scaling_efficiency, which is for a
strong-scaling study: there the problem size is fixed, so the ideal is
a speedup proportional to the rank count and efficiency divides the
measured speedup by that. Here the ideal is constant runtime, so no such
division applies - using the strong-scaling plot on weak-scaling runs
reports a near-zero efficiency that means nothing.
Parameters
work_per_rank : Sequence[float], optional Work per rank for each profiling run, in whatever unit suits the problem (grid cells, particles, unknowns). Only the caller can know this - it is a property of the problem, not of the profile - so it is optional, but when given it is checked: the runs must agree, and a mismatch raises rather than plotting an efficiency that silently compares runs doing different amounts of work. The value is recorded in the exported plot data.
write_region_statistics_jsonfunction#
scope_profiler.plotting_scripts.statisticsView sourcedef write_region_statistics_json(profiling_data: ProfilingResults | Sequence[ProfilingResults], filepath: str | Path, ranks: list[int] | int | None = None, include: list[str] | str | None = None, exclude: list[str] | str | None = None, labels: Sequence[str] | None = None) -> dictWrite aggregate region-duration statistics to a JSON file.