@@ -663,11 +663,12 @@ def secondary_y_coord(value: float) -> float:
663663 f"<style>{ style } </style>" ,
664664 ]
665665 if annotation :
666- # Footer metadata line below the x-axis title, right-aligned to the
667- # plot edge — the top stays legend-only (an earlier top-right placement
666+ # Header metadata line centered above the legend: the bottom rows are
667+ # reserved for the axis titles, and the earlier bottom-right footer
668+ # placement sat too close to the canvas edge (a top-right placement
668669 # collided with the centered legend at this font size).
669670 lines .append (
670- f'<text x="{ left + plot_width :.2f} " y="{ height - 6 } " text-anchor="end " font-size="11" '
671+ f'<text x="{ width / 2 :.2f} " y="18 " text-anchor="middle " font-size="11" '
671672 f'fill="#6b7280">{ escape (annotation )} </text>'
672673 )
673674 legend_entries = [("curve" , spec .metric_label ["en" ])]
@@ -680,8 +681,8 @@ def secondary_y_coord(value: float) -> float:
680681 for (css_class , label ), entry_width in zip (legend_entries , legend_widths ):
681682 lines .extend (
682683 [
683- f'<line class="{ css_class } " x1="{ legend_x :.2f} " y1="30 " x2="{ legend_x + 28 :.2f} " y2="30 "/>' ,
684- f'<text x="{ legend_x + 36 :.2f} " y="34 " font-size="13">{ escape (label )} </text>' ,
684+ f'<line class="{ css_class } " x1="{ legend_x :.2f} " y1="34 " x2="{ legend_x + 28 :.2f} " y2="34 "/>' ,
685+ f'<text x="{ legend_x + 36 :.2f} " y="38 " font-size="13">{ escape (label )} </text>' ,
685686 ]
686687 )
687688 legend_x += entry_width + 28
@@ -991,6 +992,9 @@ def read_snapshot(
991992 runs = payload ["runs" ]
992993 if not points or not runs :
993994 raise RuntimeError (f"Performance snapshot is incomplete: { path } " )
995+ provenance_runs = payload .get ("provenance" )
996+ if provenance_runs is not None and (not isinstance (provenance_runs , list ) or len (provenance_runs ) != len (runs )):
997+ raise RuntimeError (f"Performance snapshot provenance does not match its runs: { path } " )
994998 if all ("environment_steps" in point for point in points ):
995999 environment_steps = [point ["environment_steps" ] for point in points ]
9961000 elif all ("step" in point for point in points ):
@@ -1043,8 +1047,13 @@ def read_snapshot(
10431047 environment_steps = np .asarray ([], dtype = np .float64 ),
10441048 elapsed_seconds = np .asarray ([], dtype = np .float64 ),
10451049 values = np .asarray ([], dtype = np .float64 ),
1050+ provenance = (
1051+ {key : record [key ] for key in ("system" , "performance" ) if key in record }
1052+ if isinstance ((record := provenance_runs [index ]), dict )
1053+ else None
1054+ ),
10461055 )
1047- for run in runs
1056+ for index , run in enumerate ( runs )
10481057 ]
10491058 except (KeyError , TypeError , ValueError , json .JSONDecodeError ) as exc :
10501059 raise RuntimeError (f"Invalid performance snapshot: { path } " ) from exc
0 commit comments