class_docstr: A candidate generator for entity linking to a KnowledgeBase. Currently, two defaults are available:
   - Unified Medical Language System (UMLS).
   - Medical Subject Headings (MESH).
  
  To use these configured default KBs, pass the `name` parameter, either 'umls' or 'mesh'.
  
  It uses a sklearn.TfidfVectorizer to embed mention text into a sparse embedding of character 3-grams.
  These are then compared via cosine distance in a pre-indexed approximate nearest neighbours index of
  a subset of all entities and aliases in the KB.
  
  Once the K nearest neighbours have been retrieved, they are canonicalized to their KB canonical ids.
  This step is required because the index also includes entity aliases, which map to a particular canonical
  entity. This point is important for two reasons:
  
  1. K nearest neighbours will return a list of Y possible neighbours, where Y < K, because the entity ids
  are canonicalized.
  
  2. A single string may be an alias for multiple canonical entities. For example, "Jefferson County" may be an
  alias for both the canonical ids "Jefferson County, Iowa" and "Jefferson County, Texas". These are completely
  valid and important aliases to include, but it means that using the candidate generator to implement a naive
  k-nn baseline linker results in very poor performance, because there are multiple entities for some strings
  which have an exact char3-gram match, as these entities contain the same alias string. This situation results
  in multiple entities returned with a distance of 0.0, because they exactly match an alias, making a k-nn
  baseline effectively a random choice between these candidates. However, this doesn't matter if you have a
  classifier on top of the candidate generator, as is intended!
  
  Parameters
  ----------
  ann_index: FloatIndex
      An nmslib approximate nearest neighbours index.
  tfidf_vectorizer: TfidfVectorizer
      The vectorizer used to encode mentions.
  ann_concept_aliases_list: List[str]
      A list of strings, mapping the indices used in the ann_index to possible KB mentions.
      This is essentially used a lookup between the ann index and actual mention strings.
  kb: KnowledgeBase
      A class representing canonical concepts from the knowledge graph.
  verbose: bool
      Setting to true will print extra information about the generated candidates.
  ef_search: int
      The efs search parameter used in the index. This substantially effects runtime speed
      (higher is slower but slightly more accurate). Note that this parameter is ignored
      if a preconstructed ann_index is passed.
  name: str, optional (default = None)
      The name of the pretrained entity linker to load. Must be one of 'umls' or 'mesh'.
docstr: ann_index.knnQueryBatch crashes if any of the vectors is all zeros.
  This function is a wrapper around `ann_index.knnQueryBatch` that solves this problem. It works as follows:
  - remove empty vectors from `vectors`.
  - call `ann_index.knnQueryBatch` with the non-empty vectors only. This returns `neighbors`,
  a list of list of neighbors. `len(neighbors)` equals the length of the non-empty vectors.
  - extend the list `neighbors` with `None`s in place of empty vectors.
  - return the extended list of neighbors and distances.
docstr_tok: ["ann_index.knnQueryBatch","crashes","if","any","of","the","vectors","is","all","zeros",".","This","function","is","a","wrapper","around","`","ann_index.knnQueryBatch","`","that","solves","this","problem",".","It","works","as","follows",":","-","remove","empty","vectors","from","`","vectors","`",".","-","call","`","ann_index.knnQueryBatch","`","with","the","non-empty","vectors","only",".","This","returns","`","neighbors","`",",","a","list","of","list","of","neighbors",".","`","len","(","neighbors",")","`","equals","the","length","of","the","non-empty","vectors",".","-","extend","the","list","`","neighbors","`","with","`","None","`","s","in","place","of","empty","vectors",".","-","return","the","extended","list","of","neighbors","and","distances","."]
code: def nmslib_knn_with_zero_vectors(
      self, vectors: numpy.ndarray, k: int
  ) -> Tuple[numpy.ndarray, numpy.ndarray]:
      """
      ann_index.knnQueryBatch crashes if any of the vectors is all zeros.
      This function is a wrapper around `ann_index.knnQueryBatch` that solves this problem. It works as follows:
      - remove empty vectors from `vectors`.
      - call `ann_index.knnQueryBatch` with the non-empty vectors only. This returns `neighbors`,
      a list of list of neighbors. `len(neighbors)` equals the length of the non-empty vectors.
      - extend the list `neighbors` with `None`s in place of empty vectors.
      - return the extended list of neighbors and distances.
      """
      empty_vectors_boolean_flags = numpy.array(
          vectors.sum(axis=1) != 0
      ).reshape(-1)
      empty_vectors_count = vectors.shape[0] - sum(
          empty_vectors_boolean_flags
      )
      if self.verbose:
          print(f"Number of empty vectors: {empty_vectors_count}")
  
      # init extended_neighbors with a list of Nones
      extended_neighbors = numpy.empty(
          (len(empty_vectors_boolean_flags),), dtype=object
      )
      extended_distances = numpy.empty(
          (len(empty_vectors_boolean_flags),), dtype=object
      )
  
      if vectors.shape[0] - empty_vectors_count == 0:
          return extended_neighbors, extended_distances
  
      # remove empty vectors before calling `ann_index.knnQueryBatch`
      vectors = vectors[empty_vectors_boolean_flags]
  
      # call `knnQueryBatch` to get neighbors
      original_neighbours = self.ann_index.knnQueryBatch(vectors, k=k)
  
      neighbors, distances = zip(
          *[(x[0].tolist(), x[1].tolist()) for x in original_neighbours]
      )
      neighbors = list(neighbors)
      distances = list(distances)
  
      # neighbors need to be converted to an np.array of objects instead of ndarray of dimensions len(vectors)xk
      # Solution: add a row to `neighbors` with any length other than k. This way, calling np.array(neighbors)
      # returns an np.array of objects
      neighbors.append([])
      distances.append([])
      # interleave `neighbors` and Nones in `extended_neighbors`
      extended_neighbors[empty_vectors_boolean_flags] = numpy.array(
          neighbors, dtype=object
      )[:-1]
      extended_distances[empty_vectors_boolean_flags] = numpy.array(
          distances, dtype=object
      )[:-1]
  
      return extended_neighbors, extended_distances
  
imports: from typing import Optional, List, Dict, Tuple, NamedTuple, Type
  import json
  import datetime
  from collections import defaultdict
  import scipy
  import numpy
  import joblib
  from sklearn.feature_extraction.text import TfidfVectorizer
  import nmslib
  from nmslib.dist import FloatIndex
  from scispacy.file_cache import cached_path
  from scispacy.linking_utils import KnowledgeBase, UmlsKnowledgeBase, Mesh, GeneOntology, RxNorm, HumanPhenotypeOntology
label_desc: Use image node_id 2 for calling the CandidateGenerator obj's underlying member method code with example usage: obj.nmslib_knn_with_zero_vectors(vectors, k) and returns: extended_neighbors,  extended_distances, extended_neighbors,  extended_distances