class_docstr: VectorizedDistance class represents a distance that is calculated in a vectorized way. This means
  that instead of going through every pair and explicitly calculating its distance, VectorizedDistance
  uses the entire vectors to compare to each other in a single operation.
  
  Parameters
  ----------
  distance_function : Callable[[np.ndarray, np.ndarray], np.ndarray]
      Distance function used to determine the distances between new candidates and objects.
      This function should take 2 input arguments, the first being a `np.ndarray` and the second
      `np.ndarray`. It has to return a `np.ndarray` with the distance matrix it calculates.
docstr: Method that calculates the distances between new candidates and objects.
  
  Parameters
  ----------
  objects : Sequence[TrackedObject]
      Sequence of [TrackedObject][norfair.tracker.TrackedObject] to be compared with potential [Detection][norfair.tracker.Detection] or [TrackedObject][norfair.tracker.TrackedObject]
      candidates.
  candidates : Union[List[Detection], List[TrackedObject]], optional
      List of candidates ([Detection][norfair.tracker.Detection] or [TrackedObject][norfair.tracker.TrackedObject]) to be compared to [TrackedObject][norfair.tracker.TrackedObject].
  
  Returns
  -------
  np.ndarray
      A matrix containing the distances between objects and candidates.
docstr_tok: ["Method","that","calculates","the","distances","between","new","candidates","and","objects",".","Parameters","--","--","--","--","--","objects",":","Sequence","[","TrackedObject","]","Sequence","of","[","TrackedObject","]","[","norfair.tracker.TrackedObject","]","to","be","compared","with","potential","[","Detection","]","[","norfair.tracker.Detection","]","or","[","TrackedObject","]","[","norfair.tracker.TrackedObject","]","candidates",".","candidates",":","Union","[","List","[","Detection","]",",","List","[","TrackedObject","]","]",",","optional","List","of","candidates","(","[","Detection","]","[","norfair.tracker.Detection","]","or","[","TrackedObject","]","[","norfair.tracker.TrackedObject","]",")","to","be","compared","to","[","TrackedObject","]","[","norfair.tracker.TrackedObject","]",".","Returns","--","--","--","-","np.ndarray","A","matrix","containing","the","distances","between","objects","and","candidates","."]
code: def get_distances(
      self,
      objects: Sequence["TrackedObject"],
      candidates: Optional[
          Union[List["Detection"], List["TrackedObject"]]
      ],
  ) -> np.ndarray:
      """
      Method that calculates the distances between new candidates and objects.
  
      Parameters
      ----------
      objects : Sequence[TrackedObject]
          Sequence of [TrackedObject][norfair.tracker.TrackedObject] to be compared with potential [Detection][norfair.tracker.Detection] or [TrackedObject][norfair.tracker.TrackedObject]
          candidates.
      candidates : Union[List[Detection], List[TrackedObject]], optional
          List of candidates ([Detection][norfair.tracker.Detection] or [TrackedObject][norfair.tracker.TrackedObject]) to be compared to [TrackedObject][norfair.tracker.TrackedObject].
  
      Returns
      -------
      np.ndarray
          A matrix containing the distances between objects and candidates.
      """
      distance_matrix = np.full(
          (len(candidates), len(objects)),
          fill_value=np.inf,
          dtype=np.float32,
      )
      if not objects or not candidates:
          return distance_matrix
  
      object_labels = np.array([o.label for o in objects]).astype(str)
      candidate_labels = np.array([c.label for c in candidates]).astype(
          str
      )
  
      # iterate over labels that are present both in objects and detections
      for label in np.intersect1d(
          np.unique(object_labels), np.unique(candidate_labels)
      ):
          # generate masks of the subset of object and detections for this label
          obj_mask = object_labels == label
          cand_mask = candidate_labels == label
  
          stacked_objects = []
          for o in objects:
              if str(o.label) == label:
                  stacked_objects.append(o.estimate.ravel())
          stacked_objects = np.stack(stacked_objects)
  
          stacked_candidates = []
          for c in candidates:
              if str(c.label) == label:
                  if "Detection" in str(type(c)):
                      stacked_candidates.append(c.points.ravel())
                  else:
                      stacked_candidates.append(c.estimate.ravel())
          stacked_candidates = np.stack(stacked_candidates)
  
          # calculate the pairwise distances between objects and candidates with this label
          # and assign the result to the correct positions inside distance_matrix
          distance_matrix[
              np.ix_(cand_mask, obj_mask)
          ] = self._compute_distance(
              stacked_candidates, stacked_objects
          )
  
      return distance_matrix
  
imports: from abc import ABC, abstractmethod
  from functools import partial
  from logging import warning
  from typing import TYPE_CHECKING, Callable, List, Optional, Sequence, Union
  import numpy
  from scipy.spatial.distance import cdist
label_desc: Use image node_id 2 for calling the VectorizedDistance obj's underlying member method code with example usage: obj.get_distances(objects, candidates) and returns: distance_matrix, distance_matrix