diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py index 1c301ff..ff03247 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/lamni.py @@ -2231,6 +2231,7 @@ class LamNI(TomoQueueMixin, LamNIAlignmentMixin, LamNIOpticsMixin, LamniGuiTools hook_source = self._active_hook_source() user_target = os.path.expanduser(f"~/data/raw/documentation/tomo_scan_ID_{self.tomo_id}.pdf") with PDFWriter(user_target) as file: + self._add_psi_footer(file) # PDFWriter (bec_lib) has no public image API -- reach into its # underlying fpdf object directly. logo_w chosen to keep the # header modest relative to the A4 page width (210mm). diff --git a/csaxs_bec/bec_ipython_client/plugins/OMNY_shared/tomo_queue_mixin.py b/csaxs_bec/bec_ipython_client/plugins/OMNY_shared/tomo_queue_mixin.py index 15cac04..6a0f9cb 100644 --- a/csaxs_bec/bec_ipython_client/plugins/OMNY_shared/tomo_queue_mixin.py +++ b/csaxs_bec/bec_ipython_client/plugins/OMNY_shared/tomo_queue_mixin.py @@ -39,6 +39,7 @@ import builtins import datetime import inspect import json +import os import threading import uuid from typing import Callable @@ -481,6 +482,39 @@ class TomoQueueMixin: threading.Thread(target=_run, name="PdfUpload", daemon=True).start() + def _add_psi_footer(self, pdf_writer) -> None: + """Add the PSI logo to every page's footer of a PDFWriter report. + + PDFWriter/BECPDF (bec_lib, a separate repo) has no public API for + this, and its footer() is fpdf's own automatic per-page callback + (unlike the header logo, which is drawn once inline right after + opening the PDFWriter) -- a report can span multiple pages (e.g. a + long at_each_angle_hook source dump), so the logo needs to repeat + on each one. Fully replaces bec_lib's own footer() (rather than + calling it and adding to it) so the timestamp can drop the + microseconds str(datetime.datetime.now()) includes -- same visual + layout/font otherwise (see bec_lib/pdf_writer.py's BECPDF.footer()). + """ + psi_logo = os.path.join(os.path.dirname(os.path.abspath(__file__)), "psi_logo.svg") + if not os.path.exists(psi_logo): + return + from fpdf import XPos, YPos + + pdf = pdf_writer._pdf + + def _footer_with_logo(): + pdf.set_y(-15) + pdf.image(psi_logo, x=pdf.l_margin, y=pdf.h - 22, h=6) + pdf.set_font("Courier", "", 8) + pdf.set_text_color(128) + timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + pdf.cell(0, 10, f"BEC, {timestamp}", 0, new_x=XPos.RIGHT, new_y=YPos.TOP, align="L") + pdf.cell( + 0, 10, "Page " + str(pdf.page_no()), 0, new_x=XPos.RIGHT, new_y=YPos.TOP, align="R" + ) + + pdf.footer = _footer_with_logo + # ── command-job action registry / dispatch ────────────────────────────── def _validate_action_kwargs(self, action_name: str, kwargs: dict) -> None: diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py index 326caf7..1471c24 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py @@ -3862,6 +3862,7 @@ class Flomni( f"~/data/raw/documentation/tomo_scan_ID_{self.tomo_id}.pdf" ) with PDFWriter(user_target) as file: + self._add_psi_footer(file) # PDFWriter (bec_lib) has no public image API -- reach into its # underlying fpdf object directly. logo_w chosen to keep the # header modest relative to the A4 page width (210mm).