docs: def get_threshold(threshold_method, threshold_modifier, image, 
                    mask=None, labels = None,
                    threshold_range_min = None, threshold_range_max = None,
                    threshold_correction_factor = 1.0,
                    adaptive_window_size = 10, **kwargs):
      """Compute a threshold for an image
      
      threshold_method - one of the TM_ methods above
      threshold_modifier - TM_GLOBAL to calculate one threshold over entire image
                           TM_ADAPTIVE to calculate a per-pixel threshold
                           TM_PER_OBJECT to calculate a different threshold for
                           each object
      image - a NxM numpy array of the image data
  
      Returns a tuple of local_threshold and global_threshold where:
      * global_threshold is the single number calculated using the threshold
      method over the whole image
      * local_threshold is the global_threshold for global methods. For adaptive
      and per-object thresholding, local_threshold is a matrix of threshold
      values representing the threshold to be applied at each pixel of the
      image.
      
      Different methods have optional and required parameters:
      Required:
      TM_PER_OBJECT:
      labels - a labels matrix that defines the extents of the individual objects
               to be thresholded separately.
      
      Optional:
      All:
      mask - a mask of the significant pixels in the image
      threshold_range_min, threshold_range_max - constrain the threshold
          values to be examined to values between these limits
      threshold_correction_factor - the calculated threshold is multiplied
          by this number to get the final threshold
      TM_MOG (mixture of Gaussians):
      object_fraction - fraction of image expected to be occupied by objects
          (pixels that are above the threshold)
      TM_OTSU - We have algorithms derived from Otsu. There is a three-class
                version of Otsu in addition to the two class. There is also
                an entropy measure in addition to the weighted variance.
                two_class_otsu - assume that the distribution represents
                                 two intensity classes if true, three if false.
                use_weighted_variance - use Otsu's weighted variance if true,
                                        an entropy measure if false
                assign_middle_to_foreground - assign pixels in the middle class
                                 in a three-class Otsu to the foreground if true
                                 or the background if false.
      """
      global_threshold = get_global_threshold(
          threshold_method, image, mask, **kwargs)
      global_threshold *= threshold_correction_factor
      if not threshold_range_min is None:
          global_threshold = max(global_threshold, threshold_range_min)
      if not threshold_range_max is None:
          global_threshold = min(global_threshold, threshold_range_max)
      if threshold_modifier == TM_GLOBAL:
          local_threshold=global_threshold
      elif threshold_modifier == TM_ADAPTIVE:
          local_threshold = get_adaptive_threshold(
              threshold_method, image, global_threshold,
              mask, adaptive_window_size = adaptive_window_size, **kwargs)
          local_threshold = local_threshold * threshold_correction_factor
      elif threshold_modifier == TM_PER_OBJECT:
          local_threshold = get_per_object_threshold(
              threshold_method, image, global_threshold, mask, labels,
              threshold_range_min, threshold_range_max,**kwargs)
          local_threshold = local_threshold * threshold_correction_factor
      else:
          raise NotImplementedError("%s thresholding is not implemented"%(threshold_modifier))
      if isinstance(local_threshold, np.ndarray):
          #
          # Constrain thresholds to within .7 to 1.5 of the global threshold.
          #
          threshold_range_min = max(threshold_range_min, global_threshold * .7)
          threshold_range_max = min(threshold_range_max, global_threshold * 1.5)
          if not threshold_range_min is None:
              local_threshold[local_threshold < threshold_range_min] = \
                  threshold_range_min
          if not threshold_range_max is None:
              local_threshold[local_threshold > threshold_range_max] = \
              threshold_range_max
          if (threshold_modifier == TM_PER_OBJECT) and (labels is not None):
              local_threshold[labels == 0] = 1.0
      else:
          if not threshold_range_min is None:
              local_threshold = max(local_threshold, threshold_range_min)
          if not threshold_range_max is None:
              local_threshold = min(local_threshold, threshold_range_max)
      return local_threshold, global_threshold