class_docstr: Results from computing metrics.
class_docstr_tok: ["Results","from","computing","metrics","."]
docstr: Get the rank-based metric key.
  
  The key input is understood as a dot-separated composition of
  
  1. The side (one of "head", "tail", or "both"). Most publications exclusively report "both".
     If not given "both" is assumed.
  2. The rank type (one of "optimistic", "pessimistic", "realistic"). If not given, "realistic" is assumed.
  3. The metric name, e.g., "adjusted_mean_rank_index", "adjusted_mean_rank", "mean_rank, "mean_reciprocal_rank",
      "inverse_geometric_mean_rank", or "hits@k" where k defaults to 10 but can be substituted for an integer.
      By default, 1, 3, 5, and 10 are available. Other K's can be calculated by setting the appropriate
      variable in the ``evaluation_kwargs`` in the :func:`pykeen.pipeline.pipeline` or setting ``ks`` in the
      :class:`pykeen.evaluation.RankBasedEvaluator`.
  
  In general, all metrics are available for all combinations of sides/types except AMR and AMRI, which
  are only calculated for the average type. This is because the calculation of the expected MR in the
  optimistic and pessimistic case scenarios is still an active area of research and therefore has no
  implementation yet.
  
  :param s:
      a string denoting a metric key
  
  :return: The resolved key.
  
  :raises ValueError:
      if the string cannot be resolved to a metric key
  
  Get the average MR
  
  >>> RankBasedMetricResults.key_from_string('both.realistic.mean_rank')
  RankBasedMetricKey(side='both', rank_type='realistic', metric='arithmetic_mean_rank')
  
  If you only give a metric name, it assumes that it's for 'both' sides and 'realistic' type.
  
  >>> RankBasedMetricResults.key_from_string('adjusted_mean_rank_index')
  RankBasedMetricKey(side='both', rank_type='realistic', metric='adjusted_arithmetic_mean_rank_index')
  
  This function will do its best to infer what's going on if you only specify one part.
  
  >>> RankBasedMetricResults.key_from_string('head.mean_rank')
  RankBasedMetricKey(side='head', rank_type='realistic', metric='arithmetic_mean_rank')
  
  >>> RankBasedMetricResults.key_from_string('optimistic.mean_rank')
  RankBasedMetricKey(side='both', rank_type='optimistic', metric='arithmetic_mean_rank')
  
  Get the default Hits @ K (where $k=10$)
  
  >>> RankBasedMetricResults.key_from_string('hits@k')
  RankBasedMetricKey(side='both', rank_type='realistic', metric='hits_at_10')
  
  Get a given Hits @ K
  
  >>> RankBasedMetricResults.key_from_string('hits@5')
  RankBasedMetricKey(side='both', rank_type='realistic', metric='hits_at_5')
