Skip to content

Commit 8665502

Browse files
scival publication lookup added
1 parent 3d28ec9 commit 8665502

File tree

9 files changed

+318
-28
lines changed

9 files changed

+318
-28
lines changed

docs/reference/PublicationLookup.rst

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
pybliometrics.scival.PublicationLookup
2+
======================================
3+
4+
`PublicationLookup()` implements the `Scival Publication Lookup API <https://dev.elsevier.com/documentation/SciValPublicationAPI.wadl>`_.
5+
6+
It accepts any identifier as the main argument which is Scopus ID (the last part of the EID).
7+
8+
.. currentmodule:: pybliometrics.scival
9+
.. contents:: Table of Contents
10+
:local:
11+
12+
Documentation
13+
-------------
14+
15+
.. autoclass:: PublicationLookup
16+
:members:
17+
:inherited-members:
18+
19+
Examples
20+
--------
21+
You initialize the class with an ID that Scopus uses, e.g. the ID:
22+
23+
.. code-block:: python
24+
25+
>>> import pybliometrics
26+
>>> from pybliometrics.scival import PublicationLookup
27+
>>> pybliometrics.scival.init()
28+
>>> pub = PublicationLookup(85036568406)
29+
30+
31+
You can obtain basic information just by printing the object:
32+
33+
.. code-block:: python
34+
35+
>>> print(pub)
36+
- ID: 85036568406
37+
- Title: Soft Electrochemical Probes for Mapping the Distribution of Biomarkers and Injected Nanomaterials in Animal and Human Tissues
38+
- DOI: 10.1002/anie.201709271
39+
- Type: Article
40+
- Year: 2017
41+
- Citation Count: 34
42+
- Source Title: Angewandte Chemie - International Edition
43+
- Topic ID: 7563
44+
- Topic Cluster ID: 157
45+
- Link: https://api.elsevier.com/analytics/scival/publication/85036568406?view=&apiKey=&httpAccept=application/json&insttoken=
46+
- Authors: Lin, T.-E., Lu, Y.-J., Sun, C.-L., Pick, H., Chen, J.-P., Lesch, A., Girault, H.H.
47+
- Institutions: Chang Gung University, Swiss Federal Institute of Technology Lausanne, Chang Gung Memorial Hospital
48+
- SDGs: SDG 3: Good Health and Well-being
49+
50+
51+
You can access different attributes of the publication
52+
53+
.. code-block:: python
54+
55+
>>> pub.id
56+
'85036568406'
57+
>>> pub.type
58+
'Article'
59+
>>> pub.title
60+
'Soft Electrochemical Probes for Mapping the Distribution of Biomarkers and Injected Nanomaterials in Animal and Human Tissues'
61+
>>> pub.doi
62+
'10.1002/anie.201709271'
63+
>>> pub.publication_year
64+
2017
65+
>>> pub.citation_count
66+
34
67+
>>> pub.source_title
68+
'Angewandte Chemie - International Edition'
69+
70+
71+
The attributes `authors`, `institutions` and `sdgs` offer insights into the document's content:
72+
73+
.. code-block:: python
74+
75+
>>> pub.authors
76+
[Author(id=7404861905, name='Lin, T.-E.', link='https://api.elsevier.com/analytics/scival/author/7404861905'),
77+
Author(id=24537666700, name='Lu, Y.-J.', link='https://api.elsevier.com/analytics/scival/author/24537666700'),
78+
Author(id=7404248170, name='Sun, C.-L.', link='https://api.elsevier.com/analytics/scival/author/7404248170'),
79+
Author(id=7004202515, name='Pick, H.', link='https://api.elsevier.com/analytics/scival/author/7004202515'),
80+
Author(id=58307174900, name='Chen, J.-P.', link='https://api.elsevier.com/analytics/scival/author/58307174900'),
81+
Author(id=36246291500, name='Lesch, A.', link='https://api.elsevier.com/analytics/scival/author/36246291500'),
82+
Author(id=7102360867, name='Girault, H.H.', link='https://api.elsevier.com/analytics/scival/author/7102360867')]
83+
84+
>>> pub.institutions
85+
[Institution(id=217002, name='Chang Gung University', country='Taiwan', country_code='TWN', link='https://api.elsevier.com/analytics/scival/institution/217002'),
86+
Institution(id=306002, name='Swiss Federal Institute of Technology Lausanne', country='Switzerland', country_code='CHE', link='https://api.elsevier.com/analytics/scival/institution/306002'), Institution(id=725104, name='Chang Gung Memorial Hospital', country='Taiwan', country_code='TWN', link='https://api.elsevier.com/analytics/scival/institution/725104')]
87+
88+
>>> pub.sdgs
89+
['SDG 3: Good Health and Well-being']
90+
91+
92+
Downloaded results are cached to expedite subsequent analyses. This information may become outdated. To refresh the cached results if they exist, set `refresh=True`, or provide an integer that will be interpreted as maximum allowed number of days since the last modification date. For example, if you want to refresh all cached results older than 100 days, set `refresh=100`. Use `ab.get_cache_file_mdate()` to obtain the date of last modification, and `ab.get_cache_file_age()` to determine the number of days since the last modification.

