code: def local_histogram_equalization(
      data,
      mask_to_equalize,
      valid_data_mask=None,
      number_of_bins=1000,
      std_mult_cutoff=3.0,
      do_zerotoone_normalization=True,
      local_radius_px: int = 300,
      clip_limit=60.0,
      slope_limit=3.0,
      do_log_scale=True,
      # can't take the log of zero, so the offset
      # may be needed; pass 0.0 if your data doesn't
      # need it
      log_offset=0.00001,
      out=None,
  ):
      """Equalize the provided data (in the mask_to_equalize) using adaptive histogram equalization.
  
      Tiles of width/height (2 * local_radius_px + 1) will be calculated and results for each pixel will be bilinearly
      interpolated from the nearest 4 tiles when pixels fall near the edge of the image (there is no adjacent tile) the
      resultant interpolated sum from the available tiles will be multiplied to account for the weight of any missing
      tiles::
  
          pixel total interpolated value = pixel available interpolated value / (1 - missing interpolation weight)
  
      If ``do_zerotoone_normalization`` is True the data will be scaled so that all data in the mask_to_equalize falls
      between 0 and 1; otherwise the data in mask_to_equalize will all fall between 0 and number_of_bins.
  
      Returns: The equalized data
      """
      out = out if out is not None else np.zeros_like(data)
      # if we don't have a valid mask, use the mask of what we should be equalizing
      if valid_data_mask is None:
          valid_data_mask = mask_to_equalize
  
      # calculate some useful numbers for our tile math
      total_rows = data.shape[0]
      total_cols = data.shape[1]
      tile_size = int(local_radius_px * 2 + 1)
      row_tiles = math.ceil(total_rows / tile_size)
      col_tiles = math.ceil(total_cols / tile_size)
  
      (
          all_cumulative_dist_functions,
          all_bin_information,
      ) = _compute_tile_dist_and_bin_info(
          data,
          valid_data_mask,
          std_mult_cutoff,
          do_log_scale,
          log_offset,
          clip_limit,
          slope_limit,
          number_of_bins,
          row_tiles,
          col_tiles,
          tile_size,
      )
  
      # get the tile weight array so we can use it to interpolate our data
      tile_weights = _calculate_weights(tile_size)
  
      # now loop through our tiles and linearly interpolate the equalized
      # versions of the data
      for num_row_tile in range(row_tiles):
          for num_col_tile in range(col_tiles):
              _interpolate_local_equalized_tiles(
                  data,
                  out,
                  mask_to_equalize,
                  valid_data_mask,
                  do_log_scale,
                  log_offset,
                  tile_weights,
                  all_bin_information,
                  all_cumulative_dist_functions,
                  num_row_tile,
                  num_col_tile,
                  tile_size,
              )
  
      # if we were asked to, normalize our data to be between zero and one,
      # rather than zero and number_of_bins
      if do_zerotoone_normalization:
          _linear_normalization_from_0to1(
              out, mask_to_equalize, number_of_bins
          )
  
      return out
  
imports: from __future__ import annotations
  import logging
  import math
  from datetime import datetime
  import dask
  import dask.array
  import numpy
  import xarray
  from satpy.composites import CompositeBase, GenericCompositor
  from satpy.dataset import combine_metadata
label_desc: Use image node_id 3 for calling a global function with example usage: local_histogram_equalization(data, mask_to_equalize, valid_data_mask, number_of_bins, std_mult_cutoff, do_zerotoone_normalization, local_radius_px, clip_limit, slope_limit, do_log_scale, log_offset, out) and returns: out