code: def add_measurement(self, flag_settings, can_delete=True):
      measurement_settings = flag_settings.measurement_settings
  
      group = SettingsGroup()
      group.append("divider1", Divider(line=False))
      group.append(
          "source_choice",
          Choice(
              "Flag is based on",
              S_ALL,
              doc="""\
  -  *%(S_IMAGE)s:* A per-image measurement, such as intensity or
     granularity.
  -  *%(S_AVERAGE_OBJECT)s:* The average of all object measurements in
     the image.
  -  *%(S_ALL_OBJECTS)s:* All the object measurements in an image,
     without averaging. In other words, if *any* of the objects meet the
     criteria, the image will be flagged.
  -  *%(S_RULES)s:* Use a text file of rules produced by CellProfiler
     Analyst. With this option, you will have to ensure that this pipeline
     produces every measurement in the rules file upstream of this module.
  -  *%(S_CLASSIFIER)s:* Use a classifier built by CellProfiler Analyst.
  """
              % globals(),
          ),
      )
  
      group.append(
          "object_name",
          LabelSubscriber(
              "Select the object to be used for flagging",
              "None",
              doc="""\
  *(Used only when flag is based on an object measurement)*
  
  Select the objects whose measurements you want to use for flagging.
  """,
          ),
      )
  
      def object_fn():
          if group.source_choice == S_IMAGE:
              return IMAGE
          return group.object_name.value
  
      group.append(
          "rules_directory",
          Directory(
              "Rules file location",
              doc="""\
  *(Used only when flagging using "{rules}")*
  
  Select the location of the rules file that will be used for flagging images.
  {folder_choice}
  """.format(
                  rules=S_RULES,
                  folder_choice=IO_FOLDER_CHOICE_HELP_TEXT,
              ),
          ),
      )
  
      def get_directory_fn():
          """Get the directory for the rules file name"""
          return group.rules_directory.get_absolute_path()
  
      def set_directory_fn(path):
          (
              dir_choice,
              custom_path,
          ) = group.rules_directory.get_parts_from_path(path)
          group.rules_directory.join_parts(dir_choice, custom_path)
  
      group.append(
          "rules_file_name",
          Filename(
              "Rules file name",
              "rules.txt",
              get_directory_fn=get_directory_fn,
              set_directory_fn=set_directory_fn,
              doc="""\
  *(Used only when flagging using "%(S_RULES)s")*
  
  The name of the rules file, most commonly from CellProfiler Analyst's
  Classifier. This file should be a plain text file
  containing the complete set of rules.
  
  Each line of this file should be a rule naming a measurement to be made
  on an image, for instance:
  
      IF (Image_ImageQuality_PowerLogLogSlope_DNA < -2.5, [0.79, -0.79], [-0.94, 0.94])
  
  The above rule will score +0.79 for the positive category and -0.94
  for the negative category for images whose power log slope is less
  than -2.5 pixels and will score the opposite for images whose slope is
  larger. The filter adds positive and negative and flags the images
  whose positive score is higher than the negative score.
  """
              % globals(),
          ),
      )
  
      def get_rules_class_choices(group=group):
          """Get the available choices from the rules file"""
          try:
              if group.source_choice == S_CLASSIFIER:
                  return self.get_bin_labels(group)
              elif group.source_choice == S_RULES:
                  rules = self.get_rules(group)
                  nclasses = len(rules.rules[0].weights[0])
                  return [str(i) for i in range(1, nclasses + 1)]
              else:
                  return ["None"]
              rules = self.get_rules(group)
              nclasses = len(rules.rules[0].weights[0])
              return [str(i) for i in range(1, nclasses + 1)]
          except:
              return [str(i) for i in range(1, 3)]
  
      group.append(
          "rules_class",
          MultiChoice(
              "Class number",
              choices=["1", "2"],
              doc="""\
  *(Used only when flagging using "%(S_RULES)s")*
  
  Select which classes to flag when filtering. The CellProfiler Analyst
  Classifier user interface lists the names of the classes in order. By
  default, these are the positive (class 1) and negative (class 2)
  classes. **FlagImage** uses the first class from CellProfiler Analyst
  if you choose “1”, etc.
  
  Please note the following:
  
  -  The flag is set if the image falls into the selected class.
  -  You can make multiple class selections. If you do so, the module will
     set the flag if the image falls into any of the selected classes.
  """
              % globals(),
          ),
      )
  
      group.rules_class.get_choices = get_rules_class_choices
  
      group.append(
          "measurement",
          Measurement(
              "Which measurement?",
              object_fn,
              doc="""Choose the measurement to be used as criteria.""",
          ),
      )
  
      group.append(
          "wants_minimum",
          Binary(
              "Flag images based on low values?",
              True,
              doc="""\
  Select *Yes* to flag images with measurements below the specified
  cutoff. If the measurement evaluates to Not-A-Number (NaN), then the
  image is not flagged.
  """
              % globals(),
          ),
      )
  
      group.append(
          "minimum_value",
          Float(
              "Minimum value",
              0,
              doc="""Set a value as a lower limit.""",
          ),
      )
  
      group.append(
          "wants_maximum",
          Binary(
              "Flag images based on high values?",
              True,
              doc="""\
  Select *Yes* to flag images with measurements above the specified
  cutoff. If the measurement evaluates to Not-A-Number (NaN), then the
  image is not flagged.
  """
              % globals(),
          ),
      )
  
      group.append(
          "maximum_value",
          Float(
              "Maximum value",
              1,
              doc="""Set a value as an upper limit.""",
          ),
      )
  
      if can_delete:
          group.append(
              "remover",
              RemoveSettingButton(
                  "",
                  "Remove this measurement",
                  measurement_settings,
                  group,
              ),
          )
  
      group.append("divider2", Divider(line=True))
      self.rules.create_settings()
      group.append("allow_fuzzy", self.rules.settings()[0])
      measurement_settings.append(group)
  
imports: import logging
  import os
  import numpy
  from cellprofiler_core.constants.measurement import IMAGE, COLTYPE_INTEGER
  from cellprofiler_core.constants.module import IO_FOLDER_CHOICE_HELP_TEXT
  from cellprofiler_core.constants.workspace import DISPOSITION_CONTINUE, DISPOSITION_SKIP
  from cellprofiler_core.measurement import Measurements
  from cellprofiler_core.module import Module
  from cellprofiler_core.preferences import DEFAULT_INPUT_FOLDER_NAME
  from cellprofiler_core.setting import Binary
  from cellprofiler_core.setting import Divider
  from cellprofiler_core.setting import HiddenCount
  from cellprofiler_core.setting import Measurement
  from cellprofiler_core.setting import SettingsGroup
  from cellprofiler_core.setting import ValidationError
  from cellprofiler_core.setting.choice import Choice
  from cellprofiler_core.setting.do_something import DoSomething, RemoveSettingButton
  from cellprofiler_core.setting.multichoice import MultiChoice
  from cellprofiler_core.setting.subscriber import LabelSubscriber
  from cellprofiler_core.setting.text import Text, Filename, Directory, Float
  from cellprofiler.utilities.rules import Rules
label_desc: Use image node_id 4 for calling the FlagImage obj's underlying member method code with example usage: obj.add_measurement(flag_settings, can_delete) and returns: group, group, IMAGE, unknown, self, unknown, unknown, list