citation-map 3.7__tar.gz → 3.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {citation-map-3.7 → citation-map-3.8}/PKG-INFO +1 -1
- {citation-map-3.7 → citation-map-3.8}/citation_map/citation_map.py +40 -38
- {citation-map-3.7 → citation-map-3.8}/citation_map.egg-info/PKG-INFO +1 -1
- {citation-map-3.7 → citation-map-3.8}/setup.py +1 -1
- {citation-map-3.7 → citation-map-3.8}/LICENSE.md +0 -0
- {citation-map-3.7 → citation-map-3.8}/README.md +0 -0
- {citation-map-3.7 → citation-map-3.8}/citation_map/__init__.py +0 -0
- {citation-map-3.7 → citation-map-3.8}/citation_map/scholarly_support.py +0 -0
- {citation-map-3.7 → citation-map-3.8}/citation_map.egg-info/SOURCES.txt +0 -0
- {citation-map-3.7 → citation-map-3.8}/citation_map.egg-info/dependency_links.txt +0 -0
- {citation-map-3.7 → citation-map-3.8}/citation_map.egg-info/requires.txt +0 -0
- {citation-map-3.7 → citation-map-3.8}/citation_map.egg-info/top_level.txt +0 -0
- {citation-map-3.7 → citation-map-3.8}/setup.cfg +0 -0
|
@@ -24,46 +24,48 @@ def fetch_google_scholar_profile(scholar_id: str):
|
|
|
24
24
|
|
|
25
25
|
def find_all_citing_institutions(publications, num_processes: int = 16) -> List[Tuple[str]]:
|
|
26
26
|
'''
|
|
27
|
-
Step 2.
|
|
27
|
+
Step 2. Find all citing institutions (i.e., insitutions of citing authors).
|
|
28
28
|
'''
|
|
29
|
+
# Fetch metadata for all publications.
|
|
29
30
|
if num_processes > 1 and isinstance(num_processes, int):
|
|
30
|
-
# Fetch metadata for all publications, in parallel.
|
|
31
31
|
with Pool(processes=num_processes) as pool:
|
|
32
32
|
all_publications = list(tqdm(pool.imap(__fill_publication_metadata, publications),
|
|
33
|
-
desc='Filling metadata for all publications
|
|
33
|
+
desc='Filling metadata for all publications',
|
|
34
34
|
total=len(publications)))
|
|
35
35
|
else:
|
|
36
36
|
all_publications = []
|
|
37
|
-
for pub in tqdm(publications, desc='Filling metadata for all publications
|
|
37
|
+
for pub in tqdm(publications, desc='Filling metadata for all publications', total=len(publications)):
|
|
38
38
|
all_publications.append(__fill_publication_metadata(pub))
|
|
39
39
|
|
|
40
|
+
# Convert all publications to Google Scholar publication IDs.
|
|
41
|
+
# This is fast and no parallel processing is needed.
|
|
40
42
|
all_publication_ids = []
|
|
41
43
|
for pub in all_publications:
|
|
42
44
|
if 'cites_id' in pub:
|
|
43
45
|
for cites_id in pub['cites_id']:
|
|
44
46
|
all_publication_ids.append(cites_id)
|
|
45
47
|
|
|
48
|
+
# Find all citing authors from all publications.
|
|
46
49
|
if num_processes > 1 and isinstance(num_processes, int):
|
|
47
|
-
# Find all citing papers from all publications, in parallel.
|
|
48
50
|
with Pool(processes=num_processes) as pool:
|
|
49
51
|
all_citing_authors_nested = list(tqdm(pool.imap(__citing_author_ids_from_publication, all_publication_ids),
|
|
50
|
-
desc='Finding all citing authors
|
|
52
|
+
desc='Finding all citing authors from cited publications',
|
|
51
53
|
total=len(all_publication_ids)))
|
|
52
54
|
else:
|
|
53
55
|
all_citing_authors_nested = []
|
|
54
|
-
for pub in tqdm(all_publication_ids, desc='Finding all citing authors
|
|
56
|
+
for pub in tqdm(all_publication_ids, desc='Finding all citing authors from cited publications', total=len(all_publication_ids)):
|
|
55
57
|
all_citing_authors_nested.append(__citing_author_ids_from_publication(pub))
|
|
56
58
|
all_citing_authors = list(itertools.chain(*all_citing_authors_nested))
|
|
57
59
|
|
|
60
|
+
# Find all citing insitutions from all citing authors.
|
|
58
61
|
if num_processes > 1 and isinstance(num_processes, int):
|
|
59
|
-
# Find all citing insitutions from all citing authors, in parallel.
|
|
60
62
|
with Pool(processes=num_processes) as pool:
|
|
61
63
|
author_institution_tuple_list = list(tqdm(pool.imap(__institutions_from_authors, all_citing_authors),
|
|
62
|
-
desc='Finding all citing institutions
|
|
64
|
+
desc='Finding all citing institutions from citing authors',
|
|
63
65
|
total=len(all_citing_authors)))
|
|
64
66
|
else:
|
|
65
67
|
author_institution_tuple_list = []
|
|
66
|
-
for author in tqdm(all_citing_authors, desc='Finding all citing institutions
|
|
68
|
+
for author in tqdm(all_citing_authors, desc='Finding all citing institutions from citing authors', total=len(all_citing_authors)):
|
|
67
69
|
author_institution_tuple_list.append(__institutions_from_authors(author))
|
|
68
70
|
|
|
69
71
|
return author_institution_tuple_list
|
|
@@ -71,6 +73,8 @@ def find_all_citing_institutions(publications, num_processes: int = 16) -> List[
|
|
|
71
73
|
def clean_institution_names(author_institution_tuple_list: List[Tuple[str]]) -> List[Tuple[str]]:
|
|
72
74
|
'''
|
|
73
75
|
Step 3. Clean up the name of institutions from the author's self-entered Google Scholar affiliation.
|
|
76
|
+
NOTE: This logic is very naive. Please send an issue or pull request if you have any idea how to improve it.
|
|
77
|
+
Currently we will not consider any paid service or tools that pose extra burden on the users, such as GPT API.
|
|
74
78
|
'''
|
|
75
79
|
cleaned_author_institution_tuple_list = []
|
|
76
80
|
for author_name, institution_string in author_institution_tuple_list:
|
|
@@ -90,22 +94,26 @@ def clean_institution_names(author_institution_tuple_list: List[Tuple[str]]) ->
|
|
|
90
94
|
cleaned_author_institution_tuple_list.append((author_name, cleaned_institution))
|
|
91
95
|
return cleaned_author_institution_tuple_list
|
|
92
96
|
|
|
93
|
-
def institution_text_to_geocode(author_institution_tuple_list: List[Tuple[str]],
|
|
97
|
+
def institution_text_to_geocode(author_institution_tuple_list: List[Tuple[str]], max_attempts: int = 3) -> List[Tuple[str]]:
|
|
94
98
|
'''
|
|
95
99
|
Step 4: Convert institutions in plain text to Geocode.
|
|
96
100
|
'''
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
101
|
+
coordinates = []
|
|
102
|
+
# NOTE: According to the Nomatim Usage Policy (https://operations.osmfoundation.org/policies/nominatim/),
|
|
103
|
+
# we are explicitly asked not to submit bulk requests on multiple threads.
|
|
104
|
+
# Therefore, we will keep it to a loop instead of multiprocessing.
|
|
105
|
+
geolocator = Nominatim(user_agent='citation_mapper')
|
|
106
|
+
for author_institution_tuple in tqdm(author_institution_tuple_list,
|
|
107
|
+
desc='Finding all geographic coordinates from citing institutions',
|
|
108
|
+
total=len(author_institution_tuple_list)):
|
|
109
|
+
for _ in range(max_attempts):
|
|
110
|
+
try:
|
|
111
|
+
author_name, institution_name = author_institution_tuple
|
|
112
|
+
geo_location = geolocator.geocode(institution_name)
|
|
113
|
+
if geo_location:
|
|
114
|
+
coordinates.append((geo_location.latitude, geo_location.longitude, author_name, institution_name))
|
|
115
|
+
except:
|
|
116
|
+
continue
|
|
109
117
|
coordinates = [item for item in coordinates if item is not None] # Filter out empty coordinates.
|
|
110
118
|
return coordinates
|
|
111
119
|
|
|
@@ -139,22 +147,11 @@ def __citing_author_ids_from_publication(cites_id: str):
|
|
|
139
147
|
def __institutions_from_authors(author_id: str):
|
|
140
148
|
time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
|
|
141
149
|
citing_author = scholarly.search_author_id(author_id)
|
|
142
|
-
citing_author = scholarly.fill(citing_author)
|
|
150
|
+
# citing_author = scholarly.fill(citing_author)
|
|
143
151
|
if 'affiliation' in citing_author:
|
|
144
152
|
return (citing_author['name'], citing_author['affiliation'])
|
|
145
153
|
return []
|
|
146
154
|
|
|
147
|
-
def __text_to_geocode(author_institution_tuple, max_attempts: int = 3):
|
|
148
|
-
geolocator = Nominatim(user_agent='citation_mapper')
|
|
149
|
-
for _ in range(max_attempts):
|
|
150
|
-
try:
|
|
151
|
-
author_name, institution_name = author_institution_tuple
|
|
152
|
-
geo_location = geolocator.geocode(institution_name)
|
|
153
|
-
if geo_location:
|
|
154
|
-
return (geo_location.latitude, geo_location.longitude, author_name, institution_name)
|
|
155
|
-
except:
|
|
156
|
-
pass
|
|
157
|
-
return None
|
|
158
155
|
|
|
159
156
|
def generate_citation_map(scholar_id: str,
|
|
160
157
|
output_path: str = 'citation_map.html',
|
|
@@ -201,20 +198,25 @@ def generate_citation_map(scholar_id: str,
|
|
|
201
198
|
num_processes=num_processes)
|
|
202
199
|
print('\nA total of %d citing institutions recorded.\n' % len(author_institution_tuple_list))
|
|
203
200
|
|
|
201
|
+
# Take unique tuples.
|
|
202
|
+
author_institution_tuple_list = list(set(author_institution_tuple_list))
|
|
203
|
+
|
|
204
204
|
if print_citing_institutions:
|
|
205
205
|
print('\nList of all citing authors and institutions before cleaning:\n')
|
|
206
|
-
for item in sorted(author_institution_tuple_list):
|
|
206
|
+
for item in sorted((author_institution_tuple_list)):
|
|
207
207
|
print(item)
|
|
208
208
|
|
|
209
209
|
cleaned_author_institution_tuple_list = clean_institution_names(author_institution_tuple_list)
|
|
210
210
|
|
|
211
|
+
# Take unique tuples.
|
|
212
|
+
cleaned_author_institution_tuple_list = list(set(cleaned_author_institution_tuple_list))
|
|
213
|
+
|
|
211
214
|
if print_citing_institutions:
|
|
212
215
|
print('\nList of all citing authors and institutions after cleaning:\n')
|
|
213
216
|
for item in sorted(cleaned_author_institution_tuple_list):
|
|
214
217
|
print(item)
|
|
215
218
|
|
|
216
|
-
coordinates = institution_text_to_geocode(author_institution_tuple_list + cleaned_author_institution_tuple_list
|
|
217
|
-
num_processes=num_processes)
|
|
219
|
+
coordinates = institution_text_to_geocode(author_institution_tuple_list + cleaned_author_institution_tuple_list)
|
|
218
220
|
print('\nConverted the institutions to %d Geocodes.' % len(coordinates))
|
|
219
221
|
|
|
220
222
|
citation_map = create_map(coordinates, pin_colorful=pin_colorful)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|