pybliometrics/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88

99
import pybliometrics.scopus
1010
import pybliometrics.sciencedirect
11+
import pybliometrics.scival

pybliometrics/scival/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from pybliometrics.utils import *
2+
3+
from pybliometrics.scival.publication_lookup import *
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"""Module with the PublicationLookup class."""
2+
from collections import namedtuple
3+
from typing import Union, Optional
4+
5+
from pybliometrics.superclasses import Retrieval
6+
from pybliometrics.utils import make_int_if_possible, chained_get
7+
8+
9+
class PublicationLookup(Retrieval):
10+
11+
@property
12+
def id(self) -> Optional[int]:
13+
"""ID of the document (same as EID without "2-s2.0-")."""
14+
return make_int_if_possible(chained_get(self._json, ['publication', 'id']))
15+
16+
@property
17+
def title(self) -> Optional[str]:
18+
"""Publication title."""
19+
return chained_get(self._json, ['publication', 'title'])
20+
21+
@property
22+
def doi(self) -> Optional[str]:
23+
"""Digital Object Identifier (DOI)."""
24+
return chained_get(self._json, ['publication', 'doi'])
25+
26+
@property
27+
def type(self) -> Optional[str]:
28+
"""Type of publication."""
29+
return chained_get(self._json, ['publication', 'type'])
30+
31+
@property
32+
def publication_year(self) -> Optional[int]:
33+
"""Year of publication."""
34+
return make_int_if_possible(chained_get(self._json, ['publication', 'publicationYear']))
35+
36+
@property
37+
def citation_count(self) -> Optional[int]:
38+
"""Count of citations."""
39+
return make_int_if_possible(chained_get(self._json, ['publication', 'citationCount']))
40+
41+
@property
42+
def source_title(self) -> Optional[str]:
43+
"""Title of source."""
44+
return chained_get(self._json, ['publication', 'sourceTitle'])
45+
46+
@property
47+
def topic_id(self) -> Optional[int]:
48+
"""Topic id."""
49+
return make_int_if_possible(chained_get(self._json, ['publication', 'topicId']))
50+
51+
@property
52+
def topic_cluster_id(self) -> Optional[int]:
53+
"""Topic cluster id."""
54+
return make_int_if_possible(chained_get(self._json, ['publication', 'topicClusterId']))
55+
56+
@property
57+
def link(self) -> Optional[str]:
58+
"""URL link."""
59+
return chained_get(self._json, ['link', '@href'])
60+
61+
@property
62+
def authors(self) -> Optional[list[namedtuple]]:
63+
"""Publication authors."""
64+
out = []
65+
fields = 'id name link'
66+
auth = namedtuple('Author', fields)
67+
for item in chained_get(self._json, ['publication', 'authors'], []):
68+
new = auth(id=make_int_if_possible(item['id']), name=item.get('name'),
69+
link=chained_get(item, ['link', '@href']))
70+
out.append(new)
71+
return out or None
72+
73+
@property
74+
def institutions(self) -> Optional[list[namedtuple]]:
75+
"""Institutions linked to publication authors."""
76+
out = []
77+
fields = 'id name country country_code link'
78+
auth = namedtuple('Institution', fields)
79+
for item in chained_get(self._json, ['publication', 'institutions'], []):
80+
new = auth(id=make_int_if_possible(item['id']), name=item.get('name'), country=item.get('country'),
81+
country_code=item.get('countryCode'), link=chained_get(item, ['link', '@href']))
82+
out.append(new)
83+
return out or None
84+
85+
@property
86+
def sdgs(self) -> Optional[list[str]]:
87+
"""List of Sustainable Development Goals (SDG)."""
88+
return chained_get(self._json, ['publication', 'sdg'])
89+
90+
def __str__(self):
91+
"""Print a summary string."""
92+
authors = ', '.join(a.name for a in self.authors) if self.authors else "N/A"
93+
institutions = ', '.join(i.name for i in self.institutions) if self.institutions else "N/A"
94+
sdgs = ', '.join(self.sdgs) if self.sdgs else "N/A"
95+
s = (f"Publication Summary:\n"
96+
f"- ID: {self.id or 'N/A'}\n"
97+
f"- Title: {self.title or 'N/A'}\n"
98+
f"- DOI: {self.doi or 'N/A'}\n"
99+
f"- Type: {self.type or 'N/A'}\n"
100+
f"- Year: {self.publication_year or 'N/A'}\n"
101+
f"- Citation Count: {self.citation_count or 'N/A'}\n"
102+
f"- Source Title: {self.source_title or 'N/A'}\n"
103+
f"- Topic ID: {self.topic_id or 'N/A'}\n"
104+
f"- Topic Cluster ID: {self.topic_cluster_id or 'N/A'}\n"
105+
f"- Link: {self.link or 'N/A'}\n"
106+
f"- Authors: {authors}\n"
107+
f"- Institutions: {institutions}\n"
108+
f"- SDGs: {sdgs}\n")
109+
return s
110+
111+
def __init__(self, identifier: int = None, refresh: Union[bool, int] = False, **kwds: str) -> None:
112+
"""Interaction with the Publication Lookup API.
113+
:param identifier: The Scopus ID of the object.
114+
:param refresh: Whether to refresh the cached file if it exists. Default: `False`.
115+
:param kwds: Keywords passed on to requests header. Must contain
116+
fields and values specified in the respective
117+
API specification.
118+
"""
119+
self._view = ''
120+
self._refresh = refresh
121+
Retrieval.__init__(self, identifier=str(identifier), **kwds)

