class_docstr: Base class for storing and searching image signatures in a database
  
  Note:
      You must implement the methods search_single_record and insert_single_record
      in a derived class
docstr: Set up storage scheme for images
  
  Central to the speed of this approach is the transforming the image
  signature into something that can be speedily indexed and matched.
  In our case, that means splitting the image signature into N words
  of length k, then encoding those words as integers. The idea here is
  that integer indices are more efficient than array indices.
  
  For example, say your image signature is [0, 1, 2, 0, -1, -2, 0, 1] and
  k=3 and N=4. That means we want 4 words of length 3.  For this signa-
  ture, that gives us:
  
  [0, 1, 2]
  [2, 0, -1]
  [-1, -2, 0]
  [0, 1]
  
  Note that signature elements can be repeated, and any mismatch in length
  is chopped off in the last word (which will be padded with zeros). Since
  these numbers run from -2..2, there 5 possibilites.  Adding 2 to each word
  makes them strictly non-negative, then the quantity, and transforming to
  base-5 makes unique integers. For the first word:
  
  [0, 1, 2] + 2 = [2, 3, 4]
  [5**0, 5**1, 5**2] = [1, 5, 25]
  dot([2, 3, 4], [1, 5, 25]) = 2 + 15 + 100 = 117
  
  So the integer word is 117.  Storing all the integer words as different
  database columns or fields gives us the speedy lookup. In practice, word
  arrays are 'squeezed' to between -1..1 before encoding.
  
  Args:
      k (Optional[int]): the width of a word (default 16)
      N (Optional[int]): the number of words (default 63)
      n_grid (Optional[int]): the n_grid x n_grid size to use in determining
          the image signature (default 9)
      crop_percentiles (Optional[Tuple[int]]): lower and upper bounds when
          considering how much variance to keep in the image (default (5, 95))
      distance_cutoff (Optional [float]): maximum image signature distance to
          be considered a match (default 0.45)
      *signature_args: Variable length argument list to pass to ImageSignature
      **signature_kwargs: Arbitrary keyword arguments to pass to ImageSignature
