class_docstr: Texture mixin class for smarter scaling decisions.
  
  This class wraps the logic to normalize data on the CPU before sending
  it to the GPU (the texture). Pre-scaling on the CPU can be helpful in
  cases where OpenGL 2/ES requirements limit the texture storage to an
  8-bit normalized integer internally.
  
  This class includes optimizations where image data is not re-normalized
  if the previous normalization can still be used to visualize the data
  with the new color limits.
  
  This class should only be used internally. For similar features where
  scaling occurs on the GPU see
  :class:`vispy.visuals._scalable_textures.GPUScaledTextureMixin`.
  
  To use this mixin, a subclass should be created to combine this mixin with
  the texture class being used. Existing subclasses already exist in this
  module. Note that this class **must** appear first in the subclass's parent
  classes so that its ``__init__`` method is called instead of the parent
  Texture class.
class_docstr_tok: ["Texture","mixin","class","for","smarter","scaling","decisions",".","This","class","wraps","the","logic","to","normalize","data","on","the","CPU","before","sending","it","to","the","GPU","(","the","texture",")",".","Pre-scaling","on","the","CPU","can","be","helpful","in","cases","where","OpenGL","2\/ES","requirements","limit","the","texture","storage","to","an","8-bit","normalized","integer","internally",".","This","class","includes","optimizations","where","image","data","is","not","re-normalized","if","the","previous","normalization","can","still","be","used","to","visualize","the","data","with","the","new","color","limits",".","This","class","should","only","be","used","internally",".","For","similar","features","where","scaling","occurs","on","the","GPU","see",":","class",":","`","vispy.visuals._scalable_textures.GPUScaledTextureMixin","`",".","To","use","this","mixin",",","a","subclass","should","be","created","to","combine","this","mixin","with","the","texture","class","being","used",".","Existing","subclasses","already","exist","in","this","module",".","Note","that","this","class","*","*","must","*","*","appear","first","in","the","subclass","'s","parent","classes","so","that","its","``","__init__","``","method","is","called","instead","of","the","parent","Texture","class","."]
docstr: Normalize current clims to match texture data inside the shader.
  
  If data is scaled on the CPU then the texture data will be in the range
  0-1 in the _build_texture() method. Inside the fragment shader the
  final contrast adjustment will be applied based on this normalized
  ``clim``.
docstr_tok: ["Normalize","current","clims","to","match","texture","data","inside","the","shader",".","If","data","is","scaled","on","the","CPU","then","the","texture","data","will","be","in","the","range","0-1","in","the","_build_texture","(",")","method",".","Inside","the","fragment","shader","the","final","contrast","adjustment","will","be","applied","based","on","this","normalized","``","clim","``","."]
code: def clim_normalized(self):
      """Normalize current clims to match texture data inside the shader.
  
      If data is scaled on the CPU then the texture data will be in the range
      0-1 in the _build_texture() method. Inside the fragment shader the
      final contrast adjustment will be applied based on this normalized
      ``clim``.
  
      """
      if isinstance(self.clim, str) and self.clim == "auto":
          raise RuntimeError(
              "Can't return 'auto' normalized color limits "
              "until data has been set. Call "
              "'scale_and_set_data' first."
          )
      if self._data_limits is None:
          raise RuntimeError(
              "Can't return normalized color limits until "
              "data has been set. Call "
              "'scale_and_set_data' first."
          )
  
      range_min, range_max = self._data_limits
      clim_min, clim_max = self.clim
      if clim_min == clim_max:
          return 0, np.inf
      clim_min = (clim_min - range_min) / (range_max - range_min)
      clim_max = (clim_max - range_min) / (range_max - range_min)
      return clim_min, clim_max
  
imports: import warnings
  import numpy
  from vispy.gloo.texture import Texture2D, Texture3D, convert_dtype_and_clip
label_desc: Use image node_id 4 for calling the CPUScaledTextureMixin obj's underlying member method code with example usage: obj.clim_normalized() and returns: clim_min,  clim_max, int,  np