code: def plot_cv(
      data: pd.Series,
      cv: Union[ExpandingWindowSplitter, SlidingWindowSplitter],
      fig_defaults: Dict[str, Any],
      fig_kwargs: Optional[Dict] = None,
  ) -> PlotReturnType:
      """Plots the cv splits used on the training split
  
      Parameters
      ----------
      data : pd.Series
          The target time series
      cv : Union[ExpandingWindowSplitter, SlidingWindowSplitter]
          The sktime compatible cross validation object to use for the plot
      fig_defaults : Dict[str, Any]
          The default settings for the plotly plot. Must contain keys for "width",
          "height", and "template".
      fig_kwargs : Optional[Dict], optional
          Specific overrides by the user for the plotly figure settings,
          by default None. Can contain keys for "width", "height" and/or "template".
  
      Returns
      -------
      PlotReturnType
          The plotly figure object along with a dictionary with the plot data.
          The data can be returned to the user (if requested) so that the plot can
          be and customized by them if not supported by pycaret by default.
      """
      fig_kwargs = fig_kwargs or {}
  
      def get_windows(y, cv):
          """
          Generate windows
          Inspired from `https://github.com/sktime/sktime`
          """
          train_windows = []
          test_windows = []
          for i, (train, test) in enumerate(cv.split(y)):
              train_windows.append(train)
              test_windows.append(test)
          return train_windows, test_windows
  
      def plot_windows(data, train_windows, test_windows):
          fig = go.Figure()
          for num_window in reversed(range(len(train_windows))):
              x = (
                  data.index.to_timestamp()
                  if isinstance(data.index, pd.PeriodIndex)
                  else data.index
              )
              time_stamps = x
  
              y_axis_label = str(num_window)
              [
                  fig.add_trace(
                      go.Scattergl(
                          x=(time_stamps[i], time_stamps[i + 1]),
                          y=(y_axis_label, y_axis_label),
                          mode="lines+markers",
                          line_color="#C0C0C0",
                          name="Unchanged",
                          hoverinfo="skip",
                      ),
                  )
                  for i in range(len(data) - 1)
              ]
              [
                  fig.add_trace(
                      go.Scattergl(
                          x=(time_stamps[i], time_stamps[i + 1]),
                          y=(y_axis_label, y_axis_label),
                          mode="lines+markers",
                          line_color="#1f77b4",
                          name="Train",
                          showlegend=False,
                          hoverinfo="skip",
                      ),
                  )
                  for i in train_windows[num_window][:-1]
              ]
              [
                  fig.add_trace(
                      go.Scattergl(
                          x=(time_stamps[i], time_stamps[i + 1]),
                          y=(y_axis_label, y_axis_label),
                          mode="lines+markers",
                          line_color="#DE970B",
                          name="ForecastHorizon",
                          hoverinfo="skip",
                      ),
                  )
                  for i in test_windows[num_window][:-1]
              ]
  
              with fig.batch_update():
                  fig.update_traces(showlegend=False)
  
                  fig.update_layout(
                      {
                          "title": "Train Cross-Validation Splits",
                          "xaxis": {"title": "Time", "zeroline": False},
                          "yaxis": {"title": "Windows"},
                          "showlegend": True,
                      }
                  )
                  template = _resolve_dict_keys(
                      dict_=fig_kwargs,
                      key="template",
                      defaults=fig_defaults,
                  )
                  fig.update_layout(template=template)
  
                  fig = _update_fig_dimensions(
                      fig=fig,
                      fig_kwargs=fig_kwargs,
                      fig_defaults=fig_defaults,
                  )
          return fig
  
      train_windows, test_windows = get_windows(data, cv)
      fig = plot_windows(data, train_windows, test_windows)
      return_data_dict = {
          "data": data,
          "train_windows": train_windows,
          "test_windows": test_windows,
      }
  
      return fig, return_data_dict
  
file_path: pycaret/pycaret/internal/plots/time_series.py
imports: from typing import Any, Dict, List, Optional, Union
  import numpy
  import pandas
  import plotly.graph_objects
  from plotly.subplots import make_subplots
  from sktime.forecasting.model_selection import ExpandingWindowSplitter, SlidingWindowSplitter
  from pycaret.internal.plots.utils.time_series import PlotReturnType, _clean_model_results_labels, _get_subplot_rows_cols, _plot_fig_update, _resolve_hoverinfo, _update_fig_dimensions, corr_subplot, decomp_subplot, dist_subplot, frequency_components_subplot, plot_original_with_overlays, qq_subplot, time_series_subplot
  from pycaret.utils.generic import _resolve_dict_keys
  from pycaret.utils.time_series import get_diffs
label_desc: Use image node_id 3 for calling a global function with example usage: plot_cv(data, cv, fig_defaults, fig_kwargs) and returns: fig,  return_data_dict, train_windows,  test_windows, fig