code: def __next__(self):
      from time import perf_counter
  
      start_time_read_data = perf_counter()
  
      # Load the next set of sampling results if necessary
      if self.__next_batch >= self.__end_exclusive:
          if self.__directory is None:
              raise StopIteration
  
          # Read the next parquet file into memory
          dir_path = (
              self.__directory
              if isinstance(self.__directory, str)
              else self.__directory.name
          )
  
          # Will raise StopIteration if there are no files left
          try:
              fname = next(self.__input_files)
          except StopIteration as ex:
              # Won't delete a non-temp dir (since it would just be deleting a string)
              del self.__directory
              self.__directory = None
              raise StopIteration(ex)
  
          m = self.__ex_parquet_file.match(fname)
          if m is None:
              raise ValueError(f"Invalid parquet filename {fname}")
  
          self.__start_inclusive, end_inclusive = [
              int(g) for g in m.groups()
          ]
          self.__next_batch = self.__start_inclusive
          self.__end_exclusive = end_inclusive + 1
  
          parquet_path = os.path.join(
              dir_path,
              fname,
          )
  
          raw_sample_data = cudf.read_parquet(parquet_path)
  
          if "map" in raw_sample_data.columns:
              if "renumber_map_offsets" not in raw_sample_data.columns:
                  num_batches = (
                      end_inclusive - self.__start_inclusive + 1
                  )
  
                  map_end = raw_sample_data["map"].iloc[num_batches]
  
                  map = torch.as_tensor(
                      raw_sample_data["map"].iloc[0:map_end],
                      device="cuda",
                  )
                  raw_sample_data.drop("map", axis=1, inplace=True)
  
                  self.__renumber_map_offsets = (
                      map[0 : num_batches + 1] - map[0]
                  )
                  self.__renumber_map = map[num_batches + 1 :]
              else:
                  self.__renumber_map = raw_sample_data["map"]
                  self.__renumber_map_offsets = raw_sample_data[
                      "renumber_map_offsets"
                  ]
                  raw_sample_data.drop(
                      columns=["map", "renumber_map_offsets"],
                      inplace=True,
                  )
  
                  self.__renumber_map.dropna(inplace=True)
                  self.__renumber_map = torch.as_tensor(
                      self.__renumber_map, device="cuda"
                  )
  
                  self.__renumber_map_offsets.dropna(inplace=True)
                  self.__renumber_map_offsets = torch.as_tensor(
                      self.__renumber_map_offsets, device="cuda"
                  )
  
          else:
              self.__renumber_map = None
  
          self.__data = raw_sample_data
          self.__coo = "majors" in self.__data.columns
          if self.__coo:
              self.__data.dropna(inplace=True)
  
          if (
              len(self.__graph_store.edge_types) == 1
              and len(self.__graph_store.node_types) == 1
          ):
              if self.__coo:
                  group_cols = ["batch_id", "hop_id"]
                  self.__data_index = self.__data.groupby(
                      group_cols, as_index=True
                  ).agg({"majors": "max", "minors": "max"})
                  self.__data_index.rename(
                      columns={
                          "majors": "src_max",
                          "minors": "dst_max",
                      },
                      inplace=True,
                  )
                  self.__data_index = self.__data_index.to_dict(
                      orient="index"
                  )
              else:
                  self.__data_index = None
  
                  self.__label_hop_offsets = self.__data[
                      "label_hop_offsets"
                  ]
                  self.__data.drop(
                      columns=["label_hop_offsets"], inplace=True
                  )
                  self.__label_hop_offsets.dropna(inplace=True)
                  self.__label_hop_offsets = torch.as_tensor(
                      self.__label_hop_offsets, device="cuda"
                  )
                  self.__label_hop_offsets -= self.__label_hop_offsets[
                      0
                  ].clone()
  
                  self.__major_offsets = self.__data["major_offsets"]
                  self.__data.drop(
                      columns="major_offsets", inplace=True
                  )
                  self.__major_offsets.dropna(inplace=True)
                  self.__major_offsets = torch.as_tensor(
                      self.__major_offsets, device="cuda"
                  )
                  self.__major_offsets -= self.__major_offsets[
                      0
                  ].clone()
  
                  self.__minors = self.__data["minors"]
                  self.__data.drop(columns="minors", inplace=True)
                  self.__minors.dropna(inplace=True)
                  self.__minors = torch.as_tensor(
                      self.__minors, device="cuda"
                  )
  
                  num_batches = (
                      self.__end_exclusive - self.__start_inclusive
                  )
                  offsets_len = len(self.__label_hop_offsets) - 1
                  if offsets_len % num_batches != 0:
                      raise ValueError("invalid label-hop offsets")
                  self.__fanout_length = int(offsets_len / num_batches)
  
      end_time_read_data = perf_counter()
      self._total_read_time += end_time_read_data - start_time_read_data
  
      # Pull the next set of sampling results out of the dataframe in memory
      if self.__coo:
          f = self.__data["batch_id"] == self.__next_batch
      if self.__renumber_map is not None:
          i = self.__next_batch - self.__start_inclusive
  
          # this should avoid d2h copy
          current_renumber_map = self.__renumber_map[
              self.__renumber_map_offsets[
                  i
              ] : self.__renumber_map_offsets[i + 1]
          ]
  
      else:
          current_renumber_map = None
  
      start_time_convert = perf_counter()
      # Get and return the sampled subgraph
      if (
          len(self.__graph_store.edge_types) == 1
          and len(self.__graph_store.node_types) == 1
      ):
          if self.__coo:
              sampler_output = (
                  _sampler_output_from_sampling_results_homogeneous_coo(
                      self.__data[f],
                      current_renumber_map,
                      self.__graph_store,
                      self.__data_index,
                      self.__next_batch,
                  )
              )
          else:
              i = (
                  self.__next_batch - self.__start_inclusive
              ) * self.__fanout_length
              current_label_hop_offsets = self.__label_hop_offsets[
                  i : i + self.__fanout_length + 1
              ]
  
              current_major_offsets = self.__major_offsets[
                  current_label_hop_offsets[0] : (
                      current_label_hop_offsets[-1] + 1
                  )
              ]
  
              current_minors = self.__minors[
                  current_major_offsets[0] : current_major_offsets[-1]
              ]
  
              sampler_output = (
                  _sampler_output_from_sampling_results_homogeneous_csr(
                      current_major_offsets,
                      current_minors,
                      current_renumber_map,
                      self.__graph_store,
                      current_label_hop_offsets,
                      self.__data_index,
                      self.__next_batch,
                  )
              )
      else:
          sampler_output = (
              _sampler_output_from_sampling_results_heterogeneous(
                  self.__data[f],
                  current_renumber_map,
                  self.__graph_store,
              )
          )
  
      # Get ready for next iteration
      self.__next_batch += 1
  
      end_time_convert = perf_counter()
      self._total_convert_time += end_time_convert - start_time_convert
  
      start_time_feature = perf_counter()
      # Create a PyG HeteroData object, loading the required features
      if self.__coo:
          pyg_filter_fn = (
              torch_geometric.loader.utils.filter_custom_hetero_store
              if hasattr(
                  torch_geometric.loader.utils,
                  "filter_custom_hetero_store",
              )
              else torch_geometric.loader.utils.filter_custom_store
          )
          out = pyg_filter_fn(
              self.__feature_store,
              self.__graph_store,
              sampler_output.node,
              sampler_output.row,
              sampler_output.col,
              sampler_output.edge,
          )
      else:
          out = filter_cugraph_store_csc(
              self.__feature_store,
              self.__graph_store,
              sampler_output.node,
              sampler_output.row,
              sampler_output.col,
              sampler_output.edge,
          )
  
      # Account for CSR format in cuGraph vs. CSC format in PyG
      if self.__coo and self.__graph_store.order == "CSC":
          for edge_type in out.edge_index_dict:
              out[edge_type].edge_index = out[
                  edge_type
              ].edge_index.flip(dims=[0])
  
      out.set_value_dict(
          "num_sampled_nodes", sampler_output.num_sampled_nodes
      )
      out.set_value_dict(
          "num_sampled_edges", sampler_output.num_sampled_edges
      )
  
      end_time_feature = perf_counter()
      self._total_feature_time = end_time_feature - start_time_feature
  
      return out
  
file_path: cugraph/python/cugraph-pyg/cugraph_pyg/loader/cugraph_node_loader.py
imports: import tempfile
  import os
  import re
  import warnings
  import cupy
  import cudf
  from cugraph.gnn import BulkSampler
  from cugraph.utilities.utils import import_optional, MissingModule
  from cugraph_pyg.data import CuGraphStore
  from cugraph_pyg.sampler.cugraph_sampler import _sampler_output_from_sampling_results_heterogeneous, _sampler_output_from_sampling_results_homogeneous_csr, _sampler_output_from_sampling_results_homogeneous_coo, filter_cugraph_store_csc
  from typing import Union, Tuple, Sequence, List, Dict
label_desc: Use image node_id 2 for calling the BulkSampleLoader obj's underlying member method code with example usage: obj.__next__() and returns: out