code: def get_optimal_category_projection(
      corpus,
      n_dims=3,
      n_steps=10,
      projector=lambda n_terms, n_dims: CategoryProjector(
          selector=AssociationCompactor(n_terms, scorer=RankDifference),
          projector=PCA(n_dims),
      ),
      optimizer: Optional[Callable] = None,
      term_counts: Optional[np.array] = None,
      verbose=False,
  ):
      min_dev = None
      best_k = None
      best_x = None
      best_y = None
      best_projector = None
      optimizer = (
          ProjectionQuality().ripley_poisson_difference
          if optimizer is None
          else optimizer
      )
      term_counts = (
          np.power(
              2,
              np.linspace(
                  np.log(corpus.get_num_categories()) / np.log(2),
                  np.log(corpus.get_num_terms()) / np.log(2),
                  n_steps,
              ),
          ).astype(int)
          if term_counts is None
          else term_counts
      )
  
      for k in term_counts:
          category_projector = projector(k, n_dims)
          category_projection = category_projector.project(corpus)
          for dim_1 in range(0, n_dims):
              for dim_2 in range(dim_1 + 1, n_dims):
                  proj = category_projection.projection[
                      :, [dim_1, dim_2]
                  ]
                  scaled_proj = np.array(
                      [
                          stretch_0_to_1(proj.T[0]),
                          stretch_0_to_1(proj.T[1]),
                      ]
                  ).T
                  dev = optimizer(scaled_proj)
                  category_projection.x_dim = dim_1
                  category_projection.y_dim = dim_2
                  tproj = (
                      category_projection.get_term_projection().values
                  )
                  print(proj.shape)
                  print(tproj.shape)
                  scaled_tproj = np.array(
                      [
                          stretch_0_to_1(tproj.T[0]),
                          stretch_0_to_1(tproj.T[1]),
                      ]
                  ).T
                  tdev = optimizer(scaled_tproj)
                  print(dev, tdev)
                  # dev = np.sum(np.abs(ripley(scaled_proj, r, mode='ripley') - ripley.poisson(r)))]
                  best = False
                  if min_dev is None or dev < min_dev:
                      min_dev = dev
                      best_k = k
                      best_projector = category_projector
                      best_x, best_y = (dim_1, dim_2)
                      best = True
                  if verbose:
                      print(
                          k,
                          dim_1,
                          dim_2,
                          dev,
                          best_k,
                          best_x,
                          best_y,
                          min_dev,
                          f"best={best}",
                      )
      if verbose:
          print(best_k, best_x, best_y)
      return best_projector.project(corpus, best_x, best_y)
  
file_path: scattertext/scattertext/categoryprojector/OptimalProjection.py
imports: from typing import Optional, Callable
  import numpy
  from sklearn.decomposition import PCA
  from scattertext.Scalers import stretch_0_to_1
  from scattertext.termscoring.RankDifference import RankDifference
  from scattertext.categoryprojector.CategoryProjector import CategoryProjector
  from scattertext.termcompaction.AssociationCompactor import AssociationCompactor, AssociationCompactorByRank, TermCategoryRanker
label_desc: Use image node_id 2 for calling a global function with example usage: get_optimal_category_projection(corpus, n_dims, n_steps, projector, optimizer, term_counts, verbose) and returns: best_projector