code: def recall(
      y_true: Union[
          pd.Series,
          pd.DataFrame,
          List[Union[Tuple[pd.Timestamp, pd.Timestamp], pd.Timestamp]],
          Dict[
              str,
              List[
                  Union[Tuple[pd.Timestamp, pd.Timestamp], pd.Timestamp]
              ],
          ],
      ],
      y_pred: Union[
          pd.Series,
          pd.DataFrame,
          List[Union[Tuple[pd.Timestamp, pd.Timestamp], pd.Timestamp]],
          Dict[
              str,
              List[
                  Union[Tuple[pd.Timestamp, pd.Timestamp], pd.Timestamp]
              ],
          ],
      ],
      thresh: float = 0.5,
  ) -> Union[float, Dict[str, float]]:
      """Recall score of prediction.
  
      Recall, a.k.a. sensitivity, hit rate, or true positive rate (TPR), is the
      percentage of true anomalies that are detected successfully.
  
      When the input is anomaly labels, metric calculation treats every time
      point with positive label as an independent event. An anomalous time point
      that are detected as anomalous is considered as a successful detection.
  
      When the input is lists of anomalous time windows, metric calculation
      treats every anomalous time window as an independent event. A true event is
      considered as successfully detected if the percentage of this time window
      covered by the detected list is greater or equal to `thresh`. Note that
      input time windows will be merged first if overlapped time windows exists
      in the list.
  
      Parameters
      ----------
      y_true: pandas Series or DataFrame, list, or dict
          Labels or lists of true anomalies.
  
          - If pandas Series, it is treated as binary labels along time index.
          - If pandas DataFrame, each column is a binary series and is treated as
            an independent type of anomaly.
          - If list, a list of events where an event is a pandas Timestamp if it
            is instantaneous or a 2-tuple of pandas Timestamps if it is a closed
            time interval.
          - If dict, each key-value pair is a list of events and is treated as an
            independent type of anomaly.
  
      y_pred: pandas Series or DataFrame, list, or dict
          Labels or lists of predicted anomalies.
  
          - If pandas Series, it is treated as binary labels along time index.
          - If pandas DataFrame, each column is a binary series and is treated as
            an independent type of anomaly.
          - If list, a list of events where an event is a pandas Timestamp if it
            is instantaneous or a 2-tuple of pandas Timestamps if it is a closed
            time interval.
          - If dict, each key-value pair is a list of events and is treated as an
            independent type of anomaly.
  
      thresh: float, optional
          Threshold of a hit. Only used if input is list or dict. Default: 0.5.
  
      Returns
      -------
      float or dict
          Score(s) for each type of anomaly.
  
      """
      if (thresh <= 0) or (thresh > 1):
          raise ValueError(
              "Parameter `thresh` must be a positive number less or equal to 1."
          )
      if type(y_true) != type(y_pred):
          raise TypeError("y_true and y_pred must have same type.")
  
      if isinstance(y_true, pd.Series) and isinstance(
          y_pred, pd.Series
      ):
          try:
              pd.testing.assert_index_equal(y_true.index, y_pred.index)
          except AssertionError:
              raise ValueError(
                  "y_true and y_pred must have identical index"
              )
          if y_true.clip(0, 1).round().sum() != 0:
              return (
                  y_true.clip(0, 1).round() * y_pred.clip(0, 1).round()
              ).sum() / (y_true.clip(0, 1).round()).sum()
          else:
              return float("nan")
      elif isinstance(y_true, pd.DataFrame) and isinstance(
          y_pred, pd.DataFrame
      ):
          if set(y_true.columns) != set(y_pred.columns):
              raise ValueError(
                  "y_true and y_pred must have identical columns."
              )
          return {
              col: recall(y_true[col], y_pred[col])
              for col in y_true.columns
          }
      elif isinstance(y_true, list) and isinstance(y_pred, list):
          y_true = validate_events(y_true)
          if not y_true:
              return float("nan")
          y_int = AndAggregator().aggregate(
              {"y_true": y_true, "y_pred": y_pred}
          )
          n_hit = 0
          for w_true in y_true:
              if isinstance(w_true, tuple):
                  true_start = w_true[0]
                  true_end = w_true[1]
              else:
                  true_start = w_true
                  true_end = w_true
              len_w_true = true_end - true_start
              if len_w_true > pd.Timedelta(0):
                  len_overlap = pd.Timedelta(0)
                  for w_int in y_int:
                      if isinstance(w_int, tuple):
                          int_start = w_int[0]
                          int_end = w_int[1]
                      else:
                          int_start = w_int
                          int_end = w_int
                      len_overlap += max(
                          pd.Timedelta(0),
                          min(true_end, int_end)
                          - max(true_start, int_start),
                      )
                  if len_overlap >= thresh * len_w_true:
                      n_hit += 1
              else:
                  for w_int in y_int:
                      if isinstance(w_int, tuple):
                          int_start = w_int[0]
                          int_end = w_int[1]
                      else:
                          int_start = w_int
                          int_end = w_int
                      if (int_start <= true_start) and (
                          int_end >= true_end
                      ):
                          n_hit += 1
                          break
          return n_hit / len(y_true)
      elif isinstance(y_true, dict) and isinstance(y_pred, dict):
          return {
              key: recall(y_true[key], y_pred[key], thresh=thresh)
              for key in y_true.keys()
          }
      else:
          raise TypeError(
              "y_true and y_pred must be pandas Series or DataFrame, list, or a "
              "dict of lists"
          )
  
imports: from typing import Dict, List, Tuple, Union, overload
  import pandas
  from ..aggregator import AndAggregator, OrAggregator
  from ..data import validate_events
label_desc: Use image node_id 5 for calling a global function with example usage: recall(y_true, y_pred, thresh) and returns: unknown, float, unknown, unknown, float, unknown