unknown Claude Opus 5.5 commited on
Commit
ee1736c
·
1 Parent(s): 46373f2

Journal Finder: SCIE / SSCI / AHCI / ESCI lists from Wikidata (open, partial) until Clarivate's lists are added

Browse files
devtools/fetch_wos_wikidata.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Web of Science collection lists (SCIE / SSCI / AHCI / ESCI) from Wikidata ("indexed in bibliographic review",
2
+ P8875), for when Clarivate's Master Journal List downloads are not available. Wikidata is CC0 but incomplete
3
+ (roughly 60-90 % of each collection), so a journal missing here may still be indexed.
4
+
5
+ python devtools/fetch_wos_wikidata.py -> finder/data/wos/wikidata_<COLL>.csv
6
+ """
7
+ import csv
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import requests
12
+
13
+ COLLECTIONS = {"SCIE": "Q104047209", "SSCI": "Q1090953", "AHCI": "Q713927", "ESCI": "Q22908122"}
14
+ OUT = Path(__file__).resolve().parent.parent / "finder" / "data" / "wos"
15
+ QUERY = """SELECT ?j ?title ?issn WHERE {
16
+ ?j p:P8875 ?st . ?st ps:P8875 wd:%s .
17
+ FILTER NOT EXISTS { ?st pq:P582 ?end } # no longer indexed
18
+ ?j wdt:P236 ?issn .
19
+ OPTIONAL { ?j wdt:P1476 ?t } OPTIONAL { ?j rdfs:label ?l FILTER(LANG(?l) = "en") }
20
+ BIND(COALESCE(?t, ?l) AS ?title) }"""
21
+
22
+
23
+ def fetch(qid: str) -> list[tuple[str, str]]:
24
+ r = requests.get("https://query.wikidata.org/sparql", params={"query": QUERY % qid, "format": "json"},
25
+ headers={"User-Agent": "CS-AI-Writing-Suite-Finder/1.0"}, timeout=300)
26
+ r.raise_for_status()
27
+ return [(b.get("title", {}).get("value", ""), b["issn"]["value"]) for b in r.json()["results"]["bindings"]]
28
+
29
+
30
+ def main() -> int:
31
+ OUT.mkdir(parents=True, exist_ok=True)
32
+ for coll, qid in COLLECTIONS.items():
33
+ rows = sorted(set(fetch(qid)))
34
+ with open(OUT / f"wikidata_{coll}.csv", "w", newline="", encoding="utf-8") as f:
35
+ w = csv.writer(f)
36
+ w.writerow(["Journal title", "ISSN"])
37
+ w.writerows(rows)
38
+ print(f"{coll}: {len({i for _, i in rows}):,} ISSNs")
39
+ return 0
40
+
41
+
42
+ if __name__ == "__main__":
43
+ sys.exit(main())
finder/data/wos/wikidata_AHCI.csv ADDED
The diff for this file is too large to render. See raw diff
 
finder/data/wos/wikidata_ESCI.csv ADDED
The diff for this file is too large to render. See raw diff
 
finder/data/wos/wikidata_SCIE.csv ADDED
The diff for this file is too large to render. See raw diff
 
finder/data/wos/wikidata_SSCI.csv ADDED
The diff for this file is too large to render. See raw diff
 
finder_tab.py CHANGED
@@ -30,6 +30,9 @@ MAX_PER_TERM = int(os.getenv("FINDER_MAX", "100"))
30
  AVAILABLE = (FINDER_DIR / "run_job.py").exists()
31
  # the Web of Science lists (Clarivate Master Journal List downloads) in finder/data/wos/
32
  WOS_READY = any((FINDER_DIR / "data" / "wos").glob("*.csv")) or any((FINDER_DIR / "data" / "wos").glob("*.xlsx"))
 
 
 
33
 
34
  def freshen_data_caches():
35
  """The pipeline keeps a parsed copy (.pkl) of each big list (Scopus 20 MB, SCImago, PubMed, ABDC) and trusts
