class_docstr: Compute t-SNE embedding using Barnes-Hut optimization and
  multiple cores (if avaialble).
  
  Parameters mostly correspond to parameters of `sklearn.manifold.TSNE`.
  
  The following parameters are unused:
  * n_iter_without_progress
  * min_grad_norm
  * metric
  * method
  
  When `cheat_metric` is true squared equclidean distance is used to build VPTree. 
  Usually leads to same quality, yet much faster.
  
  Parameter `init` doesn't support 'pca' initialization, but a precomputed
  array can be passed.
  
  Parameter `n_iter_early_exag` defines the number of iterations out of total `n_iter`
  to spend in the early exaggeration phase of the algorithm. With default `learning_rate`,
  the default values of 250/1000 may need to be increased when embedding large numbers
  of observations. Properly setting `learning_rate` results in good embeddings with fewer 
  iterations. This interplay is discussed at https://doi.org/10.1101/451690.
class_docstr_tok: ["Compute","t-SNE","embedding","using","Barnes-Hut","optimization","and","multiple","cores","(","if","avaialble",")",".","Parameters","mostly","correspond","to","parameters","of","`","sklearn.manifold.TSNE","`",".","The","following","parameters","are","unused",":","*","n_iter_without_progress","*","min_grad_norm","*","metric","*","method","When","`","cheat_metric","`","is","true","squared","equclidean","distance","is","used","to","build","VPTree",".","Usually","leads","to","same","quality",",","yet","much","faster",".","Parameter","`","init","`","does","n't","support","'pca","'","initialization",",","but","a","precomputed","array","can","be","passed",".","Parameter","`","n_iter_early_exag","`","defines","the","number","of","iterations","out","of","total","`","n_iter","`","to","spend","in","the","early","exaggeration","phase","of","the","algorithm",".","With","default","`","learning_rate","`",",","the","default","values","of","250\/1000","may","need","to","be","increased","when","embedding","large","numbers","of","observations",".","Properly","setting","`","learning_rate","`","results","in","good","embeddings","with","fewer","iterations",".","This","interplay","is","discussed","at","https",":","\/\/doi.org\/10.1101\/451690","."]
code: def __init__(
      self,
      n_components=2,
      perplexity=30.0,
      early_exaggeration=12,
      learning_rate=200,
      n_iter=1000,
      n_iter_early_exag=250,
      n_iter_without_progress=30,
      min_grad_norm=1e-07,
      metric="euclidean",
      init="random",
      verbose=0,
      random_state=None,
      method="barnes_hut",
      angle=0.5,
      n_jobs=1,
      cheat_metric=True,
  ):
      self.n_components = n_components
      self.angle = angle
      self.perplexity = perplexity
      self.early_exaggeration = early_exaggeration
      self.learning_rate = learning_rate
      self.n_iter = n_iter
      self.n_iter_early_exag = n_iter_early_exag
      self.n_jobs = n_jobs
      self.random_state = -1 if random_state is None else random_state
      self.init = init
      self.embedding_ = None
      self.n_iter_ = None
      self.kl_divergence_ = None
      self.verbose = int(verbose)
      self.cheat_metric = cheat_metric
      assert (
          isinstance(init, np.ndarray) or init == "random"
      ), "init must be 'random' or array"
      if isinstance(init, np.ndarray):
          assert init.ndim == 2, "init array must be 2D"
          assert (
              init.shape[1] == n_components
          ), "init array must be of shape (n_instances, n_components)"
          self.init = np.ascontiguousarray(init, float)
  
      self.ffi = cffi.FFI()
      self.ffi.cdef(
          """void tsne_run_double(double* X, int N, int D, double* Y,
                                      int no_dims, double perplexity, double theta,
                                      int num_threads, int max_iter, int n_iter_early_exag,
                                      int random_state, bool init_from_Y, int verbose,
                                      double early_exaggeration, double learning_rate,
                                      double *final_error, int distance);"""
      )
  
      path = os.path.dirname(os.path.realpath(__file__))
      try:
          sofile = (
              glob(os.path.join(path, "libtsne*.so"))
              + glob(os.path.join(path, "*tsne*.dll"))
          )[0]
          self.C = self.ffi.dlopen(os.path.join(path, sofile))
      except (IndexError, OSError):
          raise RuntimeError(
              "Cannot find/open tsne_multicore shared library"
          )
  
file_path: Multicore-TSNE/MulticoreTSNE/__init__.py
imports: from __future__ import print_function
  from glob import glob
  import threading
  import os
  import sys
  import numpy
  import cffi
label_desc: Use image node_id 1 to create a new MulticoreTSNE object  with example: obj = MulticoreTSNE(n_components, perplexity, early_exaggeration, learning_rate, n_iter, n_iter_early_exag, n_iter_without_progress, min_grad_norm, metric, init, verbose, random_state, method, angle, n_jobs, cheat_metric)