code: def key_from_string(cls, s: str | None) -> RankBasedMetricKey:
      """Get the rank-based metric key.
  
      The key input is understood as a dot-separated composition of
  
      1. The side (one of "head", "tail", or "both"). Most publications exclusively report "both".
         If not given "both" is assumed.
      2. The rank type (one of "optimistic", "pessimistic", "realistic"). If not given, "realistic" is assumed.
      3. The metric name, e.g., "adjusted_mean_rank_index", "adjusted_mean_rank", "mean_rank, "mean_reciprocal_rank",
          "inverse_geometric_mean_rank", or "hits@k" where k defaults to 10 but can be substituted for an integer.
          By default, 1, 3, 5, and 10 are available. Other K's can be calculated by setting the appropriate
          variable in the ``evaluation_kwargs`` in the :func:`pykeen.pipeline.pipeline` or setting ``ks`` in the
          :class:`pykeen.evaluation.RankBasedEvaluator`.
  
      In general, all metrics are available for all combinations of sides/types except AMR and AMRI, which
      are only calculated for the average type. This is because the calculation of the expected MR in the
      optimistic and pessimistic case scenarios is still an active area of research and therefore has no
      implementation yet.
  
      :param s:
          a string denoting a metric key
  
      :return: The resolved key.
  
      :raises ValueError:
          if the string cannot be resolved to a metric key
  
      Get the average MR
  
      >>> RankBasedMetricResults.key_from_string('both.realistic.mean_rank')
      RankBasedMetricKey(side='both', rank_type='realistic', metric='arithmetic_mean_rank')
  
      If you only give a metric name, it assumes that it's for 'both' sides and 'realistic' type.
  
      >>> RankBasedMetricResults.key_from_string('adjusted_mean_rank_index')
      RankBasedMetricKey(side='both', rank_type='realistic', metric='adjusted_arithmetic_mean_rank_index')
  
      This function will do its best to infer what's going on if you only specify one part.
  
      >>> RankBasedMetricResults.key_from_string('head.mean_rank')
      RankBasedMetricKey(side='head', rank_type='realistic', metric='arithmetic_mean_rank')
  
      >>> RankBasedMetricResults.key_from_string('optimistic.mean_rank')
      RankBasedMetricKey(side='both', rank_type='optimistic', metric='arithmetic_mean_rank')
  
      Get the default Hits @ K (where $k=10$)
  
      >>> RankBasedMetricResults.key_from_string('hits@k')
      RankBasedMetricKey(side='both', rank_type='realistic', metric='hits_at_10')
  
      Get a given Hits @ K
  
      >>> RankBasedMetricResults.key_from_string('hits@5')
      RankBasedMetricKey(side='both', rank_type='realistic', metric='hits_at_5')
      """
      if s is None:
          return RankBasedMetricKey(
              side=SIDE_BOTH,
              rank_type=RANK_REALISTIC,
              metric=rank_based_metric_resolver.make(query=None).key,
          )
  
      match = METRIC_PATTERN.match(s)
      if not match:
          raise ValueError(f"Invalid metric name: {s}")
      k: Union[None, str, int]
      name, side, rank_type, k = [
          match.group(key) for key in ("name", "side", "type", "k")
      ]
      name = name.lower()
      match = HITS_PATTERN.match(name)
      if match:
          name, k = match.groups()
  
      # normalize metric name
      if not name:
          raise ValueError("A metric name must be provided.")
      metric_cls = rank_based_metric_resolver.lookup(name)
  
      kwargs = {}
      if issubclass(metric_cls, HITS_METRICS):
          k = int(k or 10)
          assert k > 0
          kwargs["k"] = k
  
      metric = rank_based_metric_resolver.make(metric_cls, kwargs)
  
      # normalize side
      side = normalize_target(side)
  
      # normalize rank type
      rank_type = normalize_rank_type(rank_type)
      if rank_type not in metric.supported_rank_types:
          raise ValueError(
              f"Invalid rank type for {metric}: {rank_type}. Allowed type: {metric.supported_rank_types}"
          )
  
      return RankBasedMetricKey(
          side=side, rank_type=rank_type, metric=metric.key
      )
  
imports: from __future__ import annotations
  import functools
  import itertools
  import logging
  import math
  import random
  import re
  from collections import defaultdict
  from typing import Callable, DefaultDict, Iterable, List, Mapping, MutableMapping, NamedTuple, Optional, Sequence, Tuple, Type, TypeVar, Union, cast
  import numpy
  import numpy.random
  import pandas
  import torch
  from class_resolver import HintOrType, OptionalKwargs
  from .evaluator import Evaluator, MetricResults, prepare_filter_triples
  from .ranks import Ranks
  from ..constants import COLUMN_LABELS, TARGET_TO_KEY_LABELS, TARGET_TO_KEYS
  from ..metrics.ranking import HITS_METRICS, RankBasedMetric, rank_based_metric_resolver
  from ..metrics.utils import Metric
  from ..triples.triples_factory import CoreTriplesFactory
  from ..typing import LABEL_HEAD, LABEL_TAIL, RANK_REALISTIC, RANK_TYPE_SYNONYMS, RANK_TYPES, SIDE_BOTH, SIDES, ExtendedTarget, MappedTriples, RankType, Target, normalize_rank_type, normalize_target
label_desc: Use image node_id 1 for calling the RankBasedMetricResults obj's underlying member method code with example usage: obj.key_from_string(cls, s) and returns: RankBasedMetricKey, RankBasedMetricKey