class_docstr: A measurement done on a class of objects (or Experiment or Image)
  
  A measurement represents a fully-qualified name of a measurement taken
  on an object. Measurements have categories and feature names and
  may or may not have a secondary image (for instance, the image used
  to measure an intensity), secondary object (for instance, the parent
  object when relating two classes of objects or the object name when
  aggregating object measurements over an image) or scale.
class_docstr_tok: ["A","measurement","done","on","a","class","of","objects","(","or","Experiment","or","Image",")","A","measurement","represents","a","fully-qualified","name","of","a","measurement","taken","on","an","object",".","Measurements","have","categories","and","feature","names","and","may","or","may","not","have","a","secondary","image","(","for","instance",",","the","image","used","to","measure","an","intensity",")",",","secondary","object","(","for","instance",",","the","parent","object","when","relating","two","classes","of","objects","or","the","object","name","when","aggregating","object","measurements","over","an","image",")","or","scale","."]
code: def test_valid(self, pipeline):
      obname = self.__object_fn()
      category = self.get_category(pipeline, obname)
      if category is None:
          raise ValidationError(
              "%s has an unavailable measurement category" % self.value,
              self,
          )
      feature_name = self.get_feature_name(pipeline, obname, category)
      if feature_name is None:
          raise ValidationError(
              "%s has an unmeasured feature name" % self.value, self
          )
      #
      # If there are any image names or object names, then there must
      # be a valid image name or object name
      #
      image_name = self.get_image_name(
          pipeline, obname, category, feature_name
      )
      image_names = self.get_image_name_choices(
          pipeline, obname, category, feature_name
      )
      sub_object_name = self.get_object_name(
          pipeline, obname, category, feature_name
      )
      sub_object_names = self.get_object_name_choices(
          pipeline, obname, category, feature_name
      )
      if (
          len(sub_object_names) > 0
          and image_name is None
          and sub_object_name is None
      ):
          raise ValidationError(
              "%s has an unavailable object name" % self.value, self
          )
      if (
          len(image_names) > 0
          and image_name is None
          and sub_object_name is None
      ):
          raise ValidationError(
              "%s has an unavailable image name" % self.value, self
          )
      scale_choices = self.get_scale_choices(
          pipeline, obname, category, feature_name
      )
      if (
          self.get_scale(pipeline, obname, category, feature_name)
          not in scale_choices
          and len(scale_choices) > 0
      ):
          raise ValidationError(
              "%s has an unavailable scale" % self.value, self
          )
      for module in pipeline.modules():
          if self.key() in [s.key() for s in module.visible_settings()]:
              break
      if not any(
          [
              column[0] == obname and column[1] == self.value
              for column in pipeline.get_measurement_columns(module)
          ]
      ):
          raise ValidationError(
              "%s is not measured for %s" % (self.value, obname), self
          )
  
file_path: CellProfiler/src/subpackages/core/cellprofiler_core/setting/_measurement.py
imports: from ._setting import Setting
  from ._validation_error import ValidationError
label_desc: Use image node_id 14 for calling the Measurement obj's underlying member method code with example usage: obj.test_valid(pipeline) without return types