nikeshn commited on
Commit
6baef5a
·
verified ·
1 Parent(s): 9ac324e

Delete scimago_index.py

Browse files
Files changed (1) hide show
  1. scimago_index.py +0 -158
scimago_index.py DELETED
@@ -1,158 +0,0 @@
1
- """
2
- SCImago CSV loader — builds in-memory ISSN → journal dict at startup.
3
- Used PRIVATELY for quartile lookup only. Never exposed as branded data source in UI.
4
- """
5
- import csv, re, os
6
- from typing import Optional
7
-
8
- _scimago_cache: dict = {}
9
-
10
- def _norm_issn(raw: str) -> Optional[str]:
11
- raw = raw.strip().upper().replace(" ", "")
12
- digits = raw.replace("-", "")
13
- if len(digits) == 8:
14
- return f"{digits[:4]}-{digits[4:]}"
15
- return None
16
-
17
- def load_scimago(csv_path: str = None) -> dict:
18
- global _scimago_cache
19
- if _scimago_cache:
20
- return _scimago_cache
21
- if csv_path is None:
22
- csv_path = os.path.join(os.path.dirname(__file__), "scimagojr_2025.csv")
23
- index = {}
24
- try:
25
- with open(csv_path, encoding="latin-1", newline="") as f:
26
- reader = csv.DictReader(f, delimiter=",")
27
- for row in reader:
28
- issn_raw = row.get("Issn", "")
29
- issn_parts = re.split(r"[,;\s]+", issn_raw)
30
- entry = {
31
- "title": row.get("Title","").strip(),
32
- "rank": row.get("Rank","").strip(),
33
- "quartile": row.get("SJR Best Quartile","").strip(),
34
- "h_index": row.get("H index","").strip(),
35
- "categories": row.get("Categories","").strip(),
36
- "areas": row.get("Areas","").strip(),
37
- "publisher": row.get("Publisher","").strip(),
38
- "open_access":row.get("Open Access","No").strip(),
39
- "country": row.get("Country","").strip(),
40
- }
41
- for part in issn_parts:
42
- normed = _norm_issn(part)
43
- if normed:
44
- index[normed] = entry
45
- _scimago_cache = index
46
- print(f"[SCImago] Loaded {len(index):,} ISSN entries.")
47
- except Exception as e:
48
- print(f"[SCImago] Failed: {e}")
49
- _scimago_cache = {}
50
- return _scimago_cache
51
-
52
- def lookup_any(issns: list) -> Optional[dict]:
53
- index = load_scimago()
54
- for issn in issns:
55
- normed = _norm_issn(str(issn)) if issn else None
56
- if normed and normed in index:
57
- result = dict(index[normed])
58
- result["matched_issn"] = normed
59
- return result
60
- return None
61
-
62
- # ── Subject search index (separate from ISSN index) ──────────────────────
63
- _subject_cache: list = []
64
-
65
- def load_subject_index(csv_path: str = None) -> list:
66
- """Load full journal list for subject browsing — separate from ISSN lookup."""
67
- global _subject_cache
68
- if _subject_cache:
69
- return _subject_cache
70
- if csv_path is None:
71
- csv_path = os.path.join(os.path.dirname(__file__), "scimagojr_2025.csv")
72
- rows = []
73
- seen_titles = set()
74
- try:
75
- with open(csv_path, encoding="latin-1", newline="") as f:
76
- reader = csv.DictReader(f, delimiter=",")
77
- for row in reader:
78
- title = row.get("Title", "").strip()
79
- if not title or title in seen_titles:
80
- continue
81
- seen_titles.add(title)
82
- issn_raw = row.get("Issn", "")
83
- issn_parts = re.split(r"[,;\s]+", issn_raw)
84
- issns = [_norm_issn(p) for p in issn_parts if _norm_issn(p)]
85
- primary_issn = issns[0] if issns else None
86
- try:
87
- h = int(row.get("H index", "0").strip() or 0)
88
- except:
89
- h = 0
90
- rows.append({
91
- "title": title,
92
- "issn": primary_issn,
93
- "quartile": row.get("SJR Best Quartile", "").strip(),
94
- "h_index": h,
95
- "categories": row.get("Categories", "").strip().lower(),
96
- "areas": row.get("Areas", "").strip().lower(),
97
- "publisher": row.get("Publisher", "").strip(),
98
- "open_access":row.get("Open Access", "No").strip(),
99
- "country": row.get("Country", "").strip(),
100
- "rank": row.get("Rank", "").strip(),
101
- })
102
- _subject_cache = rows
103
- print(f"[SCImago] Subject index loaded: {len(rows):,} unique journals.")
104
- except Exception as e:
105
- print(f"[SCImago] Subject index failed: {e}")
106
- _subject_cache = []
107
- return _subject_cache
108
-
109
-
110
- def search_by_subject(category: str, area: str, top_n: int = 15) -> list:
111
- """
112
- Search journals by normalised category + area strings from GPT.
113
- Returns top_n sorted by h_index descending.
114
- Tries: exact category match -> partial category -> area match.
115
- """
116
- rows = load_subject_index()
117
- cat_lower = category.lower().strip() if category else ""
118
- area_lower = area.lower().strip() if area else ""
119
-
120
- def score(r):
121
- cats = r["categories"]
122
- areas = r["areas"]
123
- if cat_lower and cat_lower in cats:
124
- return 3
125
- if cat_lower:
126
- # partial word match
127
- words = [w for w in cat_lower.split() if len(w) > 3]
128
- if any(w in cats for w in words):
129
- return 2
130
- if area_lower and area_lower in areas:
131
- return 1
132
- if area_lower:
133
- words = [w for w in area_lower.split() if len(w) > 3]
134
- if any(w in areas for w in words):
135
- return 1
136
- return 0
137
-
138
- scored = [(score(r), r) for r in rows]
139
- matched = [(s, r) for s, r in scored if s > 0]
140
-
141
- if not matched:
142
- return []
143
-
144
- # Sort: score desc, then h_index desc
145
- matched.sort(key=lambda x: (-x[0], -x[1]["h_index"]))
146
- return [r for _, r in matched[:top_n]]
147
-
148
-
149
- def get_all_areas() -> list:
150
- """Return sorted unique area names for frontend hints."""
151
- rows = load_subject_index()
152
- areas = set()
153
- for r in rows:
154
- for a in r["areas"].split(";"):
155
- a = a.strip().title()
156
- if a:
157
- areas.add(a)
158
- return sorted(areas)