diff --git a/sfm/report_pdf.py b/sfm/report_pdf.py index 6618d9a..25859d1 100644 --- a/sfm/report_pdf.py +++ b/sfm/report_pdf.py @@ -638,14 +638,7 @@ def _draw_channel_stats_waveform(ax, rd: ReportData) -> None: ("Sensor Check", "sensor_check", ""), ] _draw_stats_table(ax, rd, rows_spec) - if rd.peak_vector_sum_ips is not None: - line = f"Peak Vector Sum {rd.peak_vector_sum_ips:.3f} in/s" - if rd.peak_vector_sum_time_s is not None: - line += f" At {rd.peak_vector_sum_time_s:.3f} sec." - ax.text(0.0, -0.08, line, fontsize=9, weight="bold", - ha="left", va="top", transform=ax.transAxes) - ax.text(0.0, -0.18, "NA: Not Applicable", fontsize=7, color="#888", - ha="left", va="top", transform=ax.transAxes) + _draw_pvs_summary(ax, rd, n_data_rows=len(rows_spec)) def _draw_channel_stats_histogram(ax, rd: ReportData) -> None: @@ -663,20 +656,54 @@ def _draw_channel_stats_histogram(ax, rd: ReportData) -> None: ("Sensor Check", "sensor_check", ""), ] _draw_stats_table(ax, rd, rows_spec) - if rd.peak_vector_sum_ips is not None: - line = f"Peak Vector Sum {rd.peak_vector_sum_ips:.3f} in/s" - # Histograms: "0.091 in/s on May 27, 2026 At 06:06:14" - # The when_str is "HH:MM:SS Month DD, YYYY" — reformat for BW match. - if rd.peak_vector_sum_when_str: - parts = rd.peak_vector_sum_when_str.split(" ", 1) - if len(parts) == 2: - line += f" on {parts[1]} At {parts[0]}" - else: - line += f" on {rd.peak_vector_sum_when_str}" - ax.text(0.0, -0.08, line, fontsize=9, weight="bold", - ha="left", va="top", transform=ax.transAxes) - ax.text(0.0, -0.18, "NA: Not Applicable", fontsize=7, color="#888", - ha="left", va="top", transform=ax.transAxes) + _draw_pvs_summary(ax, rd, n_data_rows=len(rows_spec), histogram_when=True) + + +def _draw_pvs_summary( + ax, + rd: ReportData, + *, + n_data_rows: int, + histogram_when: bool = False, +) -> None: + """Render the Peak Vector Sum + 'NA: Not Applicable' caption below the + stats table. + + Reads ``ax._stats_table_bottom`` (set by ``_draw_stats_table`` when + it pins the table via an explicit ``bbox``) so the PVS line lands + just below the table's known bottom edge instead of guessing at the + geometry. + + Centered horizontally for visual balance (the previous left-aligned + x=0 landed under the label column, not the data, which looked off). + """ + if rd.peak_vector_sum_ips is None: + return + + line = f"Peak Vector Sum {rd.peak_vector_sum_ips:.3f} in/s" + if histogram_when and rd.peak_vector_sum_when_str: + # Histogram absolute date+time. when_str is "HH:MM:SS Month DD, YYYY"; + # reformat to " on At