Skip to content

Commit c39f8d9

Browse files
authored
Merge pull request #11 from SIMEXP/iss10
Iss10: publications
2 parents 0aad6fc + a219498 commit c39f8d9

File tree

7 files changed

+238
-2
lines changed

7 files changed

+238
-2
lines changed

.github/workflows/deploy-book.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ name: deploy-book
44
on:
55
push:
66
branches:
7-
- main
8-
7+
- main
8+
99
# This job installs dependencies, build the book, and pushes it to `gh-pages`
1010
jobs:
1111
deploy-book:
@@ -23,6 +23,11 @@ jobs:
2323
run: |
2424
pip install -r content/requirements.txt
2525
26+
# Fetch ORCID records
27+
- name: Fetch ORCID records
28+
run: |
29+
cd content; python orcid_to_bib.py
30+
2631
# Build the page
2732
- name: Build the book
2833
run: |

content/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
_build
2+
orcid_works_*.bib

content/_config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
title: SIMEXP lab
55
author: SIMEXP lab team
66
logo: images/simexp.png
7+
bibtex_bibfiles:
8+
- orcid_works_article.bib
9+
- orcid_works_inproceedings.bib
10+
- orcid_works_unpublished.bib
11+
- orcid_works_misc.bib
712

813
# Force re-execution of notebooks on each build.
914
# See https://jupyterbook.org/content/execute.html

content/_toc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ chapters:
88
- file: coc
99
- file: members
1010
- file: CONTRIBUTING
11+
- file: publications

