code: def hdbscan(
      X,
      min_cluster_size=5,
      min_samples=None,
      alpha=1.0,
      cluster_selection_epsilon=0.0,
      max_cluster_size=0,
      metric="minkowski",
      p=2,
      leaf_size=40,
      algorithm="best",
      memory=Memory(None, verbose=0),
      approx_min_span_tree=True,
      gen_min_span_tree=False,
      core_dist_n_jobs=4,
      cluster_selection_method="eom",
      allow_single_cluster=False,
      match_reference_implementation=False,
      **kwargs,
  ):
      """Perform HDBSCAN clustering from a vector array or distance matrix.
  
      Parameters
      ----------
      X : array or sparse (CSR) matrix of shape (n_samples, n_features), or \
              array of shape (n_samples, n_samples)
          A feature array, or array of distances between samples if
          ``metric='precomputed'``.
  
      min_cluster_size : int, optional (default=5)
          The minimum number of samples in a group for that group to be
          considered a cluster; groupings smaller than this size will be left
          as noise.
  
      min_samples : int, optional (default=None)
          The number of samples in a neighborhood for a point
          to be considered as a core point. This includes the point itself.
          defaults to the min_cluster_size.
  
      cluster_selection_epsilon: float, optional (default=0.0)
          A distance threshold. Clusters below this value will be merged.
          See [3]_ for more information. Note that this should not be used
          if we want to predict the cluster labels for new points in future
          (e.g. using approximate_predict), as the approximate_predict function
          is not aware of this argument.
  
      alpha : float, optional (default=1.0)
          A distance scaling parameter as used in robust single linkage.
          See [2]_ for more information.
  
      max_cluster_size : int, optional (default=0)
          A limit to the size of clusters returned by the eom algorithm.
          Has no effect when using leaf clustering (where clusters are
          usually small regardless) and can also be overridden in rare
          cases by a high value for cluster_selection_epsilon. Note that
          this should not be used if we want to predict the cluster labels
          for new points in future (e.g. using approximate_predict), as
          the approximate_predict function is not aware of this argument.
  
      metric : string or callable, optional (default='minkowski')
          The metric to use when calculating distance between instances in a
          feature array. If metric is a string or callable, it must be one of
          the options allowed by metrics.pairwise.pairwise_distances for its
          metric parameter.
          If metric is "precomputed", X is assumed to be a distance matrix and
          must be square.
  
      p : int, optional (default=2)
          p value to use if using the minkowski metric.
  
      leaf_size : int, optional (default=40)
          Leaf size for trees responsible for fast nearest
          neighbour queries.
  
      algorithm : string, optional (default='best')
          Exactly which algorithm to use; hdbscan has variants specialised
          for different characteristics of the data. By default this is set
          to ``best`` which chooses the "best" algorithm given the nature of
          the data. You can force other options if you believe you know
          better. Options are:
              * ``best``
              * ``generic``
              * ``prims_kdtree``
              * ``prims_balltree``
              * ``boruvka_kdtree``
              * ``boruvka_balltree``
  
      memory : instance of joblib.Memory or string, optional
          Used to cache the output of the computation of the tree.
          By default, no caching is done. If a string is given, it is the
          path to the caching directory.
  
      approx_min_span_tree : bool, optional (default=True)
          Whether to accept an only approximate minimum spanning tree.
          For some algorithms this can provide a significant speedup, but
          the resulting clustering may be of marginally lower quality.
          If you are willing to sacrifice speed for correctness you may want
          to explore this; in general this should be left at the default True.
  
      gen_min_span_tree : bool, optional (default=False)
          Whether to generate the minimum spanning tree for later analysis.
  
      core_dist_n_jobs : int, optional (default=4)
          Number of parallel jobs to run in core distance computations (if
          supported by the specific algorithm). For ``core_dist_n_jobs``
          below -1, (n_cpus + 1 + core_dist_n_jobs) are used.
  
      cluster_selection_method : string, optional (default='eom')
          The method used to select clusters from the condensed tree. The
          standard approach for HDBSCAN* is to use an Excess of Mass algorithm
          to find the most persistent clusters. Alternatively you can instead
          select the clusters at the leaves of the tree -- this provides the
          most fine grained and homogeneous clusters. Options are:
              * ``eom``
              * ``leaf``
  
      allow_single_cluster : bool, optional (default=False)
          By default HDBSCAN* will not produce a single cluster, setting this
          to t=True will override this and allow single cluster results in
          the case that you feel this is a valid result for your dataset.
          (default False)
  
      match_reference_implementation : bool, optional (default=False)
          There exist some interpretational differences between this
          HDBSCAN* implementation and the original authors reference
          implementation in Java. This can result in very minor differences
          in clustering results. Setting this flag to True will, at a some
          performance cost, ensure that the clustering results match the
          reference implementation.
  
      **kwargs : optional
          Arguments passed to the distance metric
  
      Returns
      -------
      labels : ndarray, shape (n_samples, )
          Cluster labels for each point.  Noisy samples are given the label -1.
  
      probabilities : ndarray, shape (n_samples, )
          Cluster membership strengths for each point. Noisy samples are assigned
          0.
  
      cluster_persistence : array, shape  (n_clusters, )
          A score of how persistent each cluster is. A score of 1.0 represents
          a perfectly stable cluster that persists over all distance scales,
          while a score of 0.0 represents a perfectly ephemeral cluster. These
          scores can be guage the relative coherence of the clusters output
          by the algorithm.
  
      condensed_tree : record array
          The condensed cluster hierarchy used to generate clusters.
  
      single_linkage_tree : ndarray, shape (n_samples - 1, 4)
          The single linkage tree produced during clustering in scipy
          hierarchical clustering format
          (see http://docs.scipy.org/doc/scipy/reference/cluster.hierarchy.html).
  
      min_spanning_tree : ndarray, shape (n_samples - 1, 3)
          The minimum spanning as an edgelist. If gen_min_span_tree was False
          this will be None.
  
      References
      ----------
  
      .. [1] Campello, R. J., Moulavi, D., & Sander, J. (2013, April).
         Density-based clustering based on hierarchical density estimates.
         In Pacific-Asia Conference on Knowledge Discovery and Data Mining
         (pp. 160-172). Springer Berlin Heidelberg.
  
      .. [2] Chaudhuri, K., & Dasgupta, S. (2010). Rates of convergence for the
         cluster tree. In Advances in Neural Information Processing Systems
         (pp. 343-351).
  
      .. [3] Malzer, C., & Baum, M. (2019). A Hybrid Approach To Hierarchical 
  	   Density-based Cluster Selection. arxiv preprint 1911.02282.
      """
      if min_samples is None:
          min_samples = min_cluster_size
  
      if not np.issubdtype(
          type(min_samples), np.integer
      ) or not np.issubdtype(type(min_cluster_size), np.integer):
          raise ValueError(
              "Min samples and min cluster size must be integers!"
          )
  
      if min_samples <= 0 or min_cluster_size <= 0:
          raise ValueError(
              "Min samples and Min cluster size must be positive"
              " integers"
          )
  
      if min_cluster_size == 1:
          raise ValueError("Min cluster size must be greater than one")
  
      if np.issubdtype(type(cluster_selection_epsilon), np.integer):
          cluster_selection_epsilon = float(cluster_selection_epsilon)
  
      if (
          type(cluster_selection_epsilon) is not float
          or cluster_selection_epsilon < 0.0
      ):
          raise ValueError(
              "Epsilon must be a float value greater than or equal to 0!"
          )
  
      if not isinstance(alpha, float) or alpha <= 0.0:
          raise ValueError(
              "Alpha must be a positive float value greater than" " 0!"
          )
  
      if leaf_size < 1:
          raise ValueError("Leaf size must be greater than 0!")
  
      if metric == "minkowski":
          if p is None:
              raise TypeError(
                  "Minkowski metric given but no p value supplied!"
              )
          if p < 0:
              raise ValueError(
                  "Minkowski metric with negative p value is not"
                  " defined!"
              )
  
      if match_reference_implementation:
          min_samples = min_samples - 1
          min_cluster_size = min_cluster_size + 1
          approx_min_span_tree = False
  
      if cluster_selection_method not in ("eom", "leaf"):
          raise ValueError(
              "Invalid Cluster Selection Method: %s\n"
              'Should be one of: "eom", "leaf"\n'
          )
  
      # Checks input and converts to an nd-array where possible
      if metric != "precomputed" or issparse(X):
          X = check_array(
              X, accept_sparse="csr", force_all_finite=False
          )
      else:
          # Only non-sparse, precomputed distance matrices are handled here
          #   and thereby allowed to contain numpy.inf for missing distances
          check_precomputed_distance_matrix(X)
  
      # Python 2 and 3 compliant string_type checking
      if isinstance(memory, str):
          memory = Memory(memory, verbose=0)
  
      size = X.shape[0]
      min_samples = min(size - 1, min_samples)
      if min_samples == 0:
          min_samples = 1
  
      if algorithm != "best":
          if (
              metric != "precomputed"
              and issparse(X)
              and algorithm != "generic"
          ):
              raise ValueError(
                  "Sparse data matrices only support algorithm 'generic'."
              )
  
          if algorithm == "generic":
              (
                  single_linkage_tree,
                  result_min_span_tree,
              ) = memory.cache(_hdbscan_generic)(
                  X,
                  min_samples,
                  alpha,
                  metric,
                  p,
                  leaf_size,
                  gen_min_span_tree,
                  **kwargs,
              )
          elif algorithm == "prims_kdtree":
              if metric not in KDTREE_VALID_METRICS:
                  raise ValueError(
                      "Cannot use Prim's with KDTree for this"
                      " metric!"
                  )
              (
                  single_linkage_tree,
                  result_min_span_tree,
              ) = memory.cache(_hdbscan_prims_kdtree)(
                  X,
                  min_samples,
                  alpha,
                  metric,
                  p,
                  leaf_size,
                  gen_min_span_tree,
                  **kwargs,
              )
          elif algorithm == "prims_balltree":
              if metric not in BALLTREE_VALID_METRICS:
                  raise ValueError(
                      "Cannot use Prim's with BallTree for this"
                      " metric!"
                  )
              (
                  single_linkage_tree,
                  result_min_span_tree,
              ) = memory.cache(_hdbscan_prims_balltree)(
                  X,
                  min_samples,
                  alpha,
                  metric,
                  p,
                  leaf_size,
                  gen_min_span_tree,
                  **kwargs,
              )
          elif algorithm == "boruvka_kdtree":
              if metric not in BALLTREE_VALID_METRICS:
                  raise ValueError(
                      "Cannot use Boruvka with KDTree for this"
                      " metric!"
                  )
              (
                  single_linkage_tree,
                  result_min_span_tree,
              ) = memory.cache(_hdbscan_boruvka_kdtree)(
                  X,
                  min_samples,
                  alpha,
                  metric,
                  p,
                  leaf_size,
                  approx_min_span_tree,
                  gen_min_span_tree,
                  core_dist_n_jobs,
                  **kwargs,
              )
          elif algorithm == "boruvka_balltree":
              if metric not in BALLTREE_VALID_METRICS:
                  raise ValueError(
                      "Cannot use Boruvka with BallTree for this"
                      " metric!"
                  )
              if (X.shape[0] // leaf_size) > 16000:
                  warn(
                      "A large dataset size and small leaf_size may induce excessive "
                      "memory usage. If you are running out of memory consider "
                      "increasing the ``leaf_size`` parameter."
                  )
              (
                  single_linkage_tree,
                  result_min_span_tree,
              ) = memory.cache(_hdbscan_boruvka_balltree)(
                  X,
                  min_samples,
                  alpha,
                  metric,
                  p,
                  leaf_size,
                  approx_min_span_tree,
                  gen_min_span_tree,
                  core_dist_n_jobs,
                  **kwargs,
              )
          else:
              raise TypeError(
                  "Unknown algorithm type %s specified" % algorithm
              )
      else:
          if issparse(X) or metric not in FAST_METRICS:
              # We can't do much with sparse matrices ...
              (
                  single_linkage_tree,
                  result_min_span_tree,
              ) = memory.cache(_hdbscan_generic)(
                  X,
                  min_samples,
                  alpha,
                  metric,
                  p,
                  leaf_size,
                  gen_min_span_tree,
                  **kwargs,
              )
          elif metric in KDTREE_VALID_METRICS:
              # TO DO: Need heuristic to decide when to go to boruvka;
              # still debugging for now
              if X.shape[1] > 60:
                  (
                      single_linkage_tree,
                      result_min_span_tree,
                  ) = memory.cache(_hdbscan_prims_kdtree)(
                      X,
                      min_samples,
                      alpha,
                      metric,
                      p,
                      leaf_size,
                      gen_min_span_tree,
                      **kwargs,
                  )
              else:
                  (
                      single_linkage_tree,
                      result_min_span_tree,
                  ) = memory.cache(_hdbscan_boruvka_kdtree)(
                      X,
                      min_samples,
                      alpha,
                      metric,
                      p,
                      leaf_size,
                      approx_min_span_tree,
                      gen_min_span_tree,
                      core_dist_n_jobs,
                      **kwargs,
                  )
          else:  # Metric is a valid BallTree metric
              # TO DO: Need heuristic to decide when to go to boruvka;
              # still debugging for now
              if X.shape[1] > 60:
                  (
                      single_linkage_tree,
                      result_min_span_tree,
                  ) = memory.cache(_hdbscan_prims_balltree)(
                      X,
                      min_samples,
                      alpha,
                      metric,
                      p,
                      leaf_size,
                      gen_min_span_tree,
                      **kwargs,
                  )
              else:
                  (
                      single_linkage_tree,
                      result_min_span_tree,
                  ) = memory.cache(_hdbscan_boruvka_balltree)(
                      X,
                      min_samples,
                      alpha,
                      metric,
                      p,
                      leaf_size,
                      approx_min_span_tree,
                      gen_min_span_tree,
                      core_dist_n_jobs,
                      **kwargs,
                  )
  
      return _tree_to_labels(
          X,
          single_linkage_tree,
          min_cluster_size,
          cluster_selection_method,
          allow_single_cluster,
          match_reference_implementation,
          cluster_selection_epsilon,
          max_cluster_size,
      ) + (result_min_span_tree,)
  
imports: import numpy
  from sklearn.base import BaseEstimator, ClusterMixin
  from sklearn.metrics import pairwise_distances
  from scipy.sparse import issparse
  from sklearn.neighbors import KDTree, BallTree
  from joblib import Memory
  from warnings import warn
  from sklearn.utils import check_array
  from joblib.parallel import cpu_count
  from scipy.sparse import csgraph
  from ._hdbscan_linkage import single_linkage, mst_linkage_core, mst_linkage_core_vector, label
  from ._hdbscan_tree import condense_tree, compute_stability, get_clusters, outlier_scores
  from ._hdbscan_reachability import mutual_reachability, sparse_mutual_reachability
  from ._hdbscan_boruvka import KDTreeBoruvkaAlgorithm, BallTreeBoruvkaAlgorithm
  from .dist_metrics import DistanceMetric
  from .plots import CondensedTree, SingleLinkageTree, MinimumSpanningTree
  from .prediction import PredictionData
  from numpy import isclose
label_desc: Use image node_id 13 for calling a global function with example usage: hdbscan(X, min_cluster_size, min_samples, alpha, cluster_selection_epsilon, max_cluster_size, metric, p, leaf_size, algorithm, memory, approx_min_span_tree, gen_min_span_tree, core_dist_n_jobs, cluster_selection_method, allow_single_cluster, match_reference_implementation) and returns: unknown