gvlktejaswi commited on
Commit
bdc9b48
·
verified ·
1 Parent(s): cebcc81

Update page_files/categorized/Backend/mapper5.py

Browse files
page_files/categorized/Backend/mapper5.py CHANGED
@@ -5,10 +5,7 @@ mapper.py — Plot ⇄ Property mapping + persistence
5
  Combines what used to be two files (Code 3 "mapping" + Code 4 "storage")
6
  into one module. It sits on top of:
7
 
8
- 2.py — Code 1: extraction + tri-LLM consensus + source verification
9
- (imported via importlib, since a module name can't start
10
- with a digit)
11
- image2.py — Code 2: plot/figure extraction + crop verification
12
 
13
  WHAT IT DOES
14
  ------------
@@ -314,7 +311,7 @@ def _get_shared_embed_model() -> Optional[Any]:
314
  _embed_tried = True
315
  try:
316
  import importlib
317
- _embed_model = importlib.import_module("2")._get_embed_model() # Code 1 = 2.py
318
  log.info("mapper: reusing Code 1's SciBERT embedding model.")
319
  return _embed_model
320
  except Exception as e:
@@ -847,7 +844,9 @@ def store_properties_with_plots(
847
  df = df_augmented.reset_index(drop=True).copy()
848
 
849
  mapped_gis = set(int(g) for g in links_df["group_idx"].tolist()) if not links_df.empty else set()
850
- group_idxs = None if save_all_group_images else mapped_gis
 
 
851
 
852
  path_map, groups = save_plot_images(plot_results, out_dir, pdf_stem, group_idxs=group_idxs)
853
  group_by_idx = {g["group_idx"]: g for g in groups}
@@ -1116,7 +1115,7 @@ def _extract(pdf_bytes: bytes, doi_override: str = "",
1116
  """Run Code 1 (2.py) + Code 2 (image2.py) ONCE. Returns a bundle with all
1117
  six property tables + plot_results + coverage + meta + errors."""
1118
  import importlib
1119
- run_pipeline = importlib.import_module("2").run_pipeline
1120
  from Pdf_ImageExtraction import extract_and_verify_plots
1121
  (dfc, dfv, dfcv, dfg, dfp, dfcl, _chunks, errors, meta) = run_pipeline(
1122
  pdf_bytes, doi_override=doi_override)
@@ -1135,7 +1134,7 @@ def _extract(pdf_bytes: bytes, doi_override: str = "",
1135
  def get_or_extract(pdf_bytes: bytes, doi_override: str = "", verify_engines=None,
1136
  use_disk_cache: bool = True, force: bool = False):
1137
  """Extraction cached by the PDF's CONTENT HASH — never by source_table.
1138
- On a cache hit, Pdf_DataExtraction.py and Pdf_ImageExtraction.py are NOT re-run, so switching tables /
1139
  pruning / re-mapping is free. Returns (pdf_hash, bundle)."""
1140
  import pickle
1141
  h = _pdf_hash(pdf_bytes)
@@ -1194,7 +1193,7 @@ def _run_streamlit() -> None:
1194
 
1195
  st.set_page_config(page_title="mapper — Plot ⇄ Property", page_icon="🔗", layout="wide")
1196
  st.title("🔗 mapper — Plot ⇄ Property mapping + database")
1197
- st.caption("Runs Pdf_DataExtraction.py + Pdf_ImageExtraction.py once (cached), auto-drops non-plots, lets you "
1198
  "prune what's left, then attaches plots to properties on Map.")
1199
 
1200
  ss = st.session_state
@@ -1244,13 +1243,13 @@ def _run_streamlit() -> None:
1244
 
1245
  # ---- sidebar ------------------------------------------------------------
1246
  with st.sidebar:
1247
- st.header("⚙️ Settings")
1248
  st.subheader("Extraction")
1249
  use_gpt = st.checkbox("Also verify crops with GPT", value=False)
1250
  use_claude = st.checkbox("Also verify crops with Claude", value=False)
1251
  doi_manual = st.text_input("DOI override (optional)", placeholder="10.xxxx/...")
1252
  use_disk_cache = st.checkbox("Use on-disk extraction cache", value=True,
1253
- help="Skip Pdf_DataExtraction.py + Pdf_ImageExtraction.py entirely when this exact "
1254
  "PDF was extracted before.")
1255
  st.divider()
1256
  st.subheader("Auto figure filter")
@@ -1292,12 +1291,12 @@ def _run_streamlit() -> None:
1292
  use_container_width=True)
1293
  else:
1294
  ec1.success("✓ This paper is loaded — switch tables / prune / map freely; "
1295
- "Pdf_DataExtraction.py and Pdf_ImageExtraction.py will NOT re-run.")
1296
  force = ec2.button("↻ Force re-extract", use_container_width=True)
1297
 
1298
  if do_extract or force:
1299
  engines = ["gemini"] + (["gpt"] if use_gpt else []) + (["claude"] if use_claude else [])
1300
- with st.spinner("Running Pdf_DataExtraction.py extraction/consensus + Pdf_ImageExtraction.py plot detection…"):
1301
  _h, bundle = get_or_extract(pdf_bytes, doi_override=doi_manual,
1302
  verify_engines=engines,
1303
  use_disk_cache=use_disk_cache, force=force)
@@ -1314,15 +1313,15 @@ def _run_streamlit() -> None:
1314
  bundle = ss["bundle"]
1315
  stem = ss["stem"]
1316
  if bundle.get("_cache") == "disk":
1317
- st.caption(" Loaded from on-disk cache — Pdf_DataExtraction.py and Pdf_ImageExtraction.py were not re-run.")
1318
 
1319
  # ---- three top-level views ---------------------------------------------
1320
  view_props, view_plots, work = st.tabs(
1321
- ["📄 Extraction (2.py)", "🖼️ Plots (Pdf_ImageExtraction.py)", "🔗 Map & curate"])
1322
 
1323
  with view_props:
1324
  if bundle.get("api_errors"):
1325
- with st.expander(f"⚠️ {len(bundle['api_errors'])} API error(s)"):
1326
  for e in bundle["api_errors"]:
1327
  st.code(e)
1328
  meta = bundle.get("meta", {})
@@ -1384,7 +1383,7 @@ def _run_streamlit() -> None:
1384
  with st.container(border=True):
1385
  hc1, hc2 = st.columns([6, 1])
1386
  hc1.markdown(f"**Page {group.get('page')}** — {group.get('caption', '')}")
1387
- if hc2.button("🗑 Remove figure", key=f"rmfig_{gi}"):
1388
  _remove_figure(gi)
1389
  images = group.get("image_data", [])
1390
  icols = st.columns(min(len(images), 4) or 1)
@@ -1399,7 +1398,7 @@ def _run_streamlit() -> None:
1399
  if st.button("x remove", key=f"rmimg_{gi}_{idx}"):
1400
  _remove_image(gi, idx)
1401
 
1402
- map_label = " Map — attach plots to properties" + (" (re-map)" if ss.get("mapped") else "")
1403
  if st.button(map_label, type="primary", use_container_width=True):
1404
  source_df = bundle["table_map"][source_table]
1405
  with st.spinner("Mapping property rows to figures…"):
@@ -1468,13 +1467,13 @@ def _run_streamlit() -> None:
1468
  out.append((imgs[ix].get("array"), cap))
1469
  return out
1470
 
1471
- names = ["🖼️ Figures & attached rows (remove links)",
1472
- f"🔗 All links ({len(links_df)})",
1473
- f"🧬 Augmented ({n_rows})",
1474
- "📤 Store / Export"]
1475
  if store:
1476
- names.insert(3, f"🗃️ Stored ({store['n_properties']})")
1477
- names.append("🔎 Properties + image")
1478
  wt = st.tabs(names)
1479
  prop_img_tab = wt[-1]
1480
 
@@ -1584,7 +1583,7 @@ def _run_streamlit() -> None:
1584
  st.markdown("**Store the curated result to the database**")
1585
  st.caption("Writes the pruned figures + edited links; each stored row points at "
1586
  "its saved crop on disk. Re-running for the same PDF overwrites cleanly.")
1587
- if st.button("💾 Store to database", type="primary", use_container_width=True):
1588
  with st.spinner("Saving crops and writing SQLite…"):
1589
  ss["store"] = store_properties_with_plots(
1590
  ss["df_aug"], ss["links_df"], ss["plot_curated"],
@@ -1608,14 +1607,14 @@ def _run_streamlit() -> None:
1608
  embed_img = st.checkbox("Embed matched plot into the table's image column",
1609
  value=True)
1610
  cA, cB = st.columns(2)
1611
- if cA.button("🔌 Test connection", use_container_width=True):
1612
  try:
1613
  db_healthcheck()
1614
  st.success(f"Connected to {DB_HOST} ({DB_KIND}).")
1615
  except Exception as e:
1616
  st.error(f"Connection failed: {e}")
1617
  push_ready = bool(store) and store.get("n_properties", 0) > 0
1618
- if cB.button(f"⬆️ Push to {category}", type="primary",
1619
  use_container_width=True, disabled=not push_ready):
1620
  try:
1621
  with st.spinner(f"Conforming + writing rows to '{category}'…"):
@@ -1628,24 +1627,24 @@ def _run_streamlit() -> None:
1628
  except Exception as e:
1629
  st.error(f"Push failed: {e}")
1630
  if not push_ready:
1631
- st.caption("Click **💾 Store to database** first — the RDS push "
1632
  "uploads those stored rows.")
1633
 
1634
  st.divider()
1635
  st.markdown("**Downloads**")
1636
  d1, d2, d3 = st.columns(3)
1637
  d1.download_button(
1638
- "⬇️ Links CSV",
1639
  links_df.drop(columns=["link_id"], errors="ignore").to_csv(index=False).encode()
1640
  if not links_df.empty else b"",
1641
  f"{stem}_links.csv", "text/csv", use_container_width=True, disabled=links_df.empty)
1642
  d2.download_button(
1643
- "⬇️ Augmented CSV",
1644
  df_aug.drop(columns=["doi_url"], errors="ignore").to_csv(index=False).encode(),
1645
  f"{stem}_properties_mapped.csv", "text/csv", use_container_width=True)
1646
  if store:
1647
  d3.download_button(
1648
- "⬇️ DB + plots (ZIP)",
1649
  data=bundle_zip(store["out_dir"], store["pdf_stem"], store["db_filename"]),
1650
  file_name=f"{stem}_db_bundle.zip", mime="application/zip",
1651
  use_container_width=True)
@@ -1680,4 +1679,6 @@ if __name__ == "__main__":
1680
  " links_df, df_aug = map_plots_to_properties(df_consensus, plot_results)\n"
1681
  " store_properties_with_plots(df_aug, links_df, plot_results,\n"
1682
  " out_dir='./aim_efrc_db', pdf_stem='paper1')\n"
1683
- )
 
 
 
5
  Combines what used to be two files (Code 3 "mapping" + Code 4 "storage")
6
  into one module. It sits on top of:
7
 
8
+
 
 
 
9
 
10
  WHAT IT DOES
11
  ------------
 
311
  _embed_tried = True
312
  try:
313
  import importlib
314
+ _embed_model = importlib.import_module("Pdf_DataExtraction")._get_embed_model() # Code 1 = 2.py
315
  log.info("mapper: reusing Code 1's SciBERT embedding model.")
316
  return _embed_model
317
  except Exception as e:
 
844
  df = df_augmented.reset_index(drop=True).copy()
845
 
846
  mapped_gis = set(int(g) for g in links_df["group_idx"].tolist()) if not links_df.empty else set()
847
+ # None = save every detected crop. If nothing mapped (empty links), fall back
848
+ # to saving all crops so images still persist instead of writing zero.
849
+ group_idxs = None if (save_all_group_images or not mapped_gis) else mapped_gis
850
 
851
  path_map, groups = save_plot_images(plot_results, out_dir, pdf_stem, group_idxs=group_idxs)
852
  group_by_idx = {g["group_idx"]: g for g in groups}
 
1115
  """Run Code 1 (2.py) + Code 2 (image2.py) ONCE. Returns a bundle with all
1116
  six property tables + plot_results + coverage + meta + errors."""
1117
  import importlib
1118
+ run_pipeline = importlib.import_module("Pdf_DataExtraction").run_pipeline
1119
  from Pdf_ImageExtraction import extract_and_verify_plots
1120
  (dfc, dfv, dfcv, dfg, dfp, dfcl, _chunks, errors, meta) = run_pipeline(
1121
  pdf_bytes, doi_override=doi_override)
 
1134
  def get_or_extract(pdf_bytes: bytes, doi_override: str = "", verify_engines=None,
1135
  use_disk_cache: bool = True, force: bool = False):
1136
  """Extraction cached by the PDF's CONTENT HASH — never by source_table.
1137
+ On a cache hit, 2.py and image2.py are NOT re-run, so switching tables /
1138
  pruning / re-mapping is free. Returns (pdf_hash, bundle)."""
1139
  import pickle
1140
  h = _pdf_hash(pdf_bytes)
 
1193
 
1194
  st.set_page_config(page_title="mapper — Plot ⇄ Property", page_icon="🔗", layout="wide")
1195
  st.title("🔗 mapper — Plot ⇄ Property mapping + database")
1196
+ st.caption("Runs 2.py + image2.py once (cached), auto-drops non-plots, lets you "
1197
  "prune what's left, then attaches plots to properties on Map.")
1198
 
1199
  ss = st.session_state
 
1243
 
1244
  # ---- sidebar ------------------------------------------------------------
1245
  with st.sidebar:
1246
+ st.header("Settings")
1247
  st.subheader("Extraction")
1248
  use_gpt = st.checkbox("Also verify crops with GPT", value=False)
1249
  use_claude = st.checkbox("Also verify crops with Claude", value=False)
1250
  doi_manual = st.text_input("DOI override (optional)", placeholder="10.xxxx/...")
1251
  use_disk_cache = st.checkbox("Use on-disk extraction cache", value=True,
1252
+ help="Skip 2.py + image2.py entirely when this exact "
1253
  "PDF was extracted before.")
1254
  st.divider()
1255
  st.subheader("Auto figure filter")
 
1291
  use_container_width=True)
1292
  else:
1293
  ec1.success("✓ This paper is loaded — switch tables / prune / map freely; "
1294
+ "2.py and image2.py will NOT re-run.")
1295
  force = ec2.button("↻ Force re-extract", use_container_width=True)
1296
 
1297
  if do_extract or force:
1298
  engines = ["gemini"] + (["gpt"] if use_gpt else []) + (["claude"] if use_claude else [])
1299
+ with st.spinner("Running 2.py extraction/consensus + image2.py plot detection…"):
1300
  _h, bundle = get_or_extract(pdf_bytes, doi_override=doi_manual,
1301
  verify_engines=engines,
1302
  use_disk_cache=use_disk_cache, force=force)
 
1313
  bundle = ss["bundle"]
1314
  stem = ss["stem"]
1315
  if bundle.get("_cache") == "disk":
1316
+ st.caption(" Loaded from on-disk cache — 2.py and image2.py were not re-run.")
1317
 
1318
  # ---- three top-level views ---------------------------------------------
1319
  view_props, view_plots, work = st.tabs(
1320
+ [" Extraction (2.py)", " Plots (image2.py)", " Map & curate"])
1321
 
1322
  with view_props:
1323
  if bundle.get("api_errors"):
1324
+ with st.expander(f" {len(bundle['api_errors'])} API error(s)"):
1325
  for e in bundle["api_errors"]:
1326
  st.code(e)
1327
  meta = bundle.get("meta", {})
 
1383
  with st.container(border=True):
1384
  hc1, hc2 = st.columns([6, 1])
1385
  hc1.markdown(f"**Page {group.get('page')}** — {group.get('caption', '')}")
1386
+ if hc2.button(" Remove figure", key=f"rmfig_{gi}"):
1387
  _remove_figure(gi)
1388
  images = group.get("image_data", [])
1389
  icols = st.columns(min(len(images), 4) or 1)
 
1398
  if st.button("x remove", key=f"rmimg_{gi}_{idx}"):
1399
  _remove_image(gi, idx)
1400
 
1401
+ map_label = " Map — attach plots to properties" + (" (re-map)" if ss.get("mapped") else "")
1402
  if st.button(map_label, type="primary", use_container_width=True):
1403
  source_df = bundle["table_map"][source_table]
1404
  with st.spinner("Mapping property rows to figures…"):
 
1467
  out.append((imgs[ix].get("array"), cap))
1468
  return out
1469
 
1470
+ names = [" Figures & attached rows (remove links)",
1471
+ f" All links ({len(links_df)})",
1472
+ f" Augmented ({n_rows})",
1473
+ " Store / Export"]
1474
  if store:
1475
+ names.insert(3, f" Stored ({store['n_properties']})")
1476
+ names.append(" Properties + image")
1477
  wt = st.tabs(names)
1478
  prop_img_tab = wt[-1]
1479
 
 
1583
  st.markdown("**Store the curated result to the database**")
1584
  st.caption("Writes the pruned figures + edited links; each stored row points at "
1585
  "its saved crop on disk. Re-running for the same PDF overwrites cleanly.")
1586
+ if st.button(" Store to database", type="primary", use_container_width=True):
1587
  with st.spinner("Saving crops and writing SQLite…"):
1588
  ss["store"] = store_properties_with_plots(
1589
  ss["df_aug"], ss["links_df"], ss["plot_curated"],
 
1607
  embed_img = st.checkbox("Embed matched plot into the table's image column",
1608
  value=True)
1609
  cA, cB = st.columns(2)
1610
+ if cA.button(" Test connection", use_container_width=True):
1611
  try:
1612
  db_healthcheck()
1613
  st.success(f"Connected to {DB_HOST} ({DB_KIND}).")
1614
  except Exception as e:
1615
  st.error(f"Connection failed: {e}")
1616
  push_ready = bool(store) and store.get("n_properties", 0) > 0
1617
+ if cB.button(f" Push to {category}", type="primary",
1618
  use_container_width=True, disabled=not push_ready):
1619
  try:
1620
  with st.spinner(f"Conforming + writing rows to '{category}'…"):
 
1627
  except Exception as e:
1628
  st.error(f"Push failed: {e}")
1629
  if not push_ready:
1630
+ st.caption("Click ** Store to database** first — the RDS push "
1631
  "uploads those stored rows.")
1632
 
1633
  st.divider()
1634
  st.markdown("**Downloads**")
1635
  d1, d2, d3 = st.columns(3)
1636
  d1.download_button(
1637
+ " Links CSV",
1638
  links_df.drop(columns=["link_id"], errors="ignore").to_csv(index=False).encode()
1639
  if not links_df.empty else b"",
1640
  f"{stem}_links.csv", "text/csv", use_container_width=True, disabled=links_df.empty)
1641
  d2.download_button(
1642
+ " Augmented CSV",
1643
  df_aug.drop(columns=["doi_url"], errors="ignore").to_csv(index=False).encode(),
1644
  f"{stem}_properties_mapped.csv", "text/csv", use_container_width=True)
1645
  if store:
1646
  d3.download_button(
1647
+ " DB + plots (ZIP)",
1648
  data=bundle_zip(store["out_dir"], store["pdf_stem"], store["db_filename"]),
1649
  file_name=f"{stem}_db_bundle.zip", mime="application/zip",
1650
  use_container_width=True)
 
1679
  " links_df, df_aug = map_plots_to_properties(df_consensus, plot_results)\n"
1680
  " store_properties_with_plots(df_aug, links_df, plot_results,\n"
1681
  " out_dir='./aim_efrc_db', pdf_stem='paper1')\n"
1682
+ )
1683
+
1684
+