(self, X, y=None)
return self
Fit X into an embedded space.

        Optionally use y for supervised dimension reduction.

        Parameters
        ----------
        X : array, shape (n_samples, n_features) or (n_samples, n_samples)
            If the metric is 'precomputed' X must be a square distance
            matrix. Otherwise it contains a sample per row. If the method
            is 'exact', X may be a sparse matrix of type 'csr', 'csc'
            or 'coo'.

        y : array, shape (n_samples)
            A target array for supervised dimension reduction. How this is
            handled is determined by parameters UMAP was instantiated with.
            The relevant attributes are ``target_metric`` and
            ``target_metric_kwds``.
Fit X into an embedded space.
Fit X into an embedded space .
def fit(self, X, y=None):
        """Fit X into an embedded space.

        Optionally use y for supervised dimension reduction.

        Parameters
        ----------
        X : array, shape (n_samples, n_features) or (n_samples, n_samples)
            If the metric is 'precomputed' X must be a square distance
            matrix. Otherwise it contains a sample per row. If the method
            is 'exact', X may be a sparse matrix of type 'csr', 'csc'
            or 'coo'.

        y : array, shape (n_samples)
            A target array for supervised dimension reduction. How this is
            handled is determined by parameters UMAP was instantiated with.
            The relevant attributes are ``target_metric`` and
            ``target_metric_kwds``.
        """

        X = check_array(X, dtype=np.float32, accept_sparse="csr", order="C")
        self._raw_data = X

        # Handle all the optional arguments, setting default
        if self.a is None or self.b is None:
            self._a, self._b = find_ab_params(self.spread, self.min_dist)
        else:
            self._a = self.a
            self._b = self.b

        if isinstance(self.init, np.ndarray):
            init = check_array(self.init, dtype=np.float32, accept_sparse=False)
        else:
            init = self.init

        self._initial_alpha = self.learning_rate

        self.knn_indices = self.precomputed_knn[0]
        self.knn_dists = self.precomputed_knn[1]
        self.knn_search_index = self.precomputed_knn[2]

        self._validate_parameters()

        if self.verbose:
            print(str(self))

        self._original_n_threads = numba.get_num_threads()
        if self.n_jobs > 0 and self.n_jobs is not None:
            numba.set_num_threads(self.n_jobs)

        # Check if we should unique the data
        # We've already ensured that we aren't in the precomputed case
        if self.unique:
            # check if the matrix is dense
            if self._sparse_data:
                # Call a sparse unique function
                index, inverse, counts = csr_unique(X)
            else:
                index, inverse, counts = np.unique(
                    X,
                    return_index=True,
                    return_inverse=True,
                    return_counts=True,
                    axis=0,
                )[1:4]
            if self.verbose:
                print(
                    "Unique=True -> Number of data points reduced from ",
                    X.shape[0],
                    " to ",
                    X[index].shape[0],
                )
                most_common = np.argmax(counts)
                print(
                    "Most common duplicate is",
                    index[most_common],
                    " with a count of ",
                    counts[most_common],
                )
            # We'll expose an inverse map when unique=True for users to map from our internal structures to their data
            self._unique_inverse_ = inverse
        # If we aren't asking for unique use the full index.
        # This will save special cases later.
        else:
            index = list(range(X.shape[0]))
            inverse = list(range(X.shape[0]))

        # Error check n_neighbors based on data size
        if X[index].shape[0] <= self.n_neighbors:
            if X[index].shape[0] == 1:
                self.embedding_ = np.zeros(
                    (1, self.n_components)
                )  # needed to sklearn comparability
                return self

            warn(
                "n_neighbors is larger than the dataset size; truncating to "
                "X.shape[0] - 1"
            )
            self._n_neighbors = X[index].shape[0] - 1
            if self.densmap:
                self._densmap_kwds["n_neighbors"] = self._n_neighbors
        else:
            self._n_neighbors = self.n_neighbors

        # Note: unless it causes issues for setting 'index', could move this to
        # initial sparsity check above
        if self._sparse_data and not X.has_sorted_indices:
            X.sort_indices()

        random_state = check_random_state(self.random_state)

        if self.verbose:
            print(ts(), "Construct fuzzy simplicial set")

        if self.metric == "precomputed" and self._sparse_data:
            # For sparse precomputed distance matrices, we just argsort the rows to find
            # nearest neighbors. To make this easier, we expect matrices that are
            # symmetrical (so we can find neighbors by looking at rows in isolation,
            # rather than also having to consider that sample's column too).
            # print("Computing KNNs for sparse precomputed distances...")
            if sparse_tril(X).getnnz() != sparse_triu(X).getnnz():
                raise ValueError(
                    "Sparse precomputed distance matrices should be symmetrical!"
                )
            if not np.all(X.diagonal() == 0):
                raise ValueError("Non-zero distances from samples to themselves!")
            if self.knn_dists is None:
                self._knn_indices = np.zeros(
                    (X.shape[0], self.n_neighbors), dtype=np.int
                )
                self._knn_dists = np.zeros(self._knn_indices.shape, dtype=np.float)
                for row_id in range(X.shape[0]):
                    # Find KNNs row-by-row
                    row_data = X[row_id].data
                    row_indices = X[row_id].indices
                    if len(row_data) < self._n_neighbors:
                        raise ValueError(
                            "Some rows contain fewer than n_neighbors distances!"
                        )
                    row_nn_data_indices = np.argsort(row_data)[: self._n_neighbors]
                    self._knn_indices[row_id] = row_indices[row_nn_data_indices]
                    self._knn_dists[row_id] = row_data[row_nn_data_indices]
            else:
                self._knn_indices = self.knn_indices
                self._knn_dists = self.knn_dists
            # Disconnect any vertices farther apart than _disconnection_distance
            disconnected_index = self._knn_dists >= self._disconnection_distance
            self._knn_indices[disconnected_index] = -1
            self._knn_dists[disconnected_index] = np.inf
            edges_removed = disconnected_index.sum()

            (
                self.graph_,
                self._sigmas,
                self._rhos,
                self.graph_dists_,
            ) = fuzzy_simplicial_set(
                X[index],
                self.n_neighbors,
                random_state,
                "precomputed",
                self._metric_kwds,
                self._knn_indices,
                self._knn_dists,
                self.angular_rp_forest,
                self.set_op_mix_ratio,
                self.local_connectivity,
                True,
                self.verbose,
                self.densmap or self.output_dens,
            )
            # Report the number of vertices with degree 0 in our our umap.graph_
            # This ensures that they were properly disconnected.
            vertices_disconnected = np.sum(
                np.array(self.graph_.sum(axis=1)).flatten() == 0
            )
            raise_disconnected_warning(
                edges_removed,
                vertices_disconnected,
                self._disconnection_distance,
                self._raw_data.shape[0],
                verbose=self.verbose,
            )
        # Handle small cases efficiently by computing all distances
        elif X[index].shape[0] < 4096 and not self.force_approximation_algorithm:
            self._small_data = True
            try:
                # sklearn pairwise_distances fails for callable metric on sparse data
                _m = self.metric if self._sparse_data else self._input_distance_func
                dmat = pairwise_distances(X[index], metric=_m, **self._metric_kwds)
            except (ValueError, TypeError) as e:
                # metric is numba.jit'd or not supported by sklearn,
                # fallback to pairwise special

                if self._sparse_data:
                    # Get a fresh metric since we are casting to dense
                    if not callable(self.metric):
                        _m = dist.named_distances[self.metric]
                        dmat = dist.pairwise_special_metric(
                            X[index].toarray(),
                            metric=_m,
                            kwds=self._metric_kwds,
                        )
                    else:
                        dmat = dist.pairwise_special_metric(
                            X[index],
                            metric=self._input_distance_func,
                            kwds=self._metric_kwds,
                        )
                else:
                    dmat = dist.pairwise_special_metric(
                        X[index],
                        metric=self._input_distance_func,
                        kwds=self._metric_kwds,
                    )
            # set any values greater than disconnection_distance to be np.inf.
            # This will have no effect when _disconnection_distance is not set since it defaults to np.inf.
            edges_removed = np.sum(dmat >= self._disconnection_distance)
            dmat[dmat >= self._disconnection_distance] = np.inf
            (
                self.graph_,
                self._sigmas,
                self._rhos,
                self.graph_dists_,
            ) = fuzzy_simplicial_set(
                dmat,
                self._n_neighbors,
                random_state,
                "precomputed",
                self._metric_kwds,
                None,
                None,
                self.angular_rp_forest,
                self.set_op_mix_ratio,
                self.local_connectivity,
                True,
                self.verbose,
                self.densmap or self.output_dens,
            )
            # Report the number of vertices with degree 0 in our our umap.graph_
            # This ensures that they were properly disconnected.
            vertices_disconnected = np.sum(
                np.array(self.graph_.sum(axis=1)).flatten() == 0
            )
            raise_disconnected_warning(
                edges_removed,
                vertices_disconnected,
                self._disconnection_distance,
                self._raw_data.shape[0],
                verbose=self.verbose,
            )
        else:
            # Standard case
            self._small_data = False
            # Standard case
            if self._sparse_data and self.metric in pynn_sparse_named_distances:
                nn_metric = self.metric
            elif not self._sparse_data and self.metric in pynn_named_distances:
                nn_metric = self.metric
            else:
                nn_metric = self._input_distance_func
            if self.knn_dists is None:
                (
                    self._knn_indices,
                    self._knn_dists,
                    self._knn_search_index,
                ) = nearest_neighbors(
                    X[index],
                    self._n_neighbors,
                    nn_metric,
                    self._metric_kwds,
                    self.angular_rp_forest,
                    random_state,
                    self.low_memory,
                    use_pynndescent=True,
                    n_jobs=self.n_jobs,
                    verbose=self.verbose,
                )
            else:
                self._knn_indices = self.knn_indices
                self._knn_dists = self.knn_dists
                self._knn_search_index = self.knn_search_index
            # Disconnect any vertices farther apart than _disconnection_distance
            disconnected_index = self._knn_dists >= self._disconnection_distance
            self._knn_indices[disconnected_index] = -1
            self._knn_dists[disconnected_index] = np.inf
            edges_removed = disconnected_index.sum()

            (
                self.graph_,
                self._sigmas,
                self._rhos,
                self.graph_dists_,
            ) = fuzzy_simplicial_set(
                X[index],
                self.n_neighbors,
                random_state,
                nn_metric,
                self._metric_kwds,
                self._knn_indices,
                self._knn_dists,
                self.angular_rp_forest,
                self.set_op_mix_ratio,
                self.local_connectivity,
                True,
                self.verbose,
                self.densmap or self.output_dens,
            )
            # Report the number of vertices with degree 0 in our our umap.graph_
            # This ensures that they were properly disconnected.
            vertices_disconnected = np.sum(
                np.array(self.graph_.sum(axis=1)).flatten() == 0
            )
            raise_disconnected_warning(
                edges_removed,
                vertices_disconnected,
                self._disconnection_distance,
                self._raw_data.shape[0],
                verbose=self.verbose,
            )

        # Currently not checking if any duplicate points have differing labels
        # Might be worth throwing a warning...
        if y is not None:
            len_X = len(X) if not self._sparse_data else X.shape[0]
            if len_X != len(y):
                raise ValueError(
                    "Length of x = {len_x}, length of y = {len_y}, while it must be equal.".format(
                        len_x=len_X, len_y=len(y)
                    )
                )
            if self.target_metric == "string":
                y_ = y[index]
            else:
                y_ = check_array(y, ensure_2d=False)[index]
            if self.target_metric == "categorical":
                if self.target_weight < 1.0:
                    far_dist = 2.5 * (1.0 / (1.0 - self.target_weight))
                else:
                    far_dist = 1.0e12
                self.graph_ = discrete_metric_simplicial_set_intersection(
                    self.graph_, y_, far_dist=far_dist
                )
            elif self.target_metric in dist.DISCRETE_METRICS:
                if self.target_weight < 1.0:
                    scale = 2.5 * (1.0 / (1.0 - self.target_weight))
                else:
                    scale = 1.0e12
                # self.graph_ = discrete_metric_simplicial_set_intersection(
                #     self.graph_,
                #     y_,
                #     metric=self.target_metric,
                #     metric_kws=self.target_metric_kwds,
                #     metric_scale=scale
                # )

                metric_kws = dist.get_discrete_params(y_, self.target_metric)

                self.graph_ = discrete_metric_simplicial_set_intersection(
                    self.graph_,
                    y_,
                    metric=self.target_metric,
                    metric_kws=metric_kws,
                    metric_scale=scale,
                )
            else:
                if len(y_.shape) == 1:
                    y_ = y_.reshape(-1, 1)
                if self.target_n_neighbors == -1:
                    target_n_neighbors = self._n_neighbors
                else:
                    target_n_neighbors = self.target_n_neighbors

                # Handle the small case as precomputed as before
                if y.shape[0] < 4096:
                    try:
                        ydmat = pairwise_distances(
                            y_, metric=self.target_metric, **self._target_metric_kwds
                        )
                    except (TypeError, ValueError):
                        ydmat = dist.pairwise_special_metric(
                            y_,
                            metric=self.target_metric,
                            kwds=self._target_metric_kwds,
                        )

                    (target_graph, target_sigmas, target_rhos,) = fuzzy_simplicial_set(
                        ydmat,
                        target_n_neighbors,
                        random_state,
                        "precomputed",
                        self._target_metric_kwds,
                        None,
                        None,
                        False,
                        1.0,
                        1.0,
                        False,
                    )
                else:
                    # Standard case
                    (target_graph, target_sigmas, target_rhos,) = fuzzy_simplicial_set(
                        y_,
                        target_n_neighbors,
                        random_state,
                        self.target_metric,
                        self._target_metric_kwds,
                        None,
                        None,
                        False,
                        1.0,
                        1.0,
                        False,
                    )
                # product = self.graph_.multiply(target_graph)
                # # self.graph_ = 0.99 * product + 0.01 * (self.graph_ +
                # #                                        target_graph -
                # #                                        product)
                # self.graph_ = product
                self.graph_ = general_simplicial_set_intersection(
                    self.graph_, target_graph, self.target_weight
                )
                self.graph_ = reset_local_connectivity(self.graph_)
            self._supervised = True
        else:
            self._supervised = False

        if self.densmap or self.output_dens:
            self._densmap_kwds["graph_dists"] = self.graph_dists_

        if self.verbose:
            print(ts(), "Construct embedding")

        if self.transform_mode == "embedding":
            self.embedding_, aux_data = self._fit_embed_data(
                self._raw_data[index],
                self.n_epochs,
                init,
                random_state,  # JH why raw data?
            )
            # Assign any points that are fully disconnected from our manifold(s) to have embedding
            # coordinates of np.nan.  These will be filtered by our plotting functions automatically.
            # They also prevent users from being deceived a distance query to one of these points.
            # Might be worth moving this into simplicial_set_embedding or _fit_embed_data
            disconnected_vertices = np.array(self.graph_.sum(axis=1)).flatten() == 0
            if len(disconnected_vertices) > 0:
                self.embedding_[disconnected_vertices] = np.full(
                    self.n_components, np.nan
                )

            self.embedding_ = self.embedding_[inverse]
            if self.output_dens:
                self.rad_orig_ = aux_data["rad_orig"][inverse]
                self.rad_emb_ = aux_data["rad_emb"][inverse]

        if self.verbose:
            print(ts() + " Finished embedding")

        numba.set_num_threads(self._original_n_threads)
        self._input_hash = joblib.hash(self._raw_data)

        return self
