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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: citation-map
3
- Version: 3.7
3
+ Version: 3.8
4
4
  Summary: A simple tool to generate your Google Scholar citation world map.
5
5
  Home-page: https://github.com/ChenLiu-1996/CitationMap
6
6
  Author: Chen Liu
@@ -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. Final all citing institutions (i.e., insitutions of citing authors).
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...', total=len(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...', total=len(all_publication_ids)):
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...', total=len(all_citing_authors)):
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]], num_processes: int = 32) -> 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
- if num_processes > 1 and isinstance(num_processes, int):
98
- with Pool(processes=num_processes) as pool:
99
- coordinates = list(tqdm(pool.imap(__text_to_geocode, author_institution_tuple_list),
100
- desc='Finding all geographic coordinates...',
101
- total=len(author_institution_tuple_list)))
102
- else:
103
- coordinates = []
104
- for author_institution_tuple in tqdm(author_institution_tuple_list,
105
- desc='Finding all geographic coordinates...',
106
- total=len(author_institution_tuple_list)):
107
- coordinates.append(__text_to_geocode(author_institution_tuple))
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: citation-map
3
- Version: 3.7
3
+ Version: 3.8
4
4
  Summary: A simple tool to generate your Google Scholar citation world map.
5
5
  Home-page: https://github.com/ChenLiu-1996/CitationMap
6
6
  Author: Chen Liu
@@ -5,7 +5,7 @@ with open('README.md') as f:
5
5
 
6
6
  setup(
7
7
  name='citation-map',
8
- version='3.7',
8
+ version='3.8',
9
9
  license='Apache 2.0',
10
10
  author='Chen Liu',
11
11
  author_email='chen.liu.cl2482@yale.edu',
File without changes
File without changes
File without changes