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, <timestamp>" 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.
This commit is contained in:
@@ -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).
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user