def fit ( self , X , y = None ) : X = check_array ( X , dtype = np . float32 , accept_sparse = "csr" , order = "C" ) self . _raw_data = X # Handle all the optional arguments, setting default if self . a is None or self . b is None : self . _a , self . _b = find_ab_params ( self . spread , self . min_dist ) else : self . _a = self . a self . _b = self . b if isinstance ( self . init , np . ndarray ) : init = check_array ( self . init , dtype = np . float32 , accept_sparse = False ) else : init = self . init self . _initial_alpha = self . learning_rate self . knn_indices = self . precomputed_knn [ 0 ] self . knn_dists = self . precomputed_knn [ 1 ] self . knn_search_index = self . precomputed_knn [ 2 ] self . _validate_parameters ( ) if self . verbose : print ( str ( self ) ) self . _original_n_threads = numba . get_num_threads ( ) if self . n_jobs > 0 and self . n_jobs is not None : numba . set_num_threads ( self . n_jobs ) # Check if we should unique the data # We've already ensured that we aren't in the precomputed case if self . unique : # check if the matrix is dense if self . _sparse_data : # Call a sparse unique function index , inverse , counts = csr_unique ( X ) else : index , inverse , counts = np . unique ( X , return_index = True , return_inverse = True , return_counts = True , axis = 0 , ) [ 1 : 4 ] if self . verbose : print ( "Unique=True -> Number of data points reduced from " , X . shape [ 0 ] , " to " , X [ index ] . shape [ 0 ] , ) most_common = np . argmax ( counts ) print ( "Most common duplicate is" , index [ most_common ] , " with a count of " , counts [ most_common ] , ) # We'll expose an inverse map when unique=True for users to map from our internal structures to their data self . _unique_inverse_ = inverse # If we aren't asking for unique use the full index. # This will save special cases later. else : index = list ( range ( X . shape [ 0 ] ) ) inverse = list ( range ( X . shape [ 0 ] ) ) # Error check n_neighbors based on data size if X [ index ] . shape [ 0 ] <= self . n_neighbors : if X [ index ] . shape [ 0 ] == 1 : self . embedding_ = np . zeros ( ( 1 , self . n_components ) ) # needed to sklearn comparability return self warn ( "n_neighbors is larger than the dataset size; truncating to " "X.shape[0] - 1" ) self . _n_neighbors = X [ index ] . shape [ 0 ] - 1 if self . densmap : self . _densmap_kwds [ "n_neighbors" ] = self . _n_neighbors else : self . _n_neighbors = self . n_neighbors # Note: unless it causes issues for setting 'index', could move this to # initial sparsity check above if self . _sparse_data and not X . has_sorted_indices : X . sort_indices ( ) random_state = check_random_state ( self . random_state ) if self . verbose : print ( ts ( ) , "Construct fuzzy simplicial set" ) if self . metric == "precomputed" and self . _sparse_data : # For sparse precomputed distance matrices, we just argsort the rows to find # nearest neighbors. To make this easier, we expect matrices that are # symmetrical (so we can find neighbors by looking at rows in isolation, # rather than also having to consider that sample's column too). # print("Computing KNNs for sparse precomputed distances...") if sparse_tril ( X ) . getnnz ( ) != sparse_triu ( X ) . getnnz ( ) : raise ValueError ( "Sparse precomputed distance matrices should be symmetrical!" ) if not np . all ( X . diagonal ( ) == 0 ) : raise ValueError ( "Non-zero distances from samples to themselves!" ) if self . knn_dists is None : self . _knn_indices = np . zeros ( ( X . shape [ 0 ] , self . n_neighbors ) , dtype = np . int ) self . _knn_dists = np . zeros ( self . _knn_indices . shape , dtype = np . float ) for row_id in range ( X . shape [ 0 ] ) : # Find KNNs row-by-row row_data = X [ row_id ] . data row_indices = X [ row_id ] . indices if len ( row_data ) < self . _n_neighbors : raise ValueError ( "Some rows contain fewer than n_neighbors distances!" ) row_nn_data_indices = np . argsort ( row_data ) [ : self . _n_neighbors ] self . _knn_indices [ row_id ] = row_indices [ row_nn_data_indices ] self . _knn_dists [ row_id ] = row_data [ row_nn_data_indices ] else : self . _knn_indices = self . knn_indices self . _knn_dists = self . knn_dists # Disconnect any vertices farther apart than _disconnection_distance disconnected_index = self . _knn_dists >= self . _disconnection_distance self . _knn_indices [ disconnected_index ] = - 1 self . _knn_dists [ disconnected_index ] = np . inf edges_removed = disconnected_index . sum ( ) ( self . graph_ , self . _sigmas , self . _rhos , self . graph_dists_ , ) = fuzzy_simplicial_set ( X [ index ] , self . n_neighbors , random_state , "precomputed" , self . _metric_kwds , self . _knn_indices , self . _knn_dists , self . angular_rp_forest , self . set_op_mix_ratio , self . local_connectivity , True , self . verbose , self . densmap or self . output_dens , ) # Report the number of vertices with degree 0 in our our umap.graph_ # This ensures that they were properly disconnected. vertices_disconnected = np . sum ( np . array ( self . graph_ . sum ( axis = 1 ) ) . flatten ( ) == 0 ) raise_disconnected_warning ( edges_removed , vertices_disconnected , self . _disconnection_distance , self . _raw_data . shape [ 0 ] , verbose = self . verbose , ) # Handle small cases efficiently by computing all distances elif X [ index ] . shape [ 0 ] < 4096 and not self . force_approximation_algorithm : self . _small_data = True try : # sklearn pairwise_distances fails for callable metric on sparse data _m = self . metric if self . _sparse_data else self . _input_distance_func dmat = pairwise_distances ( X [ index ] , metric = _m , * * self . _metric_kwds ) except ( ValueError , TypeError ) as e : # metric is numba.jit'd or not supported by sklearn, # fallback to pairwise special if self . _sparse_data : # Get a fresh metric since we are casting to dense if not callable ( self . metric ) : _m = dist . named_distances [ self . metric ] dmat = dist . pairwise_special_metric ( X [ index ] . toarray ( ) , metric = _m , kwds = self . _metric_kwds , ) else : dmat = dist . pairwise_special_metric ( X [ index ] , metric = self . _input_distance_func , kwds = self . _metric_kwds , ) else : dmat = dist . pairwise_special_metric ( X [ index ] , metric = self . _input_distance_func , kwds = self . _metric_kwds , ) # set any values greater than disconnection_distance to be np.inf. # This will have no effect when _disconnection_distance is not set since it defaults to np.inf. edges_removed = np . sum ( dmat >= self . _disconnection_distance ) dmat [ dmat >= self . _disconnection_distance ] = np . inf ( self . graph_ , self . _sigmas , self . _rhos , self . graph_dists_ , ) = fuzzy_simplicial_set ( dmat , self . _n_neighbors , random_state , "precomputed" , self . _metric_kwds , None , None , self . angular_rp_forest , self . set_op_mix_ratio , self . local_connectivity , True , self . verbose , self . densmap or self . output_dens , ) # Report the number of vertices with degree 0 in our our umap.graph_ # This ensures that they were properly disconnected. vertices_disconnected = np . sum ( np . array ( self . graph_ . sum ( axis = 1 ) ) . flatten ( ) == 0 ) raise_disconnected_warning ( edges_removed , vertices_disconnected , self . _disconnection_distance , self . _raw_data . shape [ 0 ] , verbose = self . verbose , ) else : # Standard case self . _small_data = False # Standard case if self . _sparse_data and self . metric in pynn_sparse_named_distances : nn_metric = self . metric elif not self . _sparse_data and self . metric in pynn_named_distances : nn_metric = self . metric else : nn_metric = self . _input_distance_func if self . knn_dists is None : ( self . _knn_indices , self . _knn_dists , self . _knn_search_index , ) = nearest_neighbors ( X [ index ] , self . _n_neighbors , nn_metric , self . _metric_kwds , self . angular_rp_forest , random_state , self . low_memory , use_pynndescent = True , n_jobs = self . n_jobs , verbose = self . verbose , ) else : self . _knn_indices = self . knn_indices self . _knn_dists = self . knn_dists self . _knn_search_index = self . knn_search_index # Disconnect any vertices farther apart than _disconnection_distance disconnected_index = self . _knn_dists >= self . _disconnection_distance self . _knn_indices [ disconnected_index ] = - 1 self . _knn_dists [ disconnected_index ] = np . inf edges_removed = disconnected_index . sum ( ) ( self . graph_ , self . _sigmas , self . _rhos , self . graph_dists_ , ) = fuzzy_simplicial_set ( X [ index ] , self . n_neighbors , random_state , nn_metric , self . _metric_kwds , self . _knn_indices , self . _knn_dists , self . angular_rp_forest , self . set_op_mix_ratio , self . local_connectivity , True , self . verbose , self . densmap or self . output_dens , ) # Report the number of vertices with degree 0 in our our umap.graph_ # This ensures that they were properly disconnected. vertices_disconnected = np . sum ( np . array ( self . graph_ . sum ( axis = 1 ) ) . flatten ( ) == 0 ) raise_disconnected_warning ( edges_removed , vertices_disconnected , self . _disconnection_distance , self . _raw_data . shape [ 0 ] , verbose = self . verbose , ) # Currently not checking if any duplicate points have differing labels # Might be worth throwing a warning... if y is not None : len_X = len ( X ) if not self . _sparse_data else X . shape [ 0 ] if len_X != len ( y ) : raise ValueError ( "Length of x = {len_x}, length of y = {len_y}, while it must be equal." . format ( len_x = len_X , len_y = len ( y ) ) ) if self . target_metric == "string" : y_ = y [ index ] else : y_ = check_array ( y , ensure_2d = False ) [ index ] if self . target_metric == "categorical" : if self . target_weight < 1.0 : far_dist = 2.5 * ( 1.0 / ( 1.0 - self . target_weight ) ) else : far_dist = 1.0e12 self . graph_ = discrete_metric_simplicial_set_intersection ( self . graph_ , y_ , far_dist = far_dist ) elif self . target_metric in dist . DISCRETE_METRICS : if self . target_weight < 1.0 : scale = 2.5 * ( 1.0 / ( 1.0 - self . target_weight ) ) else : scale = 1.0e12 # self.graph_ = discrete_metric_simplicial_set_intersection( #     self.graph_, #     y_, #     metric=self.target_metric, #     metric_kws=self.target_metric_kwds, #     metric_scale=scale # ) metric_kws = dist . get_discrete_params ( y_ , self . target_metric ) self . graph_ = discrete_metric_simplicial_set_intersection ( self . graph_ , y_ , metric = self . target_metric , metric_kws = metric_kws , metric_scale = scale , ) else : if len ( y_ . shape ) == 1 : y_ = y_ . reshape ( - 1 , 1 ) if self . target_n_neighbors == - 1 : target_n_neighbors = self . _n_neighbors else : target_n_neighbors = self . target_n_neighbors # Handle the small case as precomputed as before if y . shape [ 0 ] < 4096 : try : ydmat = pairwise_distances ( y_ , metric = self . target_metric , * * self . _target_metric_kwds ) except ( TypeError , ValueError ) : ydmat = dist . pairwise_special_metric ( y_ , metric = self . target_metric , kwds = self . _target_metric_kwds , ) ( target_graph , target_sigmas , target_rhos , ) = fuzzy_simplicial_set ( ydmat , target_n_neighbors , random_state , "precomputed" , self . _target_metric_kwds , None , None , False , 1.0 , 1.0 , False , ) else : # Standard case ( target_graph , target_sigmas , target_rhos , ) = fuzzy_simplicial_set ( y_ , target_n_neighbors , random_state , self . target_metric , self . _target_metric_kwds , None , None , False , 1.0 , 1.0 , False , ) # product = self.graph_.multiply(target_graph) # # self.graph_ = 0.99 * product + 0.01 * (self.graph_ + # #                                        target_graph - # #                                        product) # self.graph_ = product self . graph_ = general_simplicial_set_intersection ( self . graph_ , target_graph , self . target_weight ) self . graph_ = reset_local_connectivity ( self . graph_ ) self . _supervised = True else : self . _supervised = False if self . densmap or self . output_dens : self . _densmap_kwds [ "graph_dists" ] = self . graph_dists_ if self . verbose : print ( ts ( ) , "Construct embedding" ) if self . transform_mode == "embedding" : self . embedding_ , aux_data = self . _fit_embed_data ( self . _raw_data [ index ] , self . n_epochs , init , random_state , # JH why raw data? ) # Assign any points that are fully disconnected from our manifold(s) to have embedding # coordinates of np.nan.  These will be filtered by our plotting functions automatically. # They also prevent users from being deceived a distance query to one of these points. # Might be worth moving this into simplicial_set_embedding or _fit_embed_data disconnected_vertices = np . array ( self . graph_ . sum ( axis = 1 ) ) . flatten ( ) == 0 if len ( disconnected_vertices ) > 0 : self . embedding_ [ disconnected_vertices ] = np . full ( self . n_components , np . nan ) self . embedding_ = self . embedding_ [ inverse ] if self . output_dens : self . rad_orig_ = aux_data [ "rad_orig" ] [ inverse ] self . rad_emb_ = aux_data [ "rad_emb" ] [ inverse ] if self . verbose : print ( ts ( ) + " Finished embedding" ) numba . set_num_threads ( self . _original_n_threads ) self . _input_hash = joblib . hash ( self . _raw_data ) return self