yogl commited on
Commit
db2000e
·
verified ·
1 Parent(s): deec0df

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -29
app.py CHANGED
@@ -71,6 +71,7 @@ DISPLAY_COLUMNS_ALL = [
71
  # - Название диссертации -> ссылка на ВАК (если есть vak_link)
72
  # - после "Год": OpenAlex (ID+ссылка), ORCID (ID+ссылка)
73
  # - Тип по умолчанию скрыт
 
74
  # ==========================
75
 
76
  UI_TABLE_COLUMNS = [
@@ -82,15 +83,18 @@ UI_TABLE_COLUMNS = [
82
  "Год",
83
  "OpenAlex",
84
  "ORCID",
85
- # "Регистрационный номер",
86
  "h-index",
87
  "i10-index",
88
  "Работ",
89
  "Цитат",
90
  ]
91
 
92
- # По умолчанию: все включены, кроме "Организация" и "Тип"
93
- DEFAULT_VISIBLE_UI = {c: (c != "Организация" and c != "Тип") for c in UI_TABLE_COLUMNS}
 
 
 
94
 
95
 
96
  # ==========================
@@ -513,7 +517,6 @@ def run_search(
513
  ):
514
  mask = build_filter_mask(candidate_selected, doctor_selected, science_selected, year_range)
515
 
516
- # С запасом, чтобы после OA/ORCID фильтров осталось до top_k
517
  prefetch_k = min(max(int(top_k) * 5, int(top_k)), 500)
518
  results = search_core(query, prefetch_k, mask=mask)
519
 
@@ -530,7 +533,6 @@ def run_search(
530
 
531
  df_raw["reg_norm"] = df_raw["registration_number"].map(_norm_regnum)
532
 
533
- # OA/ORCID enrichment
534
  if not oa_enrich.empty:
535
  en = oa_enrich.reindex(df_raw["reg_norm"]).reset_index(drop=True)
536
 
@@ -542,19 +544,18 @@ def run_search(
542
  df_raw["openalex_url"] = _get("openalex_url", "").map(_norm_openalex_url)
543
  df_raw["orcid_url"] = _get("orcid_url", "").map(_norm_orcid_url)
544
 
545
- df_raw["h_index"] = pd.to_numeric(_get("h_index", 0), errors="coerce").astype("float64")
546
- df_raw["i10_index"] = pd.to_numeric(_get("i10_index", 0), errors="coerce").astype("float64")
547
- df_raw["works_count"] = pd.to_numeric(_get("works_count", 0), errors="coerce").astype("float64")
548
- df_raw["cited_by_count"] = pd.to_numeric(_get("cited_by_count", 0), errors="coerce").astype("float64")
549
  else:
550
  df_raw["openalex_url"] = ""
551
  df_raw["orcid_url"] = ""
552
- df_raw["h_index"] = 0
553
- df_raw["i10_index"] = 0
554
- df_raw["works_count"] = 0
555
- df_raw["cited_by_count"] = 0
556
 
557
- # Фильтры "только с ..."
558
  if only_openalex:
559
  df_raw = df_raw[df_raw["openalex_url"].map(_safe_text) != ""]
560
  if only_orcid:
@@ -564,15 +565,12 @@ def run_search(
564
  if len(df_raw) > int(top_k):
565
  df_raw = df_raw.iloc[: int(top_k)].copy()
566
 
567
- # Дедуп и индекс-идентификатор для стабильного выбора
568
  df_raw["reg_norm"] = df_raw["registration_number"].map(_norm_regnum)
569
  df_raw = df_raw.drop_duplicates(subset=["reg_norm"]).set_index("reg_norm", drop=True)
570
 
571
- # Перенумерация "№"
572
  if "№" in df_raw.columns:
573
  df_raw["№"] = np.arange(1, len(df_raw) + 1)
574
 
575
- # ====== UI значения со ссылками ======
576
  fio_txt = df_raw["fio"].map(_safe_text)
577
 
578
  title_txt = df_raw["title"].map(_safe_text)
@@ -591,13 +589,13 @@ def run_search(
591
  df_ui = pd.DataFrame(
592
  {
593
  "Сходство": pd.to_numeric(df_raw["score"], errors="coerce").astype("float64"),
594
- "ФИО": fio_txt, # НЕ ссылка
595
- "Название диссертации": title_cell, # ссылка на ВАК через LinkColumn
596
  "Организация": df_raw["author_org_short"].map(_safe_text),
597
  "Тип": df_raw["dissertation_type"].map(_safe_text),
598
  "Год": pd.to_numeric(df_raw["protection_year"], errors="coerce").astype("float64"),
599
- "OpenAlex": openalex_cell, # ID + ссылка
600
- "ORCID": orcid_cell, # ID + ссылка
601
  "Регистрационный номер": df_raw["registration_number"].map(_safe_text),
602
  "h-index": df_raw["h_index"],
603
  "i10-index": df_raw["i10_index"],
@@ -608,7 +606,6 @@ def run_search(
608
  )
609
  df_ui.index.name = "reg_norm"
610
 
611
- # Excel
612
  df_excel_ru = df_raw.reset_index(drop=True).rename(columns=COLUMN_LABELS_RU_EXCEL)
613
  output = io.BytesIO()
614
  with pd.ExcelWriter(output, engine="xlsxwriter") as writer:
@@ -662,11 +659,9 @@ if "last_df_raw" not in st.session_state:
662
  if "last_excel" not in st.session_state:
663
  st.session_state.last_excel = None
664
 
665
- # выбор диссертаций хранится по reg_norm (стабильный ключ)
666
  if "selected_regnorms" not in st.session_state:
667
  st.session_state.selected_regnorms = set()
668
 
669
- # ключ для data_editor (обновляем на новый поиск)
670
  if "search_id" not in st.session_state:
671
  st.session_state.search_id = 0
672
 
@@ -734,10 +729,9 @@ with st.form("search_form"):
734
  with c2:
735
  do_search = st.form_submit_button("🔍 Поиск", type="primary", use_container_width=True)
736
 
737
- # выбранные для отображения колонки (после формы)
738
  visible_ui_cols = [c for c in UI_TABLE_COLUMNS if st.session_state.get(_show_col_key(c), True)]
739
  if not visible_ui_cols:
740
- visible_ui_cols = [c for c in UI_TABLE_COLUMNS if c not in {"Организация", "Тип"}]
741
 
742
  if do_search:
743
  if not candidate_selected and not doctor_selected:
@@ -759,7 +753,6 @@ if do_search:
759
  st.session_state.last_df_raw = df_raw
760
  st.session_state.last_excel = excel_bytes
761
 
762
- # выбор не сбрасываем — оставляем только те, что есть в новых результатах
763
  if isinstance(df_ui, pd.DataFrame) and not df_ui.empty:
764
  st.session_state.selected_regnorms = set(st.session_state.selected_regnorms) & set(df_ui.index)
765
  else:
@@ -777,7 +770,6 @@ if isinstance(df_ui_saved, pd.DataFrame) and not df_ui_saved.empty:
777
  selected_set = set(st.session_state.selected_regnorms) & set(df_ui_saved.index)
778
  st.session_state.selected_regnorms = selected_set
779
 
780
- # таблица + колонка выбора
781
  df_display = df_ui_saved.copy()
782
  df_display.insert(0, "Выбрать", df_display.index.map(lambda x: x in selected_set))
783
 
@@ -830,7 +822,6 @@ if isinstance(df_ui_saved, pd.DataFrame) and not df_ui_saved.empty:
830
  key=f"editor_{st.session_state.search_id}",
831
  )
832
 
833
- # синхронизация выбора
834
  if isinstance(edited, pd.DataFrame) and "Выбрать" in edited.columns:
835
  st.session_state.selected_regnorms = set(edited.index[edited["Выбрать"] == True].tolist())
836
 
 
71
  # - Название диссертации -> ссылка на ВАК (если есть vak_link)
72
  # - после "Год": OpenAlex (ID+ссылка), ORCID (ID+ссылка)
73
  # - Тип по умолчанию скрыт
74
+ # - Регистрационный номер по умолчанию скрыт
75
  # ==========================
76
 
77
  UI_TABLE_COLUMNS = [
 
83
  "Год",
84
  "OpenAlex",
85
  "ORCID",
86
+ "Регистрационный номер",
87
  "h-index",
88
  "i10-index",
89
  "Работ",
90
  "Цитат",
91
  ]
92
 
93
+ # По умолчанию: все включены, кроме "Организация", "Тип" и "Регистрационный номер"
94
+ DEFAULT_VISIBLE_UI = {
95
+ c: (c not in {"Организация", "Тип", "Регистрационный номер"})
96
+ for c in UI_TABLE_COLUMNS
97
+ }
98
 
99
 
100
  # ==========================
 
517
  ):
518
  mask = build_filter_mask(candidate_selected, doctor_selected, science_selected, year_range)
519
 
 
520
  prefetch_k = min(max(int(top_k) * 5, int(top_k)), 500)
521
  results = search_core(query, prefetch_k, mask=mask)
522
 
 
533
 
534
  df_raw["reg_norm"] = df_raw["registration_number"].map(_norm_regnum)
535
 
 
536
  if not oa_enrich.empty:
537
  en = oa_enrich.reindex(df_raw["reg_norm"]).reset_index(drop=True)
538
 
 
544
  df_raw["openalex_url"] = _get("openalex_url", "").map(_norm_openalex_url)
545
  df_raw["orcid_url"] = _get("orcid_url", "").map(_norm_orcid_url)
546
 
547
+ df_raw["h_index"] = pd.to_numeric(_get("h_index", np.nan), errors="coerce").astype("float64")
548
+ df_raw["i10_index"] = pd.to_numeric(_get("i10_index", np.nan), errors="coerce").astype("float64")
549
+ df_raw["works_count"] = pd.to_numeric(_get("works_count", np.nan), errors="coerce").astype("float64")
550
+ df_raw["cited_by_count"] = pd.to_numeric(_get("cited_by_count", np.nan), errors="coerce").astype("float64")
551
  else:
552
  df_raw["openalex_url"] = ""
553
  df_raw["orcid_url"] = ""
554
+ df_raw["h_index"] = np.nan
555
+ df_raw["i10_index"] = np.nan
556
+ df_raw["works_count"] = np.nan
557
+ df_raw["cited_by_count"] = np.nan
558
 
 
559
  if only_openalex:
560
  df_raw = df_raw[df_raw["openalex_url"].map(_safe_text) != ""]
561
  if only_orcid:
 
565
  if len(df_raw) > int(top_k):
566
  df_raw = df_raw.iloc[: int(top_k)].copy()
567
 
 
568
  df_raw["reg_norm"] = df_raw["registration_number"].map(_norm_regnum)
569
  df_raw = df_raw.drop_duplicates(subset=["reg_norm"]).set_index("reg_norm", drop=True)
570
 
 
571
  if "№" in df_raw.columns:
572
  df_raw["№"] = np.arange(1, len(df_raw) + 1)
573
 
 
574
  fio_txt = df_raw["fio"].map(_safe_text)
575
 
576
  title_txt = df_raw["title"].map(_safe_text)
 
589
  df_ui = pd.DataFrame(
590
  {
591
  "Сходство": pd.to_numeric(df_raw["score"], errors="coerce").astype("float64"),
592
+ "ФИО": fio_txt,
593
+ "Название диссертации": title_cell,
594
  "Организация": df_raw["author_org_short"].map(_safe_text),
595
  "Тип": df_raw["dissertation_type"].map(_safe_text),
596
  "Год": pd.to_numeric(df_raw["protection_year"], errors="coerce").astype("float64"),
597
+ "OpenAlex": openalex_cell,
598
+ "ORCID": orcid_cell,
599
  "Регистрационный номер": df_raw["registration_number"].map(_safe_text),
600
  "h-index": df_raw["h_index"],
601
  "i10-index": df_raw["i10_index"],
 
606
  )
607
  df_ui.index.name = "reg_norm"
608
 
 
609
  df_excel_ru = df_raw.reset_index(drop=True).rename(columns=COLUMN_LABELS_RU_EXCEL)
610
  output = io.BytesIO()
611
  with pd.ExcelWriter(output, engine="xlsxwriter") as writer:
 
659
  if "last_excel" not in st.session_state:
660
  st.session_state.last_excel = None
661
 
 
662
  if "selected_regnorms" not in st.session_state:
663
  st.session_state.selected_regnorms = set()
664
 
 
665
  if "search_id" not in st.session_state:
666
  st.session_state.search_id = 0
667
 
 
729
  with c2:
730
  do_search = st.form_submit_button("🔍 Поиск", type="primary", use_container_width=True)
731
 
 
732
  visible_ui_cols = [c for c in UI_TABLE_COLUMNS if st.session_state.get(_show_col_key(c), True)]
733
  if not visible_ui_cols:
734
+ visible_ui_cols = [c for c in UI_TABLE_COLUMNS if c not in {"Организация", "Тип", "Регистрационный номер"}]
735
 
736
  if do_search:
737
  if not candidate_selected and not doctor_selected:
 
753
  st.session_state.last_df_raw = df_raw
754
  st.session_state.last_excel = excel_bytes
755
 
 
756
  if isinstance(df_ui, pd.DataFrame) and not df_ui.empty:
757
  st.session_state.selected_regnorms = set(st.session_state.selected_regnorms) & set(df_ui.index)
758
  else:
 
770
  selected_set = set(st.session_state.selected_regnorms) & set(df_ui_saved.index)
771
  st.session_state.selected_regnorms = selected_set
772
 
 
773
  df_display = df_ui_saved.copy()
774
  df_display.insert(0, "Выбрать", df_display.index.map(lambda x: x in selected_set))
775
 
 
822
  key=f"editor_{st.session_state.search_id}",
823
  )
824
 
 
825
  if isinstance(edited, pd.DataFrame) and "Выбрать" in edited.columns:
826
  st.session_state.selected_regnorms = set(edited.index[edited["Выбрать"] == True].tolist())
827