def passage_lines_df_from_answer(line_df, answer_json): a = json.loads(answer_json) sp, sl = a["start_page_num"], a["start_line_num"] ep, el = a["end_page_num"], a["end_line_num"] if sp is None: return line_df.iloc[0:0] mask = ( line_df["page_num"].between(sp, ep) & ((line_df["page_num"] != sp) | (line_df["line_num"] >= sl)) & ((line_df["page_num"] != ep) | (line_df["line_num"] <= el)) ) return line_df.loc[mask].copy() def passage_bbox_by_page(passage_df): return passage_df.groupby("page_num", as_index=False).agg( x0=("x0", "min"), y0=("y0", "min"), x1=("x1", "max"), y1=("y1", "max")) def draw_passage_rectangles(pdf_path, bboxes_df, out_path): doc = fitz.open(pdf_path) for _, r in bboxes_df.iterrows(): page = doc[int(r["page_num"]) - 1] page.add_rect_annot(fitz.Rect(r["x0"], r["y0"], r["x1"], r["y1"])) doc.save(out_path)