Source code for pybliometrics.scival.author_metrics

from typing import NamedTuple

from pybliometrics.superclasses import Retrieval
from pybliometrics.utils import make_int_if_possible
from pybliometrics.utils.constants import SCIVAL_METRICS
from pybliometrics.utils.parse_metrics import extract_metric_data, MetricData


class Author(NamedTuple):
    """Named tuple representing an author."""
    id: int | None
    name: str | None
    uri: str | None


[docs] class AuthorMetrics(Retrieval): @property def AcademicCorporateCollaboration(self) -> list[MetricData] | None: """Academic corporate collaboration metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'AcademicCorporateCollaboration', self._by_year, "author") @property def AcademicCorporateCollaborationImpact(self) -> list[MetricData] | None: """Academic corporate collaboration impact metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'AcademicCorporateCollaborationImpact', self._by_year, "author") @property def authors(self) -> list[MetricData] | None: """A list of namedtuples representing authors and their basic info in the form `(id, name, uri)`. """ out = [] # Handle both dict and direct access to results if isinstance(self._json, dict): results = self._json.get('results', []) else: results = [] for result in results: author_data = result.get('author', {}) new = Author( id=make_int_if_possible(author_data.get('id')), name=author_data.get('name'), uri=author_data.get('uri') ) out.append(new) return out or None @property def CitationCount(self) -> list[MetricData] | None: """Citation count metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'CitationCount', self._by_year, "author") @property def CitationsPerPublication(self) -> list[MetricData] | None: """Citations per publication metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'CitationsPerPublication', self._by_year, "author") @property def CitedPublications(self) -> list[MetricData] | None: """Cited publications metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'CitedPublications', self._by_year, "author") @property def Collaboration(self) -> list[MetricData] | None: """Collaboration metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'Collaboration', self._by_year, "author") @property def CollaborationImpact(self) -> list[MetricData] | None: """Collaboration impact metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'CollaborationImpact', self._by_year, "author") @property def FieldWeightedCitationImpact(self) -> list[MetricData] | None: """Field weighted citation impact metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'FieldWeightedCitationImpact', self._by_year, "author") @property def HIndices(self) -> list[MetricData] | None: """H-indices metrics for each author (only available when by_year=False). Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'HIndices', self._by_year, "author") @property def OutputsInTopCitationPercentiles(self) -> list[MetricData] | None: """Outputs in top citation percentiles metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'OutputsInTopCitationPercentiles', self._by_year, "author") @property def PublicationsInTopJournalPercentiles(self) -> list[MetricData] | None: """Publications in top journal percentiles metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'PublicationsInTopJournalPercentiles', self._by_year, "author") @property def ScholarlyOutput(self) -> list[MetricData] | None: """Scholarly output metrics for each author. Returns list of MetricData namedtuples with structure: (entity_id, entity_name, metric, year, value, percentage, threshold). """ return extract_metric_data(self._json, 'ScholarlyOutput', self._by_year, "author") def __init__(self, author_ids: str | list, metric_types: str | list | None = None, by_year: bool = False, refresh: bool | int = False, **kwds: str ) -> None: """Interaction with the SciVal Author Metrics API. :param author_ids: Scopus Author ID(s). Can be a single ID or comma-separated string of IDs, or a list of IDs (e.g. `[55586732900, 57215631099]`). :param metric_types: Metric type(s) to retrieve. Can be a single metric or comma-separated string, or a list. Available metrics are: AcademicCorporateCollaboration, AcademicCorporateCollaborationImpact, CitationCount, CitedPublications, Collaboration, CollaborationImpact, FieldWeightedCitationImpact, ScholarlyOutput, PublicationsInTopJournalPercentiles, OutputsInTopCitationPercentiles, HIndices. If not provided, all metrics are retrieved. :param by_year: Whether to retrieve metrics broken down by year. :param refresh: Whether to refresh the cached file if it exists or not. If int is passed, cached file will be refreshed if the number of days since last modification exceeds that value. :param kwds: Keywords passed on as query parameters. Must contain fields and values mentioned in the API specification at https://dev.elsevier.com/documentation/SciValAuthorAPI.wadl. Note: All metric properties return lists of MetricData namedtuples with structure: `(entity_id, entity_name, metric, year, value, percentage, threshold)` which enable concatenation of results from different metrics. """ self._view = '' self._refresh = refresh self._by_year = by_year # Handle authors parameter if isinstance(author_ids, list): author_ids = ",".join(str(a) for a in author_ids) # Handle metric_types parameter - use all metrics by default if metric_types is None: if not by_year: metric_types = SCIVAL_METRICS["AuthorMetrics"]["byYear"] + SCIVAL_METRICS["AuthorMetrics"]["notByYear"] if by_year: metric_types = SCIVAL_METRICS["AuthorMetrics"]["byYear"] if isinstance(metric_types, list): metric_types = ",".join(metric_types) self._metric_types = metric_types # Set up parameters for the API call params = { 'authors': author_ids, 'metricTypes': metric_types, 'byYear': str(by_year).lower(), **kwds } Retrieval.__init__(self, **params) def __str__(self): """Return pretty text version of the author metrics.""" authors = self.authors or [] author_count = len(authors) if author_count == 0: return "No authors found" else: s = f"AuthorMetrics for {author_count} author(s):" for author in authors: s += f"\n- {author.name} (ID: {author.id})" return s