docstr: Return an array containing the best object per enclosing object
  
  workspace - workspace passed into Run
  src_objects - the Objects instance to be filtered
docstr_tok: ["Return","an","array","containing","the","best","object","per","enclosing","object","workspace","-","workspace","passed","into","Run","src_objects","-","the","Objects","instance","to","be","filtered"]
code: def keep_per_object(self, workspace, src_objects):
      """Return an array containing the best object per enclosing object
  
      workspace - workspace passed into Run
      src_objects - the Objects instance to be filtered
      """
      measurement = self.measurements[0].measurement.value
      src_name = self.x_name.value
      enclosing_name = self.enclosing_object_name.value
      src_objects = workspace.get_objects(src_name)
      enclosing_objects = workspace.get_objects(enclosing_name)
      enclosing_labels = enclosing_objects.segmented
      enclosing_max = enclosing_objects.count
      if enclosing_max == 0:
          return numpy.array([], int)
      enclosing_range = numpy.arange(1, enclosing_max + 1)
      #
      # Make a vector of the value of the measurement per label index.
      # We can then label each pixel in the image with the measurement
      # value for the object at that pixel.
      # For unlabeled pixels, put the minimum value if looking for the
      # maximum value and vice-versa
      #
      values = workspace.measurements.get_current_measurement(
          src_name, measurement
      )
      wants_max = self.filter_choice == FI_MAXIMAL_PER_OBJECT
      src_labels = src_objects.segmented
      src_count = src_objects.count
      if self.per_object_assignment == PO_PARENT_WITH_MOST_OVERLAP:
          #
          # Find the number of overlapping pixels in enclosing
          # and source objects
          #
          mask = enclosing_labels * src_labels != 0
          enclosing_labels = enclosing_labels[mask]
          src_labels = src_labels[mask]
          order = numpy.lexsort((enclosing_labels, src_labels))
          src_labels = src_labels[order]
          enclosing_labels = enclosing_labels[order]
          firsts = numpy.hstack(
              (
                  [0],
                  numpy.where(
                      (src_labels[:-1] != src_labels[1:])
                      | (enclosing_labels[:-1] != enclosing_labels[1:])
                  )[0]
                  + 1,
                  [len(src_labels)],
              )
          )
          areas = firsts[1:] - firsts[:-1]
          enclosing_labels = enclosing_labels[firsts[:-1]]
          src_labels = src_labels[firsts[:-1]]
          #
          # Re-sort by source label value and area descending
          #
          if wants_max:
              svalues = -values
          else:
              svalues = values
          order = numpy.lexsort((-areas, svalues[src_labels - 1]))
          src_labels, enclosing_labels, areas = [
              x[order] for x in (src_labels, enclosing_labels, areas)
          ]
          firsts = numpy.hstack(
              (
                  [0],
                  numpy.where(src_labels[:-1] != src_labels[1:])[0] + 1,
                  src_labels.shape[:1],
              )
          )
          counts = firsts[1:] - firsts[:-1]
          #
          # Process them in order. The maximal or minimal child
          # will be assigned to the most overlapping parent and that
          # parent will be excluded.
          #
          best_src_label = numpy.zeros(enclosing_max + 1, int)
          for idx, count in zip(firsts[:-1], counts):
              for i in range(count):
                  enclosing_object_number = enclosing_labels[idx + i]
                  if best_src_label[enclosing_object_number] == 0:
                      best_src_label[
                          enclosing_object_number
                      ] = src_labels[idx]
                      break
          #
          # Remove best source labels = 0 and sort to get the list
          #
          best_src_label = best_src_label[best_src_label != 0]
          best_src_label.sort()
          return best_src_label
      else:
          tricky_values = numpy.zeros((len(values) + 1,))
          tricky_values[1:] = values
          if wants_max:
              tricky_values[0] = -numpy.Inf
          else:
              tricky_values[0] = numpy.Inf
          src_values = tricky_values[src_labels]
          #
          # Now find the location of the best for each of the enclosing objects
          #
          fn = (
              scipy.ndimage.maximum_position
              if wants_max
              else scipy.ndimage.minimum_position
          )
          best_pos = fn(src_values, enclosing_labels, enclosing_range)
          best_pos = numpy.array(
              (best_pos,) if isinstance(best_pos, tuple) else best_pos
          )
          best_pos = best_pos.astype(numpy.uint32)
          #
          # Get the label of the pixel at each location
          #
          # Multidimensional indexing with non-tuple values is not allowed as of numpy 1.23
          best_pos = tuple(map(tuple, best_pos.transpose()))
          indexes = src_labels[best_pos]
          indexes = set(indexes)
          indexes = list(indexes)
          indexes.sort()
          return (
              indexes[1:]
              if len(indexes) > 0 and indexes[0] == 0
              else indexes
          )
  
imports: from cellprofiler_core.constants.measurement import M_LOCATION_CENTER_X, M_LOCATION_CENTER_Y, C_CHILDREN, C_PARENT, C_LOCATION, C_NUMBER, FTR_OBJECT_NUMBER, C_COUNT, FTR_CENTER_X, FTR_CENTER_Y, FTR_CENTER_Z
  from cellprofiler_core.module.image_segmentation import ObjectProcessing
  from cellprofiler_core.preferences import DEFAULT_INPUT_FOLDER_NAME, ABSOLUTE_FOLDER_NAME, DEFAULT_INPUT_SUBFOLDER_NAME, DEFAULT_OUTPUT_SUBFOLDER_NAME
  from cellprofiler_core.setting import Divider, HiddenCount, SettingsGroup, Measurement, Binary, ValidationError
  from cellprofiler_core.setting.choice import Choice
  from cellprofiler_core.setting.do_something import DoSomething, RemoveSettingButton
  from cellprofiler_core.setting.subscriber import LabelSubscriber
  from cellprofiler_core.setting.text import Directory, Filename, Float, LabelName
  from cellprofiler.modules import _help
  import logging
  import os
  import numpy
  import scipy
  import scipy.ndimage
  import scipy.sparse
  import cellprofiler.gui.help
  import cellprofiler_core.object
  from cellprofiler.utilities.rules import Rules
label_desc: Use image node_id 15 for calling the FilterObjects obj's underlying member method code with example usage: obj.keep_per_object(workspace, src_objects) and returns: numpy, best_src_label, unknown