docstr_tok: ["Set","up","storage","scheme","for","images","Central","to","the","speed","of","this","approach","is","the","transforming","the","image","signature","into","something","that","can","be","speedily","indexed","and","matched",".","In","our","case",",","that","means","splitting","the","image","signature","into","N","words","of","length","k",",","then","encoding","those","words","as","integers",".","The","idea","here","is","that","integer","indices","are","more","efficient","than","array","indices",".","For","example",",","say","your","image","signature","is","[","0",",","1",",","2",",","0",",","-1",",","-2",",","0",",","1","]","and","k=3","and","N=4",".","That","means","we","want","4","words","of","length","3",".","For","this","signa-","ture",",","that","gives","us",":","[","0",",","1",",","2","]","[","2",",","0",",","-1","]","[","-1",",","-2",",","0","]","[","0",",","1","]","Note","that","signature","elements","can","be","repeated",",","and","any","mismatch","in","length","is","chopped","off","in","the","last","word","(","which","will","be","padded","with","zeros",")",".","Since","these","numbers","run","from","-2","..","2",",","there","5","possibilites",".","Adding","2","to","each","word","makes","them","strictly","non-negative",",","then","the","quantity",",","and","transforming","to","base-5","makes","unique","integers",".","For","the","first","word",":","[","0",",","1",",","2","]","+","2","=","[","2",",","3",",","4","]","[","5","*","*","0",",","5","*","*","1",",","5","*","*","2","]","=","[","1",",","5",",","25","]","dot","(","[","2",",","3",",","4","]",",","[","1",",","5",",","25","]",")","=","2","+","15","+","100","=","117","So","the","integer","word","is","117",".","Storing","all","the","integer","words","as","different","database","columns","or","fields","gives","us","the","speedy","lookup",".","In","practice",",","word","arrays","are","'squeezed","'","to","between","-1","..","1","before","encoding",".","Args",":","k","(","Optional","[","int","]",")",":","the","width","of","a","word","(","default","16",")","N","(","Optional","[","int","]",")",":","the","number","of","words","(","default","63",")","n_grid","(","Optional","[","int","]",")",":","the","n_grid","x","n_grid","size","to","use","in","determining","the","image","signature","(","default","9",")","crop_percentiles","(","Optional","[","Tuple","[","int","]","]",")",":","lower","and","upper","bounds","when","considering","how","much","variance","to","keep","in","the","image","(","default","(","5",",","95",")",")","distance_cutoff","(","Optional","[","float","]",")",":","maximum","image","signature","distance","to","be","considered","a","match","(","default","0.45",")","*","signature_args",":","Variable","length","argument","list","to","pass","to","ImageSignature","*","*","signature_kwargs",":","Arbitrary","keyword","arguments","to","pass","to","ImageSignature"]
code: def __init__(
      self,
      k=16,
      N=63,
      n_grid=9,
      crop_percentile=(5, 95),
      distance_cutoff=0.45,
      *signature_args,
      **signature_kwargs,
  ):
      """Set up storage scheme for images
  
      Central to the speed of this approach is the transforming the image
      signature into something that can be speedily indexed and matched.
      In our case, that means splitting the image signature into N words
      of length k, then encoding those words as integers. The idea here is
      that integer indices are more efficient than array indices.
  
      For example, say your image signature is [0, 1, 2, 0, -1, -2, 0, 1] and
      k=3 and N=4. That means we want 4 words of length 3.  For this signa-
      ture, that gives us:
  
      [0, 1, 2]
      [2, 0, -1]
      [-1, -2, 0]
      [0, 1]
  
      Note that signature elements can be repeated, and any mismatch in length
      is chopped off in the last word (which will be padded with zeros). Since
      these numbers run from -2..2, there 5 possibilites.  Adding 2 to each word
      makes them strictly non-negative, then the quantity, and transforming to
      base-5 makes unique integers. For the first word:
  
      [0, 1, 2] + 2 = [2, 3, 4]
      [5**0, 5**1, 5**2] = [1, 5, 25]
      dot([2, 3, 4], [1, 5, 25]) = 2 + 15 + 100 = 117
  
      So the integer word is 117.  Storing all the integer words as different
      database columns or fields gives us the speedy lookup. In practice, word
      arrays are 'squeezed' to between -1..1 before encoding.
  
      Args:
          k (Optional[int]): the width of a word (default 16)
          N (Optional[int]): the number of words (default 63)
          n_grid (Optional[int]): the n_grid x n_grid size to use in determining
              the image signature (default 9)
          crop_percentiles (Optional[Tuple[int]]): lower and upper bounds when
              considering how much variance to keep in the image (default (5, 95))
          distance_cutoff (Optional [float]): maximum image signature distance to
              be considered a match (default 0.45)
          *signature_args: Variable length argument list to pass to ImageSignature
          **signature_kwargs: Arbitrary keyword arguments to pass to ImageSignature
  
      """
      # Check integer inputs
      if type(k) is not int:
          raise TypeError("k should be an integer")
      if type(N) is not int:
          raise TypeError("N should be an integer")
      if type(n_grid) is not int:
          raise TypeError("n_grid should be an integer")
  
      self.k = k
      self.N = N
      self.n_grid = n_grid
  
      # Check float input
      if type(distance_cutoff) is not float:
          raise TypeError("distance_cutoff should be a float")
      if distance_cutoff < 0.0:
          raise ValueError(
              "distance_cutoff should be > 0 (got %r)" % distance_cutoff
          )
  
      self.distance_cutoff = distance_cutoff
  
      self.crop_percentile = crop_percentile
  
      self.gis = ImageSignature(
          n=n_grid,
          crop_percentiles=crop_percentile,
          *signature_args,
          **signature_kwargs,
      )
  
file_path: image-match/image_match/signature_database_base.py
imports: from image_match.goldberg import ImageSignature
  from itertools import product
  from operator import itemgetter
  import numpy
label_desc: Use image node_id 3 to create a new SignatureDatabaseBase object from inherited base classes: object with example: obj = SignatureDatabaseBase(k, N, n_grid, crop_percentile, distance_cutoff)