From 79f257f072a85701899aef8ff31fc2e7e20ae816 Mon Sep 17 00:00:00 2001 From: x01dc Date: Mon, 27 Jul 2026 17:48:57 +0200 Subject: [PATCH] feat(LamNI,flomni): add PSI logo to every PDF report page footer Downloaded from https://intranet.psi.ch/themes/custom/design/logo.svg (no gradients/filters/embedded fonts -- confirmed fpdf2 renders it directly, no PNG conversion needed) and stored as psi_logo.svg in OMNY_shared. Added TomoQueueMixin._add_psi_footer(), which overrides the fpdf instance's footer() callback (PDFWriter/BECPDF live in bec_lib, a separate repo with no public API for this) so the logo repeats on every page -- unlike the header logo, which is drawn once inline, a report can span multiple pages (e.g. a long at_each_angle_hook source dump). Also drops the microseconds from the existing "BEC, " footer text while reimplementing it, per request ("ms precision is not needed"). Verified end-to-end with bec_lib's real PDFWriter: a 300-line hook source forced a 7-page report, with the logo correctly repeating on every page. --- .../bec_ipython_client/plugins/LamNI/lamni.py | 1 + .../plugins/OMNY_shared/tomo_queue_mixin.py | 34 +++++++++++++++++++ .../plugins/flomni/flomni.py | 1 + 3 files changed, 36 insertions(+) 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).