code: def _get_axis_info(
      trials: list[FrozenTrial], param_name: str
  ) -> _AxisInfo:
      values: list[str | float | None]
      if _is_numerical(trials, param_name):
          values = [t.params.get(param_name) for t in trials]
      else:
          values = [
              str(t.params.get(param_name))
              if param_name in t.params
              else None
              for t in trials
          ]
  
      min_value = min([v for v in values if v is not None])
      max_value = max([v for v in values if v is not None])
  
      if _is_log_scale(trials, param_name):
          min_value = float(min_value)
          max_value = float(max_value)
          padding = (
              math.log10(max_value) - math.log10(min_value)
          ) * PADDING_RATIO
          min_value = math.pow(10, math.log10(min_value) - padding)
          max_value = math.pow(10, math.log10(max_value) + padding)
          is_log = True
          is_cat = False
  
      elif _is_numerical(trials, param_name):
          min_value = float(min_value)
          max_value = float(max_value)
          padding = (max_value - min_value) * PADDING_RATIO
          min_value = min_value - padding
          max_value = max_value + padding
          is_log = False
          is_cat = False
  
      else:
          unique_values = set(values)
          span = len(unique_values) - 1
          if None in unique_values:
              span -= 1
          padding = span * PADDING_RATIO
          min_value = -padding
          max_value = span + padding
          is_log = False
          is_cat = True
  
      indices = sorted(set([v for v in values if v is not None]))
  
      if len(indices) < 2:
          return _AxisInfo(
              name=param_name,
              range=(min_value, max_value),
              is_log=is_log,
              is_cat=is_cat,
              indices=indices,
              values=values,
          )
  
      if _is_numerical(trials, param_name):
          indices.insert(0, min_value)
          indices.append(max_value)
  
      return _AxisInfo(
          name=param_name,
          range=(min_value, max_value),
          is_log=is_log,
          is_cat=is_cat,
          indices=indices,
          values=values,
      )
  
imports: from __future__ import annotations
  import math
  from typing import Any
  from typing import Callable
  from typing import NamedTuple
  from optuna.logging import get_logger
  from optuna.samplers._base import _CONSTRAINTS_KEY
  from optuna.study import Study
  from optuna.study import StudyDirection
  from optuna.trial import FrozenTrial
  from optuna.trial import TrialState
  from optuna.visualization._plotly_imports import _imports
  from optuna.visualization._utils import _check_plot_args
  from optuna.visualization._utils import _filter_nonfinite
  from optuna.visualization._utils import _is_log_scale
  from optuna.visualization._utils import _is_numerical
  from optuna.visualization._utils import _is_reverse_scale
label_desc: Use image node_id 8 for calling a global function with example usage: _get_axis_info(trials, param_name) and returns: _AxisInfo, _AxisInfo