code: def pull_bounds(
      row,
      red_high,
      yellow_high,
      yellow_low: int = 0,
      red_low: int = 0,
      suffix_mean: str = "_mean",
      suffix_std: str = "_std",
      cols=None,
  ):
      """Calculate traffic light pull bounds for list of cols
  
      Function can be used with ApplyFunc module.
  
      :param pd.Series row: row to apply this function to.
      :param float red_high: higher bound of red traffic light
      :param float yellow_high: higher bound of yellow traffic light
      :param float yellow_low: lower bound of yellow traffic light (optional)
      :param float red_low: lower bound of red traffic light (optional)
      :param str suffix_mean: suffix of mean column. default is '_mean' (optional)
      :param str suffix_std: suffix of std column. default is '_std' (optional)
      :param list cols: list of cols to calculate bounds of (optional)
      """
      assert (
          np.diff([red_high, yellow_high, yellow_low, red_low]) > 0
      ).sum() == 0, "Traffic lights not sorted!"
  
      if cols is None or len(cols) == 0:
          # if no columns are given, find columns for which pulls can be calculated.
          # e.g. to calculate x_pull, need to have [x, x_mean, x_std] present. If so, put x in cols.
          cols = []
          for m in row.index.to_list():
              if m not in cols:
                  required = [m, m + suffix_mean, m + suffix_std]
                  if all(r in row for r in required):
                      cols.append(m)
      else:
          for m in cols:
              required = [m + suffix_mean, m + suffix_std]
              assert all(r in row for r in required)
  
      x = {}
      for m in cols:
          x[m + "_red_high"] = np.nan
          x[m + "_yellow_high"] = np.nan
          x[m + "_yellow_low"] = np.nan
          x[m + "_red_low"] = np.nan
          required = [m + suffix_mean, m + suffix_std]
          if any(pd.isnull(row[required])):
              continue
          x[m + "_red_high"] = (
              row[m + suffix_mean] + row[m + suffix_std] * red_high
          )
          x[m + "_yellow_high"] = (
              row[m + suffix_mean] + row[m + suffix_std] * yellow_high
          )
          x[m + "_yellow_low"] = (
              row[m + suffix_mean] + row[m + suffix_std] * yellow_low
          )
          x[m + "_red_low"] = (
              row[m + suffix_mean] + row[m + suffix_std] * red_low
          )
      return pd.Series(x)
  
imports: from __future__ import annotations
  import copy
  import fnmatch
  from collections import defaultdict
  from typing import Any
  import numpy
  import pandas
  from popmon.analysis.apply_func import ApplyFunc
  from popmon.base import Module, Pipeline
label_desc: Use image node_id 4 for calling a global function with example usage: pull_bounds(row, red_high, yellow_high, yellow_low, red_low, suffix_mean, suffix_std, cols) and returns: pd