iTagPDF / pdf-script /pipeline.py
peyajm
add pdf-script as plain directory
c6c9042
Raw
History Blame
5.55 kB
#!/usr/bin/env python3
"""
pipeline.py β€” Full PDF Accessibility Pipeline
==============================================
Runs both parts end-to-end:
Part 1 Β· generate_metadata (Python)
PDF β†’ YOLOv11 + Tesseract + GPT-4o β†’ output/elements.txt
Part 2 Β· embed_metadata (Java / iText)
input.pdf + elements.txt β†’ output/tagged_output.pdf (PDF/UA-1)
Usage
-----
python pipeline.py # uses data/input.pdf
python pipeline.py --pdf path/to/file.pdf
python pipeline.py --pdf file.pdf --latex path/to/latex-project/
python pipeline.py --skip-metadata # only run Java tagger
python pipeline.py --skip-tagging # only run Python analysis
"""
import argparse
import os
import subprocess
import sys
ROOT = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = os.path.join(ROOT, "data")
OUTPUT_DIR = os.path.join(ROOT, "output")
JAR_PATH = os.path.join(ROOT, "pdftagger.jar")
def run(cmd: list, **kwargs):
print(f"\n>>> {' '.join(str(c) for c in cmd)}")
result = subprocess.run(cmd, **kwargs)
if result.returncode != 0:
sys.exit(result.returncode)
return result
def build_jar(force: bool = False):
if os.path.exists(JAR_PATH) and not force:
print(f"[pipeline] JAR already built: {JAR_PATH}")
return
print("[pipeline] Building Java tagger JAR (maven package)…")
run(["mvn", "-f", os.path.join(ROOT, "pom.xml"), "package", "-q", "-DskipTests"])
if not os.path.exists(JAR_PATH):
print("[pipeline] ERROR: pdftagger.jar not found after build.", file=sys.stderr)
sys.exit(1)
print(f"[pipeline] JAR built: {JAR_PATH}")
def main():
parser = argparse.ArgumentParser(
description="PDF Accessibility Pipeline β€” analyse then tag.",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"--pdf",
default=os.path.join(DATA_DIR, "input.pdf"),
help="Input PDF (default: data/input.pdf)",
)
parser.add_argument(
"--latex",
default=DATA_DIR,
metavar="DIR",
help="Directory containing the LaTeX source subfolder (default: data/). "
"Place your .tex project as a subfolder inside data/ and this is detected automatically.",
)
parser.add_argument(
"--output",
default=OUTPUT_DIR,
help="Output directory (default: output/)",
)
parser.add_argument(
"--pages",
type=int,
default=-1,
metavar="N",
help="Limit to first N pages (-1 = all)",
)
parser.add_argument(
"--skip-metadata",
action="store_true",
help="Skip Part 1 (use existing output/elements.txt)",
)
parser.add_argument(
"--skip-tagging",
action="store_true",
help="Skip Part 2 (Java tagger)",
)
parser.add_argument(
"--rebuild-jar",
action="store_true",
help="Force rebuild of pdftagger.jar before tagging",
)
parser.add_argument(
"--no-preflight",
action="store_true",
help="Skip prerequisite checks (for CI/CD environments).",
)
args = parser.parse_args()
from preflight import run_preflight_checks
run_preflight_checks(
skip=args.no_preflight,
need_python_part=not args.skip_metadata,
need_java_part=not args.skip_tagging,
)
pdf_path = os.path.abspath(args.pdf)
output_dir = os.path.abspath(args.output)
elements_out = os.path.join(output_dir, "elements.txt")
tagged_out = os.path.join(output_dir, "tagged_output.pdf")
os.makedirs(output_dir, exist_ok=True)
os.makedirs(os.path.join(output_dir, "visualizations"), exist_ok=True)
if not os.path.exists(pdf_path):
print(f"[pipeline] ERROR: PDF not found: {pdf_path}", file=sys.stderr)
sys.exit(1)
# ----------------------------------------------------------------
# Part 1 β€” generate_metadata
# ----------------------------------------------------------------
if not args.skip_metadata:
print("\n[pipeline] ═══ Part 1: Generate Metadata ═══")
cmd = [
sys.executable, "-m", "generate_metadata.main",
"--pdf", pdf_path,
"--output", output_dir,
"--pages", str(args.pages),
]
cmd += ["--latex", os.path.abspath(args.latex)]
run(cmd, cwd=ROOT)
if not os.path.exists(elements_out):
print(f"[pipeline] ERROR: elements.txt not produced at {elements_out}", file=sys.stderr)
sys.exit(1)
else:
print(f"[pipeline] Skipping Part 1 β€” using: {elements_out}")
if not os.path.exists(elements_out):
print(
"[pipeline] ERROR: elements.txt not found. Run without --skip-metadata first.",
file=sys.stderr,
)
sys.exit(1)
# ----------------------------------------------------------------
# Part 2 β€” embed_metadata (Java tagger)
# ----------------------------------------------------------------
if not args.skip_tagging:
print("\n[pipeline] ═══ Part 2: Embed Metadata ═══")
build_jar(force=args.rebuild_jar)
run(["java", "-jar", JAR_PATH, pdf_path, elements_out, tagged_out])
print(f"\n[pipeline] Tagged PDF: {tagged_out}")
else:
print("[pipeline] Skipping Part 2 (Java tagger).")
print("\n[pipeline] Done.")
if __name__ == "__main__":
main()