code: def _handle_nice_params(
      embedding: np.ndarray, optim_params: dict
  ) -> None:
      """Convert the user-friendly params into something the optimizer can
      understand."""
      n_samples = embedding.shape[0]
      # Handle callbacks
      optim_params["callbacks"] = _check_callbacks(
          optim_params.get("callbacks")
      )
      optim_params["use_callbacks"] = (
          optim_params["callbacks"] is not None
      )
  
      # Handle negative gradient method
      negative_gradient_method = optim_params.pop(
          "negative_gradient_method", "auto"
      )
      if (
          isinstance(negative_gradient_method, str)
          and negative_gradient_method == "auto"
      ):
          if n_samples < 10_000:
              negative_gradient_method = "bh"
          else:
              negative_gradient_method = "fft"
          log.info(
              f"Automatically determined negative gradient method `{negative_gradient_method}`"
          )
  
      if callable(negative_gradient_method):
          negative_gradient_method = negative_gradient_method
      elif negative_gradient_method in {"bh", "BH", "barnes-hut"}:
          negative_gradient_method = kl_divergence_bh
      elif negative_gradient_method in {"fft", "FFT", "interpolation"}:
          negative_gradient_method = kl_divergence_fft
      else:
          raise ValueError(
              "Unrecognized gradient method. Please choose one of "
              "the supported methods or provide a valid callback."
          )
      # `gradient_descent` uses the more informative name `objective_function`
      optim_params["objective_function"] = negative_gradient_method
  
      # Handle number of jobs
      n_jobs = optim_params.get("n_jobs", 1)
      if n_jobs < 0:
          n_cores = multiprocessing.cpu_count()
          # Add negative number of n_jobs to the number of cores, but increment by
          # one because -1 indicates using all cores, -2 all except one, and so on
          n_jobs = n_cores + n_jobs + 1
  
      # If the number of jobs, after this correction is still <= 0, then the user
      # probably thought they had more cores, so we'll default to 1
      if n_jobs <= 0:
          log.warning(
              "`n_jobs` receieved value %d but only %d cores are available. "
              "Defaulting to single job."
              % (optim_params["n_jobs"], n_cores)
          )
          n_jobs = 1
  
      optim_params["n_jobs"] = n_jobs
  
      # Determine learning rate if requested
      learning_rate = optim_params.get("learning_rate", "auto")
      if learning_rate == "auto":
          exaggeration = optim_params.get("exaggeration", None)
          if exaggeration is None:
              exaggeration = 1
          learning_rate = n_samples / exaggeration
      optim_params["learning_rate"] = learning_rate
  
imports: import inspect
  import logging
  import multiprocessing
  from collections.abc import Iterable
  from types import SimpleNamespace
  from time import time
  import numpy
  from sklearn.base import BaseEstimator
  from openTSNE import _tsne
  from openTSNE import initialization
  from openTSNE.affinity import Affinities, MultiscaleMixture
  from openTSNE.quad_tree import QuadTree
  from openTSNE import utils
label_desc: Use image node_id 2 for calling a global function with example usage: _handle_nice_params(embedding, optim_params) without return types