Spaces:
Sleeping
Sleeping
| #!/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() | |