class_docstr: Action forecasting video data set for EpicKitchen-55 Dataset.
  <https://epic-kitchens.github.io/2019/>
  
  This dataset handles the loading, decoding, and clip sampling for the videos.
class_docstr_tok: ["Action","forecasting","video","data","set","for","EpicKitchen-55","Dataset",".","<","https",":","\/\/epic-kitchens.github.io\/2019\/",">","This","dataset","handles","the","loading",",","decoding",",","and","clip","sampling","for","the","videos","."]
docstr: Args:
      clip_sampling (ClipSampling):
          The type of sampling to perform to perform on the videos of the dataset.
      seconds_per_clip (float): The length of each sampled clip in seconds.
      clip_time_stride: The time difference in seconds between the start of
          each input subclip.
      num_input_clips (int):  The number of subclips to be included in the video data.
      num_forecast_actions (int): The number of actions to be included in the
          action vector.
  
  Returns:
      A function that takes a dictionary of videos and outputs a list of sampled
      clips.
docstr_tok: ["Args",":","clip_sampling","(","ClipSampling",")",":","The","type","of","sampling","to","perform","to","perform","on","the","videos","of","the","dataset",".","seconds_per_clip","(","float",")",":","The","length","of","each","sampled","clip","in","seconds",".","clip_time_stride",":","The","time","difference","in","seconds","between","the","start","of","each","input","subclip",".","num_input_clips","(","int",")",":","The","number","of","subclips","to","be","included","in","the","video","data",".","num_forecast_actions","(","int",")",":","The","number","of","actions","to","be","included","in","the","action","vector",".","Returns",":","A","function","that","takes","a","dictionary","of","videos","and","outputs","a","list","of","sampled","clips","."]
code: def _define_clip_structure_generator(
      clip_sampling: str,
      seconds_per_clip: float,
      clip_time_stride: float,
      num_input_clips: int,
      num_forecast_actions: int,
  ) -> Callable[
      [Dict[str, Video], Dict[str, List[ActionData]]],
      List[VideoClipInfo],
  ]:
      """
      Args:
          clip_sampling (ClipSampling):
              The type of sampling to perform to perform on the videos of the dataset.
          seconds_per_clip (float): The length of each sampled clip in seconds.
          clip_time_stride: The time difference in seconds between the start of
              each input subclip.
          num_input_clips (int):  The number of subclips to be included in the video data.
          num_forecast_actions (int): The number of actions to be included in the
              action vector.
  
      Returns:
          A function that takes a dictionary of videos and outputs a list of sampled
          clips.
      """
      # TODO(T77683480)
      if not clip_sampling == ClipSampling.Random:
          raise NotImplementedError(
              f"Only {ClipSampling.Random} is implemented. "
              f"{clip_sampling} not implemented."
          )
  
      time_window_length = (
          seconds_per_clip + (num_input_clips - 1) * clip_time_stride
      )
  
      def define_clip_structure(
          videos: Dict[str, Video],
          video_actions: Dict[str, List[ActionData]],
      ) -> List[VideoClipInfo]:
          candidate_sample_clips = []
          for video_id, actions in video_actions.items():
              for i, action in enumerate(
                  actions[: (-1 * num_forecast_actions)]
              ):
                  # Only actions with num_forecast_actions after to predict
                  # Confirm there are >= num_forecast_actions available
                  # (it is possible for actions to overlap)
                  number_valid_actions = 0
                  for j in range(i + 1, len(actions)):
                      if actions[j].start_time > action.stop_time:
                          number_valid_actions += 1
                      if number_valid_actions == num_forecast_actions:
                          if (
                              action.start_time - time_window_length
                              >= 0
                          ):  # Only add clips that have the full input video available
                              candidate_sample_clips.append(
                                  VideoClipInfo(
                                      video_id,
                                      action.stop_time
                                      - time_window_length,
                                      action.stop_time,
                                  )
                              )
                          break
          return candidate_sample_clips
  
      return define_clip_structure
  
file_path: pytorchvideo/pytorchvideo/data/epic_kitchen_forecasting.py
imports: from dataclasses import fields
  from enum import Enum
  from typing import Any, Callable, Dict, List, Optional
  import torch
  from pytorchvideo.data.dataset_manifest_utils import EncodedVideoInfo, VideoClipInfo, VideoDatasetType, VideoFrameInfo, VideoInfo
  from pytorchvideo.data.epic_kitchen import ActionData, EpicKitchenDataset
  from pytorchvideo.data.video import Video
label_desc: Use image node_id 4 for calling the EpicKitchenForecasting obj's underlying member method code with example usage: obj._define_clip_structure_generator(clip_sampling, seconds_per_clip, clip_time_stride, num_input_clips, num_forecast_actions) and returns: define_clip_structure, candidate_sample_clips