pybliometrics/scival/tests/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""Tests for the PublicationLookup() class."""
2+
3+
from pybliometrics.scival import PublicationLookup
4+
from pybliometrics.utils import init
5+
6+
init()
7+
8+
# Base information
9+
pub1 = PublicationLookup(85036568406)
10+
11+
12+
def test_publication_id():
13+
assert pub1.id == 85036568406
14+
15+
16+
def test_publication_doi():
17+
assert pub1.doi == "10.1002/anie.201709271"
18+
19+
20+
def test_publication_type():
21+
assert pub1.type == "Article"
22+
23+
24+
def test_publication_year():
25+
assert pub1.publication_year == 2017
26+
27+
28+
def test_publication_source_title():
29+
assert pub1.source_title == 'Angewandte Chemie - International Edition'
30+
31+
32+
def test_publication_citation_count():
33+
assert pub1.citation_count > 0
34+
35+
36+
def test_publication_authors_count():
37+
assert len(pub1.authors) >= 7
38+
39+
40+
def test_publication_first_author():
41+
assert pub1.authors[0].id == 7404861905
42+
assert pub1.authors[0].name == "Lin, T.-E."
43+
44+
45+
def test_publication_institutions_count():
46+
assert len(pub1.institutions) >= 3
47+
48+
49+
def test_publication_first_institution():
50+
assert pub1.institutions[0].id == 217002
51+
assert pub1.institutions[0].name == "Chang Gung University"
52+
assert pub1.institutions[0].country == "Taiwan"
53+
assert pub1.institutions[0].country_code == "TWN"
54+
55+
56+
def test_publication_sdgs():
57+
assert len(pub1.sdgs) >= 1
58+
assert pub1.sdgs[0] == 'SDG 3: Good Health and Well-being'

pybliometrics/superclasses/retrieval.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,7 @@ def __init__(self,
4747
self._cache_file_path = parent/self._view/stem
4848

4949
# Parse file contents
50-
params = {'view': self._view, **kwds}
50+
params = {**kwds}
51+
if self._view:
52+
params['view'] = self._view
5153
Base.__init__(self, params=params, url=url)

0 commit comments

Comments
 (0)