code: def _connected_components(
      edgelist: Scores, max_components: int
  ) -> Generator[Scores, None, None]:
      component_stops = union_find(edgelist)
  
      start = 0
      for stop in component_stops:
          sub_graph = edgelist[start:stop]
          n_edges = stop - start
          start = stop
  
          needs_filtering = False
          # first we find the upper bound of the
          # number of components given the edgelist
          upper_bound_components = n_edges + 1
          if upper_bound_components > max_components:
              # which we can refine using a more expensive operation
              # if it's possible we have too many components
              n_components = len(numpy.unique(sub_graph["pairs"]))
              if n_components > max_components:
                  needs_filtering = True
  
          if needs_filtering:
              min_score = numpy.min(sub_graph["score"])
              min_score_logit = numpy.log(min_score) - numpy.log(
                  1 - min_score
              )
              threshold = 1 / (1 + numpy.exp(-min_score_logit - 1))
              logger.warning(
                  "A component contained %s elements. "
                  "Components larger than %s are "
                  "re-filtered. The threshold for this "
                  "filtering is %s"
                  % (n_components, max_components, threshold)
              )
              # slices of memmaped arrays are also memmaped arrays,
              # which is what we want. The components should
              # already sorted by score so we can slice as oppose
              # to selecting like `sub_graph[sub_graph['score'] >
              # threshold]`, which would lead to an in memory copy being
              # made
              cut_point = numpy.searchsorted(
                  sub_graph["score"], threshold
              )
              filtered_sub_graph = sub_graph[max(cut_point, 2) :]
  
              for sub_graph in _connected_components(
                  filtered_sub_graph, max_components
              ):
                  yield sub_graph[["pairs", "score"]]
          else:
              yield sub_graph[["pairs", "score"]]
  
imports: from __future__ import annotations
  import array
  import itertools
  import logging
  import tempfile
  from collections import defaultdict
  from typing import Generator, Iterable, Sequence, cast
  import numpy
  import numpy.typing
  import scipy.cluster.hierarchy
  from dedupe._typing import ArrayLinks, Clusters, RecordID, Scores, TupleLinks
label_desc: Use image node_id 2 for calling a global function with example usage: _connected_components(edgelist, max_components) without return types