citation-map 4.3__tar.gz → 4.4__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: 4.3
3
+ Version: 4.4
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
@@ -115,6 +115,8 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
115
115
  generate_citation_map(scholar_id)
116
116
  ```
117
117
 
118
+ Note that in Version 4.4, we support manual edit of the csv. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
119
+
118
120
  Note that in Version 4.0, we will cache the results before identifying affiliations. So if you want to rerun the same author from scratch, you need to delete the cache (default location is 'cache').
119
121
 
120
122
  More input arguments are shown in [the demo script](https://github.com/ChenLiu-1996/CitationMap/blob/main/demo/demo.py).
@@ -203,6 +205,16 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
203
205
  ```
204
206
 
205
207
  ## Changelog
208
+ <details>
209
+ <summary>Version 4.4 (Dec 6, 2024)</summary>
210
+ <br>
211
+
212
+ 1. **Support manual edit of the csv.** Note you do need to manually correct the coordinates too if you choose to use this functionality. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
213
+ 2. Slight optimization on caching.
214
+
215
+ </details>
216
+
217
+
206
218
  <details>
207
219
  <summary>Version 4.0 (Aug 2, 2024)</summary>
208
220
  <br>
@@ -99,6 +99,8 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
99
99
  generate_citation_map(scholar_id)
100
100
  ```
101
101
 
102
+ Note that in Version 4.4, we support manual edit of the csv. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
103
+
102
104
  Note that in Version 4.0, we will cache the results before identifying affiliations. So if you want to rerun the same author from scratch, you need to delete the cache (default location is 'cache').
103
105
 
104
106
  More input arguments are shown in [the demo script](https://github.com/ChenLiu-1996/CitationMap/blob/main/demo/demo.py).
@@ -187,6 +189,16 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
187
189
  ```
188
190
 
189
191
  ## Changelog
192
+ <details>
193
+ <summary>Version 4.4 (Dec 6, 2024)</summary>
194
+ <br>
195
+
196
+ 1. **Support manual edit of the csv.** Note you do need to manually correct the coordinates too if you choose to use this functionality. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
197
+ 2. Slight optimization on caching.
198
+
199
+ </details>
200
+
201
+
190
202
  <details>
191
203
  <summary>Version 4.0 (Aug 2, 2024)</summary>
192
204
  <br>
@@ -14,7 +14,7 @@ from geopy.geocoders import Nominatim
14
14
  from multiprocessing import Pool
15
15
  from scholarly import scholarly, ProxyGenerator
16
16
  from tqdm import tqdm
17
- from typing import Any, Iterable, List, Tuple
17
+ from typing import Any, List, Tuple
18
18
 
19
19
  from .scholarly_support import get_citing_author_ids_and_citing_papers, get_organization_name
20
20
 