content/orcid_to_bib.py

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import hashlib
2+
import requests
3+
from tqdm import tqdm
4+
5+
# Hardcoded ORCID ID
6+
ORCID_ID = '0000-0002-9111-0699'
7+
8+
def infer_preprint_server(doi_url):
9+
if 'doi.org/10.31234' in doi_url:
10+
return 'OSF'
11+
if 'doi.org/10.1101' in doi_url:
12+
return 'bioRxiv'
13+
if 'doi.org/10.31730' in doi_url:
14+
return 'PsyArXiv'
15+
if 'doi.org/10.55458' in doi_url:
16+
return 'Neurolibre'
17+
# Add more DOI prefixes as needed
18+
return 'Unknown'
19+
20+
def infer_proceedings_venue(doi_url):
21+
if 'doi.org/10.1145' in doi_url:
22+
return 'ACM Digital Library'
23+
# Add more DOI prefixes as needed
24+
return ''
25+
26+
def extract_first_author(detailed_work):
27+
if detailed_work and 'contributors' in detailed_work:
28+
contributors = detailed_work['contributors'].get('contributor', [])
29+
for contributor in contributors:
30+
if 'contributor-attributes' in contributor and contributor['contributor-attributes'] and contributor['contributor-attributes'].get('contributor-sequence') == 'first':
31+
if 'credit-name' in contributor and contributor['credit-name']:
32+
return contributor['credit-name']['value'].split()[-1]
33+
if contributors:
34+
first_contributor = contributors[0]
35+
if 'credit-name' in first_contributor and first_contributor['credit-name']:
36+
return first_contributor['credit-name']['value'].split()[-1]
37+
return 'unknown'
38+
39+
def sanitize_key(key):
40+
return key.replace(' ', '_').replace(',', '').replace(':', '').replace('.', '').replace('-', '_')
41+
42+
def generate_unique_id(work, detailed_work, entry_type):
43+
try:
44+
title = work['title']['title']['value']
45+
year = work.get('publication-date', {}).get('year', {}).get('value', '')
46+
first_author = extract_first_author(detailed_work)
47+
48+
if entry_type == 'unpublished':
49+
venue = 'preprint'
50+
else:
51+
venue = work.get('journal-title', {}).get('value', 'misc') if work.get('journal-title') else 'misc'
52+
53+
title_hash = hashlib.md5(title.encode('utf-8')).hexdigest()[:8]
54+
raw_key = f"{first_author}-{venue}-{year}-{title_hash}"
55+
return sanitize_key(raw_key)
56+
except Exception as e:
57+
print(f"Error generating unique ID: {e}")
58+
return 'unknown_id'
59+
60+
def construct_bibtex_entry(work, detailed_work):
61+
try:
62+
entry_type_map = {
63+
'journal-article': 'article',
64+
'book-chapter': 'incollection',
65+
'conference-paper': 'inproceedings',
66+
'preprint': 'unpublished',
67+
# Add more mappings as needed
68+
}
69+
70+
entry_type = entry_type_map.get(work.get('type', 'misc'), 'misc')
71+
unique_id = generate_unique_id(work, detailed_work, entry_type)
72+
title = work['title']['title']['value']
73+
journal = work.get('journal-title', {}).get('value', '') if work.get('journal-title') else ''
74+
year = work.get('publication-date', {}).get('year', {}).get('value', '') if work.get('publication-date') else ''
75+
url = work.get('url', {}).get('value', '') if work.get('url') else ''
76+
authors = []
77+
if detailed_work and 'contributors' in detailed_work:
78+
for contributor in detailed_work['contributors'].get('contributor', []):
79+
if 'credit-name' in contributor and contributor['credit-name']:
80+
authors.append(contributor['credit-name']['value'])
81+
elif 'contributor-orcid' in contributor and contributor['contributor-orcid']:
82+
authors.append(contributor['contributor-orcid']['path'])
83+
84+
# Retrieve preprint server or proceedings venue
85+
note = ''
86+
booktitle = ''
87+
if entry_type == 'unpublished' and url:
88+
preprint_server = infer_preprint_server(url)
89+
note = f"{preprint_server} preprint"
90+
elif entry_type == 'inproceedings':
91+
booktitle = work.get('journal-title', {}).get('value', '')
92+
if not booktitle:
93+
booktitle = infer_proceedings_venue(url)
94+
if booktitle == 'ACM Digital Library':
95+
booktitle = 'Proceedings of the ACM Digital Library'
96+
97+
bibtex_entry = f"@{entry_type}{{{unique_id},\n"
98+
bibtex_entry += f" title = {{{title}}},\n"
99+
if journal:
100+
bibtex_entry += f" journal = {{{journal}}},\n"
101+
if note:
102+
bibtex_entry += f" note = {{{note}}},\n"
103+
if booktitle:
104+
bibtex_entry += f" booktitle = {{{booktitle}}},\n"
105+
if year:
106+
bibtex_entry += f" year = {{{year}}},\n"
107+
if url:
108+
bibtex_entry += f" url = {{{url}}},\n"
109+
if authors:
110+
author_list = ' and '.join(authors)
111+
bibtex_entry += f" author = {{{author_list}}},\n"
112+
bibtex_entry += "}\n"
113+
return bibtex_entry
114+
except Exception as e:
115+
print(f"Error constructing BibTeX entry: {e}")
116+
return ''
117+
118+
def fetch_detailed_work(orcid_id, put_code):
119+
try:
120+
url = f'https://pub.orcid.org/v3.0/{orcid_id}/work/{put_code}'
121+
headers = {
122+
'Accept': 'application/json'
123+
}
124+
response = requests.get(url, headers=headers)
125+
if response.status_code == 200:
126+
return response.json()
127+
else:
128+
raise Exception(f"Failed to retrieve detailed work. HTTP Status code: {response.status_code}")
129+
except Exception as e:
130+
print(f"Error fetching detailed work: {e}")
131+
return None
132+
133+
def fetch_orcid_works(orcid_id):
134+
url = f'https://pub.orcid.org/v3.0/{orcid_id}/works'
135+
headers = {
136+
'Accept': 'application/json'
137+
}
138+
response = requests.get(url, headers=headers)
139+
if response.status_code == 200:
140+
works = response.json()['group']
141+
bib_entries = {
142+
'article': [],
143+
'unpublished': [],
144+
'incollection': [],
145+
'inproceedings': [],
146+
'misc': []
147+
}
148+
ignored_entries = []
149+
entry_type_map = {
150+
'journal-article': 'article',
151+
'book-chapter': 'incollection',
152+
'conference-paper': 'inproceedings',
153+
'preprint': 'unpublished',
154+
# Add more mappings as needed
155+
}
156+
for work_group in tqdm(works, desc="Fetching works", unit="work"):
157+
work_summary = work_group['work-summary'][0]
158+
try:
159+
detailed_work = fetch_detailed_work(orcid_id, work_summary['put-code'])
160+
if detailed_work:
161+
bibtex_entry = construct_bibtex_entry(work_summary, detailed_work)
162+
if bibtex_entry:
163+
entry_type = work_summary.get('type', 'misc')
164+
entry_type_key = entry_type_map.get(entry_type, 'misc')
165+
bib_entries[entry_type_key].append(bibtex_entry)
166+
else:
167+
ignored_entries.append((work_summary, 'BibTeX entry construction failed'))
168+
else:
169+
ignored_entries.append((work_summary, 'Detailed work fetch failed'))
170+
except Exception as e:
171+
print(f"Error: {e}")
172+
ignored_entries.append((work_summary, str(e)))
173+
return bib_entries, ignored_entries
174+
else:
175+
raise Exception(f"Failed to retrieve works. HTTP Status code: {response.status_code}")
176+
177+
def save_bibtex_files(bib_entries):
178+
for entry_type, entries in bib_entries.items():
179+
with open(f'orcid_works_{entry_type}.bib', 'w') as bib_file:
180+
bib_file.write('\n\n'.join(entries))
181+
182+
def main():
183+
orcid_id = ORCID_ID
184+
bib_entries, ignored_entries = fetch_orcid_works(orcid_id)
185+
save_bibtex_files(bib_entries)
186+
print("BibTeX files updated successfully.")
187+
188+
if ignored_entries:
189+
print("\nWarning: Some entries were ignored due to errors.")
190+
for entry, error in ignored_entries:
191+
print(f"\nEntry: {entry}")
192+
print(f"Error: {error}")
193+
194+
if __name__ == "__main__":
195+
main()

content/publications.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Publications
2+
3+
Here is a list of publications from the laboratory, which is automatically generated from the [ORCID record](https://orcid.org/0000-0002-9111-0699) of Dr Bellec:
4+
5+
## Journal articles
6+
```{bibliography} orcid_works_article.bib
7+
:filter: (year >= "2010")
8+
:style: unsrtalpha
9+
```
10+
11+
## Proceedings
12+
```{bibliography} orcid_works_inproceedings.bib
13+
:filter: (year >= "2010")
14+
:style: unsrtalpha
15+
```
16+
17+
## Preprints
18+
```{bibliography} orcid_works_unpublished.bib
19+
:filter: (year >= "2010")
20+
:style: unsrtalpha
21+
```
22+
23+
## Misc
24+
```{bibliography} orcid_works_misc.bib
25+
:filter: (year >= "2010")
26+
:style: unsrtalpha
27+
```

content/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ jupyter-book
22
matplotlib
33
numpy
44
sphinx_design
5+
requests
6+
tqdm

0 commit comments

Comments
 (0)