@@ -126,7 +129,8 @@ def _table(csv_path):
126
  if c in df.columns:
127
  df[c] = [("—" if pd.isna(v) else round(float(v), 1 if c == "opportunity_score" else 0)) for v in df[c]]
128
  if "wos" in df.columns:
129
- df["wos"] = ["—" if pd.isna(v) or not str(v).strip() else str(v) for v in df["wos"]]
 
130
  if "in_pubmed" in df.columns:
131
  # (a column with gaps is read as text: "False" must not count as yes)
132
  df["in_pubmed"] = ["yes" if str(v).strip().lower() in ("true", "1", "yes") else "—" for v in df["in_pubmed"]]
@@ -282,8 +286,11 @@ def build(ui=None):
282
  "ESCI (Web of Science)", "PubMed", "ABDC"], value=["Scopus"],
283
  label="Must be listed in",
284
  info="Scopus, PubMed and ABDC: every one you tick. Web of Science: any of the "
285
- "ticked collections." + ("" if WOS_READY else
286
- " (Web of Science lists not installed yet.)"))
 
 
 
287
  quartiles = gr.CheckboxGroup(["Q1", "Q2", "Q3", "Q4"], value=[], label="SJR quartile (empty = any)")
288
  sort_by = gr.Radio(["Best fit", "Fastest acceptance"], value="Best fit", label="Rank by")
289
  with gr.Accordion("⚙️ More options (not needed)", open=False):
 
30
  AVAILABLE = (FINDER_DIR / "run_job.py").exists()
31
  # the Web of Science lists (Clarivate Master Journal List downloads) in finder/data/wos/
32
  WOS_READY = any((FINDER_DIR / "data" / "wos").glob("*.csv")) or any((FINDER_DIR / "data" / "wos").glob("*.xlsx"))
33
+ # only the Wikidata copy (devtools/fetch_wos_wikidata.py): good but incomplete, so say so
34
+ WOS_PARTIAL = WOS_READY and all(f.name.startswith("wikidata_") for f in (FINDER_DIR / "data" / "wos").iterdir()
35
+ if f.suffix.lower() in (".csv", ".xlsx"))
36
 
37
  def freshen_data_caches():
38
  """The pipeline keeps a parsed copy (.pkl) of each big list (Scopus 20 MB, SCImago, PubMed, ABDC) and trusts
 
129
  if c in df.columns:
130
  df[c] = [("—" if pd.isna(v) else round(float(v), 1 if c == "opportunity_score" else 0)) for v in df[c]]
131
  if "wos" in df.columns:
132
+ df["wos"] = [("not listed" if WOS_PARTIAL else "—") if pd.isna(v) or not str(v).strip() else str(v)
133
+ for v in df["wos"]]
134
  if "in_pubmed" in df.columns:
135
  # (a column with gaps is read as text: "False" must not count as yes)
136
  df["in_pubmed"] = ["yes" if str(v).strip().lower() in ("true", "1", "yes") else "—" for v in df["in_pubmed"]]
 
286
  "ESCI (Web of Science)", "PubMed", "ABDC"], value=["Scopus"],
287
  label="Must be listed in",
288
  info="Scopus, PubMed and ABDC: every one you tick. Web of Science: any of the "
289
+ "ticked collections." + (
290
+ " (Web of Science lists not installed yet.)" if not WOS_READY else
291
+ " Web of Science status comes from Wikidata's open list, which misses "
292
+ "some indexed journals: confirm on mjl.clarivate.com before submitting."
293
+ if WOS_PARTIAL else ""))
294
  quartiles = gr.CheckboxGroup(["Q1", "Q2", "Q3", "Q4"], value=[], label="SJR quartile (empty = any)")
295
  sort_by = gr.Radio(["Best fit", "Fastest acceptance"], value="Best fit", label="Rank by")
296
  with gr.Accordion("⚙️ More options (not needed)", open=False):