@@ -178,9 +178,32 @@ def affiliation_text_to_geocode(author_paper_affiliation_tuple_list: List[Tuple[
178
178
  coordinates_and_info = [item for item in coordinates_and_info if item is not None] # Filter out empty entries.
179
179
  return coordinates_and_info
180
180
 
181
+ def export_dict_to_csv(coordinates_and_info: List[Tuple[str]], csv_output_path: str) -> None:
182
+ '''
183
+ Step 5.1: Export csv file recording citation information.
184
+ '''
185
+
186
+ citation_df = pd.DataFrame(coordinates_and_info,
187
+ columns=['citing author name', 'citing paper title', 'cited paper title',
188
+ 'affiliation', 'latitude', 'longitude',
189
+ 'county', 'city', 'state', 'country'])
190
+
191
+ citation_df.to_csv(csv_output_path)
192
+ return
193
+
194
+ def read_csv_to_dict(csv_path: str) -> None:
195
+ '''
196
+ Step 5.1: Read csv file recording citation information.
197
+ Only relevant if `read_from_csv` is True.
198
+ '''
199
+
200
+ citation_df = pd.read_csv(csv_path, index_col=0)
201
+ coordinates_and_info = list(citation_df.itertuples(index=False, name=None))
202
+ return coordinates_and_info
203
+
181
204
  def create_map(coordinates_and_info: List[Tuple[str]], pin_colorful: bool = True):
182
205
  '''
183
- Step 5.1: Create the Citation World Map.
206
+ Step 5.2: Create the Citation World Map.
184
207
 
185
208
  For authors under the same affiliations, they will be displayed in the same pin.
186
209
  '''
@@ -218,18 +241,6 @@ def create_map(coordinates_and_info: List[Tuple[str]], pin_colorful: bool = True
218
241
  folium.Marker([lat, lon], popup='%s (%s)' % (affiliation_name, ' & '.join(author_name_list))).add_to(citation_map)
219
242
  return citation_map
220
243
 
221
- def export_csv(coordinates_and_info: List[Tuple[str]], csv_output_path: str) -> None:
222
- '''
223
- Step 5.2: Export csv file recording citation information.
224
- '''
225
-
226
- citation_df = pd.DataFrame(coordinates_and_info,
227
- columns=['citing author name', 'citing paper title', 'cited paper title',
228
- 'affiliation', 'latitude', 'longitude',
229
- 'county', 'city', 'state', 'country'])
230
-
231
- citation_df.to_csv(csv_output_path)
232
- return
233
244
 
234
245
  def __fill_publication_metadata(pub):
235
246
  time.sleep(random.uniform(1, 5)) # Random delay to reduce risk of being blocked.
@@ -329,6 +340,7 @@ def load_cache(fpath: str) -> Any:
329
340
  def generate_citation_map(scholar_id: str,
330
341
  output_path: str = 'citation_map.html',
331
342
  csv_output_path: str = 'citation_info.csv',
343
+ parse_csv: bool = False,
332
344
  cache_folder: str = 'cache',
333
345
  affiliation_conservative: bool = False,
334
346
  num_processes: int = 16,
@@ -348,6 +360,9 @@ def generate_citation_map(scholar_id: str,
348
360
  csv_output_path: str
349
361
  (default is 'citation_info.csv')
350
362
  The path to the output csv file.
363
+ parse_csv: bool
364
+ (default is False)
365
+ If True, will directly jump to Step 5.2, using the information loaded from the csv.
351
366
  cache_folder: str
352
367
  (default is 'cache')
353
368
  The folder to save intermediate results, after finding (author, paper) but before finding the affiliations.
@@ -373,85 +388,110 @@ def generate_citation_map(scholar_id: str,
373
388
  If true, print the list of citing affiliations (affiliations of citing authors).
374
389
  '''
375
390
 
376
- if use_proxy:
377
- pg = ProxyGenerator()
378
- pg.FreeProxies()
379
- scholarly.use_proxy(pg)
380
- print('Using proxy.')
391
+ if not parse_csv:
381
392
 
382
- if cache_folder is not None:
383
- cache_path = os.path.join(cache_folder, scholar_id, 'all_citing_author_paper_tuple_list.pkl')
384
- else:
385
- cache_path = None
393
+ if use_proxy:
394
+ pg = ProxyGenerator()
395
+ pg.FreeProxies()
396
+ scholarly.use_proxy(pg)
397
+ print('Using proxy.')
386
398
 
387
- if cache_path is None or not os.path.exists(cache_path):
388
- print('No cache found for this author. Running from scratch.\n')
399
+ if cache_folder is not None:
400
+ cache_path = os.path.join(cache_folder, scholar_id, 'all_citing_author_paper_tuple_list.pkl')
401
+ else:
402
+ cache_path = None
389
403
 
390
- # NOTE: Step 1. Find all publications of the given Google Scholar ID.
391
- # Step 2. Find all citing authors.
392
- all_citing_author_paper_tuple_list = find_all_citing_authors(scholar_id=scholar_id,
393
- num_processes=num_processes)
394
- print('A total of %d citing authors recorded.\n' % len(all_citing_author_paper_tuple_list))
395
- if cache_path is not None and len(all_citing_author_paper_tuple_list) > 0:
396
- save_cache(all_citing_author_paper_tuple_list, cache_path)
397
- print('Saved to cache: %s.\n' % cache_path)
404
+ if cache_path is None or not os.path.exists(cache_path):
405
+ print('No cache found for this author. Finding citing authors from scratch.\n')
398
406
 
399
- else:
400
- print('Cache found. Loading author paper affiliation information from cache.\n')
401
-
402
- # NOTE: Step 1. Find all publications of the given Google Scholar ID.
403
- # Step 2. Find all citing authors.
404
- all_citing_author_paper_tuple_list = load_cache(cache_path)
405
- print('Loaded from cache: %s.\n' % cache_path)
406
- print('A total of %d citing authors loaded.\n' % len(all_citing_author_paper_tuple_list))
407
-
408
- # NOTE: Step 2. Find all citing affiliations.
409
- print('Identifying affiliations using the %s approach.' % ('conservative' if affiliation_conservative else 'aggressive'))
410
- author_paper_affiliation_tuple_list = find_all_citing_affiliations(all_citing_author_paper_tuple_list,
411
- num_processes=num_processes,
412
- affiliation_conservative=affiliation_conservative)
413
- print('\nA total of %d citing affiliations recorded.\n' % len(author_paper_affiliation_tuple_list))
414
- # Take unique tuples.
415
- author_paper_affiliation_tuple_list = list(set(author_paper_affiliation_tuple_list))
407
+ # NOTE: Step 1. Find all publications of the given Google Scholar ID.
408
+ # Step 2. Find all citing authors.
409
+ all_citing_author_paper_tuple_list = find_all_citing_authors(scholar_id=scholar_id,
410
+ num_processes=num_processes)
411
+ print('A total of %d citing authors recorded.\n' % len(all_citing_author_paper_tuple_list))
412
+ if cache_path is not None and len(all_citing_author_paper_tuple_list) > 0:
413
+ save_cache(all_citing_author_paper_tuple_list, cache_path)
414
+ print('Saved to cache: %s.\n' % cache_path)
415
+
416
+ else:
417
+ print('Cache found. Loading author paper information from cache.\n')
418
+ all_citing_author_paper_tuple_list = load_cache(cache_path)
419
+ print('Loaded from cache: %s.\n' % cache_path)
420
+ print('A total of %d citing authors loaded.\n' % len(all_citing_author_paper_tuple_list))
421
+
422
+ if cache_folder is not None:
423
+ cache_path = os.path.join(cache_folder, scholar_id, 'author_paper_affiliation_tuple_list.pkl')
424
+ else:
425
+ cache_path = None
426
+
427
+ if cache_path is None or not os.path.exists(cache_path):
428
+ print('No cache found for this author. Finding citing affiliations from scratch.\n')
429
+
430
+ # NOTE: Step 2. Find all citing affiliations.
431
+ print('Identifying affiliations using the %s approach.' % ('conservative' if affiliation_conservative else 'aggressive'))
432
+ author_paper_affiliation_tuple_list = find_all_citing_affiliations(all_citing_author_paper_tuple_list,
433
+ num_processes=num_processes,
434
+ affiliation_conservative=affiliation_conservative)
435
+ print('\nA total of %d citing affiliations recorded.\n' % len(author_paper_affiliation_tuple_list))
436
+ # Take unique tuples.
437
+ author_paper_affiliation_tuple_list = list(set(author_paper_affiliation_tuple_list))
438
+
439
+ # NOTE: Step 3. Clean the affiliation strings (optional, only used if taking the aggressive approach).
440
+ if print_citing_affiliations:
441
+ if affiliation_conservative:
442
+ print('Taking the conservative approach. Will not need to clean the affiliation names.')
443
+ print('List of all citing authors and affiliations:\n')
444
+ else:
445
+ print('Taking the aggressive approach. Cleaning the affiliation names.')
446
+ print('List of all citing authors and affiliations before cleaning:\n')
447
+ __print_author_and_affiliation(author_paper_affiliation_tuple_list)
448
+ if not affiliation_conservative:
449
+ cleaned_author_paper_affiliation_tuple_list = clean_affiliation_names(author_paper_affiliation_tuple_list)
450
+ if print_citing_affiliations:
451
+ print('List of all citing authors and affiliations after cleaning:\n')
452
+ __print_author_and_affiliation(cleaned_author_paper_affiliation_tuple_list)
453
+ # Use the merged set to maximize coverage.
454
+ author_paper_affiliation_tuple_list += cleaned_author_paper_affiliation_tuple_list
455
+ # Take unique tuples.
456
+ author_paper_affiliation_tuple_list = list(set(author_paper_affiliation_tuple_list))
457
+
458
+ if cache_path is not None and len(author_paper_affiliation_tuple_list) > 0:
459
+ save_cache(author_paper_affiliation_tuple_list, cache_path)
460
+ print('Saved to cache: %s.\n' % cache_path)
416
461
 
417
- # NOTE: Step 3. Clean the affiliation strings (optional, only used if taking the aggressive approach).
418
- if print_citing_affiliations:
419
- if affiliation_conservative:
420
- print('Taking the conservative approach. Will not need to clean the affiliation names.')
421
- print('List of all citing authors and affiliations:\n')
422
462
  else:
423
- print('Taking the aggressive approach. Cleaning the affiliation names.')
424
- print('List of all citing authors and affiliations before cleaning:\n')
425
- __print_author_and_affiliation(author_paper_affiliation_tuple_list)
426
- if not affiliation_conservative:
427
- cleaned_author_paper_affiliation_tuple_list = clean_affiliation_names(author_paper_affiliation_tuple_list)
428
- if print_citing_affiliations:
429
- print('List of all citing authors and affiliations after cleaning:\n')
430
- __print_author_and_affiliation(cleaned_author_paper_affiliation_tuple_list)
431
- # Use the merged set to maximize coverage.
432
- author_paper_affiliation_tuple_list += cleaned_author_paper_affiliation_tuple_list
463
+ print('Cache found. Loading author paper and affiliation information from cache.\n')
464
+ author_paper_affiliation_tuple_list = load_cache(cache_path)
465
+ print('List of all citing authors and affiliations loaded:\n')
466
+ __print_author_and_affiliation(author_paper_affiliation_tuple_list)
467
+
468
+ # NOTE: Step 4. Convert affiliations in plain text to Geocode.
469
+ coordinates_and_info = affiliation_text_to_geocode(author_paper_affiliation_tuple_list)
433
470
  # Take unique tuples.
434
- author_paper_affiliation_tuple_list = list(set(author_paper_affiliation_tuple_list))
471
+ coordinates_and_info = list(set(coordinates_and_info))
435
472
 
436
- # NOTE: Step 4. Convert affiliations in plain text to Geocode.
437
- coordinates_and_info = affiliation_text_to_geocode(author_paper_affiliation_tuple_list)
438
- # Take unique tuples.
439
- coordinates_and_info = list(set(coordinates_and_info))
473
+ # NOTE: Step 5.1. Export csv file recording citation information.
474
+ export_dict_to_csv(coordinates_and_info, csv_output_path)
475
+ print('\nCitation information exported to %s.' % csv_output_path)
440
476
 
441
- # NOTE: Step 5.1. Create the citation world map.
477
+ else:
478
+ print('\nDirectly parsing the csv. Skipping all previous steps.')
479
+ assert os.path.isfile(csv_output_path), '`csv_output_path` is not a file.'
480
+ coordinates_and_info = read_csv_to_dict(csv_output_path)
481
+ print('\nCitation information loaded from %s.' % csv_output_path)
482
+
483
+ # NOTE: Step 5.2. Create the citation world map.
442
484
  citation_map = create_map(coordinates_and_info, pin_colorful=pin_colorful)
443
485
  citation_map.save(output_path)
444
- print('\nMap created and saved at %s.\n' % output_path)
445
-
446
- # NOTE: Step 5.2. Export csv file recording citation information.
447
- export_csv(coordinates_and_info, csv_output_path)
448
- print('\nCitation information exported to %s.' % csv_output_path)
486
+ print('\nHTML map created and saved at %s.\n' % output_path)
449
487
  return
450
488
 
451
489
 
452
490
  if __name__ == '__main__':
453
491
  # Replace this with your Google Scholar ID.
454
492
  scholar_id = '3rDjnykAAAAJ'
455
- generate_citation_map(scholar_id, output_path='citation_map.html', csv_output_path='citation_info.csv',
493
+ generate_citation_map(scholar_id, output_path='citation_map.html',
494
+ csv_output_path='citation_info.csv',
495
+ parse_csv=False,
456
496
  cache_folder='cache', affiliation_conservative=True, num_processes=16,
457
497
  use_proxy=False, pin_colorful=True, print_citing_affiliations=True)
@@ -30,7 +30,7 @@ def get_html_per_citation_page(soup) -> List[str]:
30
30
  citing_authors_and_citing_papers.append((author_id, title))
31
31
  paper_parsed = True
32
32
  if not paper_parsed:
33
- print("[WARNING!] Could not find author links for ", title_text)
33
+ print("[WARNING!] Could not find author links for ", title)
34
34
  else:
35
35
  continue
36
36
  return citing_authors_and_citing_papers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: citation-map
3
- Version: 4.3
3
+ Version: 4.4
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
@@ -115,6 +115,8 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
115
115
  generate_citation_map(scholar_id)
116
116
  ```
117
117
 
118
+ Note that in Version 4.4, we support manual edit of the csv. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
119
+
118
120
  Note that in Version 4.0, we will cache the results before identifying affiliations. So if you want to rerun the same author from scratch, you need to delete the cache (default location is 'cache').
119
121
 
120
122
  More input arguments are shown in [the demo script](https://github.com/ChenLiu-1996/CitationMap/blob/main/demo/demo.py).
@@ -203,6 +205,16 @@ Liu, Chen. "CitationMap: A Python Tool to Identify and Visualize Your Google Sch
203
205
  ```
204
206
 
205
207
  ## Changelog
208
+ <details>
209
+ <summary>Version 4.4 (Dec 6, 2024)</summary>
210
+ <br>
211
+
212
+ 1. **Support manual edit of the csv.** Note you do need to manually correct the coordinates too if you choose to use this functionality. You can run `generate_citation_map` first, and get the csv and HTML. Then, you can manually modify the csv content, and generate an updated HTML by running `generate_citation_map` again with `parse_csv=True`.
213
+ 2. Slight optimization on caching.
214
+
215
+ </details>
216
+
217
+
206
218
  <details>
207
219
  <summary>Version 4.0 (Aug 2, 2024)</summary>
208
220
  <br>
@@ -5,7 +5,7 @@ with open('README.md') as f:
5
5
 
6
6
  setup(
7
7
  name='citation-map',
8
- version='4.3',
8
+ version='4.4',
9
9
  license='CC BY-NC-SA',
10
10
  author='Chen Liu',
11
11
  author_email='chen.liu.cl2482@yale.edu',
File without changes
File without changes