Spaces:
Running
Running
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)
|
|
|
|
| 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." + (
|
| 286 |
-
|
|
|
|
|
|
|
|
|
|
| 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):
|