class_docstr: A Pipenet object connects transformers, detectors and aggregators.
  
  Parameters
  ----------
  steps: dicts
      Components of the pipenet. Each key-value item represents a step (
      transformer, detector, or aggregator), where key is the unique name of
      the step and the value is a dict with the following key-value pairs:
  
          - input (str or list of str): Input to the model, which must be
            either 'original' (i.e. the input time series), or the name of
            a upstream component.
          - subset (str, list of str, or list of lists of str, optional): If
            a model does not use all series from an input component, use this
            field to specify which series should be included. If not given or
            "all", all series from the input component will be used.
          - model (object): A detector, transformer, or aggregator object.
  
  Attributes
  ----------
  steps_graph_: OrderedDict
      Order of steps to be executed. Keys are step names, values are 2-tuple
      (i, j) where i is the index of execution round and j is the the index
      within a round.
  
  final_step_: str
      Name of the final step to be executed. It is the single step in the
      last round of execution in attribute `steps_graph_`.
  
  Examples
  --------
  The following example show how to use a Pipenet to build a level shift
  detector with some basic transformers, detectors, and aggregator.
  
  >>> from adtk.detector import QuantileAD, ThresholdAD
  >>> from adtk.transformer import DoubleRollingAggregate
  >>> from adtk.aggregator import AndAggregator
  >>> from adtk.pipe import Pipenet
  >>> steps = {
          "diff_abs": {
              "input": "original",
              "model": DoubleRollingAggregate(
                  agg="median",
                  window=20,
                  center=True,
                  diff="l1",
              ),
          },
          "quantile_ad": {
              "input": "diff_abs",
              "model": QuantileAD(high=0.99, low=0),
          },
          "diff": {
              "input": "original",
              "model": DoubleRollingAggregate(
                  agg="median",
                  window=20,
                  center=True,
                  diff="diff",
              ),
          },
          "sign_check": {
              "input": "diff",
              "model": ThresholdAD(high=0.0, low=-float("inf")),
          },
          "and": {
              "model": AndAggregator(),
              "input": ["quantile_ad", "sign_check"],
          },
      }
  >>> myPipenet = Pipenet(steps)
docstr: Train models in the pipenet and detect anomaly with it.
  
  Parameters
  ----------
  ts: pandas Series or DataFrame
      Time series to detect anomalies from.
  
  skip_fit: list, optional
      Models to skip training. This could be used when pipenet contains
      models that are already trained by the same time series, and re-
      training would be time consuming. It must be a list of strings
      where each element is a model name. Default: None.
  
  return_intermediate: bool, optional
      Whether to return intermediate results. Default: False.
  
  return_list: bool, optional
      Whether to return a list of anomalous events, or a binary series
      indicating normal/anomalous. Default: False.
  
  Returns
  -------
  pandas Series, pandas DataFrame, list, or dict
      Detected anomalies.
  
      - If return_intermediate=False, return detected anomalies, i.e.
        result from last detector.
      - If return_intermediate=True, return results of all models in
        pipenet as a dict where each item represents the result of a
        model.
      - If return_list=False, result from a detector or an aggregator
        will be a binary pandas Series indicating normal/anomalous.
      - If return_list=True, result from a detector or an aggregator
        will be 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.
docstr_tok: ["Train","models","in","the","pipenet","and","detect","anomaly","with","it",".","Parameters","--","--","--","--","--","ts",":","pandas","Series","or","DataFrame","Time","series","to","detect","anomalies","from",".","skip_fit",":","list",",","optional","Models","to","skip","training",".","This","could","be","used","when","pipenet","contains","models","that","are","already","trained","by","the","same","time","series",",","and","re-","training","would","be","time","consuming",".","It","must","be","a","list","of","strings","where","each","element","is","a","model","name",".","Default",":","None",".","return_intermediate",":","bool",",","optional","Whether","to","return","intermediate","results",".","Default",":","False",".","return_list",":","bool",",","optional","Whether","to","return","a","list","of","anomalous","events",",","or","a","binary","series","indicating","normal\/anomalous",".","Default",":","False",".","Returns","--","--","--","-","pandas","Series",",","pandas","DataFrame",",","list",",","or","dict","Detected","anomalies",".","-","If","return_intermediate=False",",","return","detected","anomalies",",","i.e",".","result","from","last","detector",".","-","If","return_intermediate=True",",","return","results","of","all","models","in","pipenet","as","a","dict","where","each","item","represents","the","result","of","a","model",".","-","If","return_list=False",",","result","from","a","detector","or","an","aggregator","will","be","a","binary","pandas","Series","indicating","normal\/anomalous",".","-","If","return_list=True",",","result","from","a","detector","or","an","aggregator","will","be","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","."]
code: def fit_detect(
      self,
      ts: Union[pd.Series, pd.DataFrame],
      skip_fit: Optional[List[str]] = None,
      return_intermediate: bool = False,
      return_list: bool = False,
  ) -> Union[
      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]
              ],
          ],
      ],
      Dict[
          str,
          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,
                      ]
                  ],
              ],
          ],
      ],
  ]:
      """Train models in the pipenet and detect anomaly with it.
  
      Parameters
      ----------
      ts: pandas Series or DataFrame
          Time series to detect anomalies from.
  
      skip_fit: list, optional
          Models to skip training. This could be used when pipenet contains
          models that are already trained by the same time series, and re-
          training would be time consuming. It must be a list of strings
          where each element is a model name. Default: None.
  
      return_intermediate: bool, optional
          Whether to return intermediate results. Default: False.
  
      return_list: bool, optional
          Whether to return a list of anomalous events, or a binary series
          indicating normal/anomalous. Default: False.
  
      Returns
      -------
      pandas Series, pandas DataFrame, list, or dict
          Detected anomalies.
  
          - If return_intermediate=False, return detected anomalies, i.e.
            result from last detector.
          - If return_intermediate=True, return results of all models in
            pipenet as a dict where each item represents the result of a
            model.
          - If return_list=False, result from a detector or an aggregator
            will be a binary pandas Series indicating normal/anomalous.
          - If return_list=True, result from a detector or an aggregator
            will be 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.
  
      """
      return self._predict(
          ts,
          fit=True,
          detect=True,
          skip_fit=skip_fit,
          return_intermediate=return_intermediate,
          return_list=return_list,
      )
  
imports: from collections import OrderedDict
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import matplotlib.pyplot
  import pandas
  from matplotlib.collections import PatchCollection
  from matplotlib.lines import Line2D
  from matplotlib.patches import Circle
  from tabulate import tabulate
  from .._aggregator_base import _Aggregator
  from .._base import _Model, _TrainableModel
  from .._detector_base import _NonTrainableUnivariateDetector, _TrainableMultivariateDetector, _TrainableUnivariateDetector
  from .._transformer_base import _NonTrainableMultivariateTransformer, _NonTrainableUnivariateTransformer, _TrainableMultivariateTransformer, _TrainableUnivariateTransformer
  from ..metrics import f1_score, iou, precision, recall
label_desc: Use image node_id 8 for calling the Pipenet obj's underlying member method code with example usage: obj.fit_detect(ts, skip_fit, return_intermediate, return_list) and returns: self