class_docstr: Return the Predictive Power Score of image properties, in order to estimate their ability to predict the label.
  
  The PPS represents the ability of a feature to single-handedly predict another feature or label.
  In this check, we specifically use it to assess the ability to predict the label by an image property (e.g.
  brightness, contrast etc.)
  A high PPS (close to 1) can mean that there's a bias in the dataset, as a single property can predict the label
  successfully, using simple classic ML algorithms - meaning that a deep learning algorithm may accidentally learn
  these properties instead of more accurate complex abstractions.
  For example, in a classification dataset of wolves and dogs photographs, if only wolves are photographed in the
  snow, the brightness of the image may be used to predict the label "wolf" easily. In this case, a model might not
  learn to discern wolf from dog by the animal's characteristics, but by using the background color.
  
  When we compare train PPS to test PPS, A high difference can strongly indicate bias in the datasets,
  as a property that was "powerful" in train but not in test can be explained by bias in train that does
  not affect a new dataset.
  
  For classification tasks, this check uses PPS to predict the class by image properties.
  For object detection tasks, this check uses PPS to predict the class of each bounding box, by the image properties
  of that specific bounding box.
  
  Uses the ppscore package - for more info, see https://github.com/8080labs/ppscore
  
  Parameters
  ----------
  image_properties : List[Dict[str, Any]], default: None
      List of properties. Replaces the default deepchecks properties.
      Each property is a dictionary with keys ``'name'`` (str), ``method`` (Callable) and ``'output_type'`` (str),
      representing attributes of said method. 'output_type' must be one of:
  
      - ``'numerical'`` - for continuous ordinal outputs.
      - ``'categorical'`` - for discrete, non-ordinal outputs. These can still be numbers,
        but these numbers do not have inherent value.
  
      For more on image / label properties, see the guide about :ref:`vision__properties_guide`.
  per_class : bool, default: True
      boolean that indicates whether the results of this check should be calculated for all classes or per class in
      label. If True, the conditions will be run per class as well.
  n_top_properties: int, default: 5
      Number of features to show, sorted by the magnitude of difference in PPS
  random_state: int, default: None
      Random state for the ppscore.predictors function
  min_pps_to_show: float, default 0.05
          Minimum PPS to show a class in the graph
  ppscore_params: dict, default: None
      dictionary of additional parameters for the ppscore predictor function
  {additional_check_init_params:2*indent}
docstr: Add new condition.
  
  Add condition that will check that train dataset property pps is less than X. If per_class is True, the
  condition will apply per class, and a single class with pps greater than X will be enough to fail the
  condition.
  
  Parameters
  ----------
  threshold : float , default: 0.2
      pps upper bound
  
  Returns
  -------
  SFC
docstr_tok: ["Add","new","condition",".","Add","condition","that","will","check","that","train","dataset","property","pps","is","less","than","X",".","If","per_class","is","True",",","the","condition","will","apply","per","class",",","and","a","single","class","with","pps","greater","than","X","will","be","enough","to","fail","the","condition",".","Parameters","--","--","--","--","--","threshold",":","float",",","default",":","0.2","pps","upper","bound","Returns","--","--","--","-","SFC"]
code: def add_condition_property_pps_in_train_less_than(
      self: PLC, threshold: float = 0.2
  ) -> PLC:
      """Add new condition.
  
      Add condition that will check that train dataset property pps is less than X. If per_class is True, the
      condition will apply per class, and a single class with pps greater than X will be enough to fail the
      condition.
  
      Parameters
      ----------
      threshold : float , default: 0.2
          pps upper bound
  
      Returns
      -------
      SFC
      """
  
      def condition(
          value: Union[
              Dict[Hashable, Dict[Hashable, float]],
              Dict[Hashable, Dict[Hashable, Dict[Hashable, float]]],
          ]
      ) -> ConditionResult:
          if self.per_class:
              failed_features = {}
              overall_max_pps = -np.inf, ""
              for feature, pps_info in value.items():
                  failed_classes = {
                      class_name: format_number(pps)
                      for class_name, pps in pps_info["train"].items()
                      if pps >= threshold
                  }
                  if failed_classes:
                      failed_features[feature] = failed_classes
                  # Get max diff to display when condition is passing
                  max_class, max_pps = get_dict_entry_by_value(
                      pps_info["train"]
                  )
                  if max_pps > overall_max_pps[0]:
                      overall_max_pps = (
                          max_pps,
                          f"Found highest PPS in train dataset {format_number(max_pps)} for "
                          f"property {feature} and class {max_class}",
                      )
  
              if failed_features:
                  message = f"Properties and classes in train dataset with PPS above threshold: {failed_features}"
                  return ConditionResult(
                      ConditionCategory.FAIL, message
                  )
              else:
                  message = (
                      overall_max_pps[1]
                      if overall_max_pps[0] > 0
                      else "0 PPS found for all properties in "
                      "train dataset"
                  )
                  return ConditionResult(
                      ConditionCategory.PASS, message
                  )
          else:
              failed_features = {
                  feature_name: format_number(pps_value)
                  for feature_name, pps_value in value["train"].items()
                  if pps_value >= threshold
              }
  
              if failed_features:
                  message = f"Properties in train dataset with PPS above threshold: {failed_features}"
                  return ConditionResult(
                      ConditionCategory.FAIL, message
                  )
              else:
                  max_feature, max_pps = get_dict_entry_by_value(
                      value["train-test difference"]
                  )
                  message = (
                      f"Found highest PPS in train dataset {format_number(max_pps)} for property {max_feature}"
                      if max_pps > 0
                      else "0 PPS found for all properties in train dataset"
                  )
                  return ConditionResult(
                      ConditionCategory.PASS, message
                  )
  
      return self.add_condition(
          f"Train properties' Predictive Power Score is less than "
          f"{format_number(threshold)}",
          condition,
      )
  
imports: from collections import defaultdict
  from typing import Any, Dict, Hashable, List, Optional, TypeVar, Union
  import numpy
  import pandas
  from deepchecks.core import CheckResult, ConditionResult, DatasetKind
  from deepchecks.core.check_utils.feature_label_correlation_utils import get_feature_label_correlation, get_feature_label_correlation_per_class
  from deepchecks.core.condition import ConditionCategory
  from deepchecks.utils.dict_funcs import get_dict_entry_by_value
  from deepchecks.utils.strings import format_number
  from deepchecks.vision._shared_docs import docstrings
  from deepchecks.vision.base_checks import TrainTestCheck
  from deepchecks.vision.context import Context
  from deepchecks.vision.utils.property_label_correlation_utils import calc_properties_for_property_label_correlation
  from deepchecks.vision.vision_data import TaskType
  from deepchecks.vision.vision_data.batch_wrapper import BatchWrapper
label_desc: Use image node_id 6 for calling the PropertyLabelCorrelationChange obj's underlying member method code with example usage: obj.add_condition_property_pps_in_train_less_than(threshold) and returns: self, ConditionResult, ConditionResult, ConditionResult, ConditionResult